(index<- )        ./libnum/lib.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri Apr 25 22:40:04 2014
   1  // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  #![feature(macro_rules)]
  12  
  13  #![crate_id = "num#0.11-pre"]
  14  #![crate_type = "rlib"]
  15  #![crate_type = "dylib"]
  16  #![license = "MIT/ASL2"]
  17  #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
  18         html_favicon_url = "http://www.rust-lang.org/favicon.ico",
  19         html_root_url = "http://static.rust-lang.org/doc/master")]
  20  
  21  #![deny(deprecated_owned_vector)]
  22  
  23  extern crate rand;
  24  
  25  pub mod bigint;
  26  pub mod rational;
  27  pub mod complex;
  28  
  29  pub trait Integer: Num + Ord
  30                   + Div<Self, Self>
  31                   + Rem<Self, Self> {
  32      /// Simultaneous truncated integer division and modulus
  33      #[inline]
  34      fn div_rem(&self, other&Self) -> (Self, Self) {
  35          (*self / *other, *self % *other)
  36      }
  37  
  38      /// Floored integer division
  39      ///
  40      /// # Examples
  41      ///
  42      /// ~~~
  43      /// # use num::Integer;
  44      /// assert!(( 8i).div_floor(& 3) ==  2);
  45      /// assert!(( 8i).div_floor(&-3) == -3);
  46      /// assert!((-8i).div_floor(& 3) == -3);
  47      /// assert!((-8i).div_floor(&-3) ==  2);
  48      ///
  49      /// assert!(( 1i).div_floor(& 2) ==  0);
  50      /// assert!(( 1i).div_floor(&-2) == -1);
  51      /// assert!((-1i).div_floor(& 2) == -1);
  52      /// assert!((-1i).div_floor(&-2) ==  0);
  53      /// ~~~
  54      fn div_floor(&self, other: &Self) -> Self;
  55  
  56      /// Floored integer modulo, satisfying:
  57      ///
  58      /// ~~~
  59      /// # use num::Integer;
  60      /// # let n = 1i; let d = 1i;
  61      /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
  62      /// ~~~
  63      ///
  64      /// # Examples
  65      ///
  66      /// ~~~
  67      /// # use num::Integer;
  68      /// assert!(( 8i).mod_floor(& 3) ==  2);
  69      /// assert!(( 8i).mod_floor(&-3) == -1);
  70      /// assert!((-8i).mod_floor(& 3) ==  1);
  71      /// assert!((-8i).mod_floor(&-3) == -2);
  72      ///
  73      /// assert!(( 1i).mod_floor(& 2) ==  1);
  74      /// assert!(( 1i).mod_floor(&-2) == -1);
  75      /// assert!((-1i).mod_floor(& 2) ==  1);
  76      /// assert!((-1i).mod_floor(&-2) == -1);
  77      /// ~~~
  78      fn mod_floor(&self, other: &Self) -> Self;
  79  
  80      /// Simultaneous floored integer division and modulus
  81      fn div_mod_floor(&self, other&Self) -> (Self, Self) {
  82          (self.div_floor(other), self.mod_floor(other))
  83      }
  84  
  85      /// Greatest Common Divisor (GCD)
  86      fn gcd(&self, other: &Self) -> Self;
  87  
  88      /// Lowest Common Multiple (LCM)
  89      fn lcm(&self, other: &Self) -> Self;
  90  
  91      /// Returns `true` if `other` divides evenly into `self`
  92      fn divides(&self, other: &Self) -> bool;
  93  
  94      /// Returns `true` if the number is even
  95      fn is_even(&self) -> bool;
  96  
  97      /// Returns `true` if the number is odd
  98      fn is_odd(&self) -> bool;
  99  }
 100  
 101  /// Simultaneous integer division and modulus
 102  #[inline] pub fn div_rem<T: Integer>(xT, yT) -> (T, T) { x.div_rem(&y) }
 103  /// Floored integer division
 104  #[inline] pub fn div_floor<T: Integer>(xT, yT) -> T { x.div_floor(&y) }
 105  /// Floored integer modulus
 106  #[inline] pub fn mod_floor<T: Integer>(xT, yT) -> T { x.mod_floor(&y) }
 107  /// Simultaneous floored integer division and modulus
 108  #[inline] pub fn div_mod_floor<T: Integer>(xT, yT) -> (T, T) { x.div_mod_floor(&y) }
 109  
 110  /// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
 111  /// result is always positive.
 112  #[inline(always)] pub fn gcd<T: Integer>(xT, yT) -> T { x.gcd(&y) }
 113  /// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
 114  #[inline(always)] pub fn lcm<T: Integer>(xT, yT) -> T { x.lcm(&y) }
 115  
 116  macro_rules! impl_integer_for_int {
 117      ($T:ty, $test_mod:ident) => (
 118          impl Integer for $T {
 119              /// Floored integer division
 120              #[inline]
 121              fn div_floor(&self, other&$T) -> $T {
 122                  // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
 123                  // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
 124                  match self.div_rem(other) {
 125                      (d, r) if (r > 0 && *other < 0)
 126                             || (r < 0 && *other > 0) => d - 1,
 127                      (d, _)                          => d,
 128                  }
 129              }
 130  
 131              /// Floored integer modulo
 132              #[inline]
 133              fn mod_floor(&self, other&$T) -> $T {
 134                  // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
 135                  // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
 136                  match *self % *other {
 137                      r if (r > 0 && *other < 0)
 138                        || (r < 0 && *other > 0) => r + *other,
 139                      r                          => r,
 140                  }
 141              }
 142  
 143              /// Calculates `div_floor` and `mod_floor` simultaneously
 144              #[inline]
 145              fn div_mod_floor(&self, other&$T) -> ($T,$T) {
 146                  // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
 147                  // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
 148                  match self.div_rem(other) {
 149                      (d, r) if (r > 0 && *other < 0)
 150                             || (r < 0 && *other > 0) => (d - 1, r + *other),
 151                      (d, r)                          => (d, r),
 152                  }
 153              }
 154  
 155              /// Calculates the Greatest Common Divisor (GCD) of the number and
 156              /// `other`. The result is always positive.
 157              #[inline]
 158              fn gcd(&self, other&$T) -> $T {
 159                  // Use Euclid's algorithm
 160                  let mut m = *self;
 161                  let mut n = *other;
 162                  while m != 0 {
 163                      let temp = m;
 164                      m = n % temp;
 165                      n = temp;
 166                  }
 167                  n.abs()
 168              }
 169  
 170              /// Calculates the Lowest Common Multiple (LCM) of the number and
 171              /// `other`.
 172              #[inline]
 173              fn lcm(&self, other&$T) -> $T {
 174                  // should not have to recalculate abs
 175                  ((*self * *other) / self.gcd(other)).abs()
 176              }
 177  
 178              /// Returns `true` if the number can be divided by `other` without
 179              /// leaving a remainder
 180              #[inline]
 181              fn divides(&self, other&$T) -> bool { *self % *other == 0 }
 182  
 183              /// Returns `true` if the number is divisible by `2`
 184              #[inline]
 185              fn is_even(&self) -> bool { self & 1 == 0 }
 186  
 187              /// Returns `true` if the number is not divisible by `2`
 188              #[inline]
 189              fn is_odd(&self) -> bool { !self.is_even() }
 190          }
 191  
 192          #[cfg(test)]
 193          mod $test_mod {
 194              use Integer;
 195  
 196              /// Checks that the division rule holds for:
 197              ///
 198              /// - `n`: numerator (dividend)
 199              /// - `d`: denominator (divisor)
 200              /// - `qr`: quotient and remainder
 201              #[cfg(test)]
 202              fn test_division_rule((n,d)($T,$T), (q,r)($T,$T)) {
 203                  assert_eq!(d * q + r, n);
 204              }
 205  
 206              #[test]
 207              fn test_div_rem() {
 208                  fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
 209                      let (n,d) = nd;
 210                      let separate_div_rem = (n / d, n % d);
 211                      let combined_div_rem = n.div_rem(&d);
 212  
 213                      assert_eq!(separate_div_rem, qr);
 214                      assert_eq!(combined_div_rem, qr);
 215  
 216                      test_division_rule(nd, separate_div_rem);
 217                      test_division_rule(nd, combined_div_rem);
 218                  }
 219  
 220                  test_nd_dr(( 8,  3), ( 2,  2));
 221                  test_nd_dr(( 8, -3), (-2,  2));
 222                  test_nd_dr((-8,  3), (-2, -2));
 223                  test_nd_dr((-8, -3), ( 2, -2));
 224  
 225                  test_nd_dr(( 1,  2), ( 0,  1));
 226                  test_nd_dr(( 1, -2), ( 0,  1));
 227                  test_nd_dr((-1,  2), ( 0, -1));
 228                  test_nd_dr((-1, -2), ( 0, -1));
 229              }
 230  
 231              #[test]
 232              fn test_div_mod_floor() {
 233                  fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
 234                      let (n,d) = nd;
 235                      let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
 236                      let combined_div_mod_floor = n.div_mod_floor(&d);
 237  
 238                      assert_eq!(separate_div_mod_floor, dm);
 239                      assert_eq!(combined_div_mod_floor, dm);
 240  
 241                      test_division_rule(nd, separate_div_mod_floor);
 242                      test_division_rule(nd, combined_div_mod_floor);
 243                  }
 244  
 245                  test_nd_dm(( 8,  3), ( 2,  2));
 246                  test_nd_dm(( 8, -3), (-3, -1));
 247                  test_nd_dm((-8,  3), (-3,  1));
 248                  test_nd_dm((-8, -3), ( 2, -2));
 249  
 250                  test_nd_dm(( 1,  2), ( 0,  1));
 251                  test_nd_dm(( 1, -2), (-1, -1));
 252                  test_nd_dm((-1,  2), (-1,  1));
 253                  test_nd_dm((-1, -2), ( 0, -1));
 254              }
 255  
 256              #[test]
 257              fn test_gcd() {
 258                  assert_eq!((10 as $T).gcd(&2), 2 as $T);
 259                  assert_eq!((10 as $T).gcd(&3), 1 as $T);
 260                  assert_eq!((0 as $T).gcd(&3), 3 as $T);
 261                  assert_eq!((3 as $T).gcd(&3), 3 as $T);
 262                  assert_eq!((56 as $T).gcd(&42), 14 as $T);
 263                  assert_eq!((3 as $T).gcd(&-3), 3 as $T);
 264                  assert_eq!((-6 as $T).gcd(&3), 3 as $T);
 265                  assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
 266              }
 267  
 268              #[test]
 269              fn test_lcm() {
 270                  assert_eq!((1 as $T).lcm(&0), 0 as $T);
 271                  assert_eq!((0 as $T).lcm(&1), 0 as $T);
 272                  assert_eq!((1 as $T).lcm(&1), 1 as $T);
 273                  assert_eq!((-1 as $T).lcm(&1), 1 as $T);
 274                  assert_eq!((1 as $T).lcm(&-1), 1 as $T);
 275                  assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
 276                  assert_eq!((8 as $T).lcm(&9), 72 as $T);
 277                  assert_eq!((11 as $T).lcm(&5), 55 as $T);
 278              }
 279  
 280              #[test]
 281              fn test_even() {
 282                  assert_eq!((-4 as $T).is_even(), true);
 283                  assert_eq!((-3 as $T).is_even(), false);
 284                  assert_eq!((-2 as $T).is_even(), true);
 285                  assert_eq!((-1 as $T).is_even(), false);
 286                  assert_eq!((0 as $T).is_even(), true);
 287                  assert_eq!((1 as $T).is_even(), false);
 288                  assert_eq!((2 as $T).is_even(), true);
 289                  assert_eq!((3 as $T).is_even(), false);
 290                  assert_eq!((4 as $T).is_even(), true);
 291              }
 292  
 293              #[test]
 294              fn test_odd() {
 295                  assert_eq!((-4 as $T).is_odd(), false);
 296                  assert_eq!((-3 as $T).is_odd(), true);
 297                  assert_eq!((-2 as $T).is_odd(), false);
 298                  assert_eq!((-1 as $T).is_odd(), true);
 299                  assert_eq!((0 as $T).is_odd(), false);
 300                  assert_eq!((1 as $T).is_odd(), true);
 301                  assert_eq!((2 as $T).is_odd(), false);
 302                  assert_eq!((3 as $T).is_odd(), true);
 303                  assert_eq!((4 as $T).is_odd(), false);
 304              }
 305          }
 306      )
 307  }
 308  
 309  impl_integer_for_int!(i8,   test_integer_i8)
 310  impl_integer_for_int!(i16,  test_integer_i16)
 311  impl_integer_for_int!(i32,  test_integer_i32)
 312  impl_integer_for_int!(i64,  test_integer_i64)
 313  impl_integer_for_int!(int,  test_integer_int)
 314  
 315  macro_rules! impl_integer_for_uint {
 316      ($T:ty, $test_mod:ident) => (
 317          impl Integer for $T {
 318              /// Unsigned integer division. Returns the same result as `div` (`/`).
 319              #[inline]
 320              fn div_floor(&self, other&$T) -> $T { *self / *other }
 321  
 322              /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
 323              #[inline]
 324              fn mod_floor(&self, other&$T) -> $T { *self % *other }
 325  
 326              /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
 327              #[inline]
 328              fn gcd(&self, other&$T) -> $T {
 329                  // Use Euclid's algorithm
 330                  let mut m = *self;
 331                  let mut n = *other;
 332                  while m != 0 {
 333                      let temp = m;
 334                      m = n % temp;
 335                      n = temp;
 336                  }
 337                  n
 338              }
 339  
 340              /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
 341              #[inline]
 342              fn lcm(&self, other&$T) -> $T {
 343                  (*self * *other) / self.gcd(other)
 344              }
 345  
 346              /// Returns `true` if the number can be divided by `other` without leaving a remainder
 347              #[inline]
 348              fn divides(&self, other&$T) -> bool { *self % *other == 0 }
 349  
 350              /// Returns `true` if the number is divisible by `2`
 351              #[inline]
 352              fn is_even(&self) -> bool { self & 1 == 0 }
 353  
 354              /// Returns `true` if the number is not divisible by `2`
 355              #[inline]
 356              fn is_odd(&self) -> bool { !self.is_even() }
 357          }
 358  
 359          #[cfg(test)]
 360          mod $test_mod {
 361              use Integer;
 362  
 363              #[test]
 364              fn test_div_mod_floor() {
 365                  assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
 366                  assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
 367                  assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
 368                  assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
 369                  assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
 370                  assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
 371                  assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
 372                  assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
 373                  assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
 374              }
 375  
 376              #[test]
 377              fn test_gcd() {
 378                  assert_eq!((10 as $T).gcd(&2), 2 as $T);
 379                  assert_eq!((10 as $T).gcd(&3), 1 as $T);
 380                  assert_eq!((0 as $T).gcd(&3), 3 as $T);
 381                  assert_eq!((3 as $T).gcd(&3), 3 as $T);
 382                  assert_eq!((56 as $T).gcd(&42), 14 as $T);
 383              }
 384  
 385              #[test]
 386              fn test_lcm() {
 387                  assert_eq!((1 as $T).lcm(&0), 0 as $T);
 388                  assert_eq!((0 as $T).lcm(&1), 0 as $T);
 389                  assert_eq!((1 as $T).lcm(&1), 1 as $T);
 390                  assert_eq!((8 as $T).lcm(&9), 72 as $T);
 391                  assert_eq!((11 as $T).lcm(&5), 55 as $T);
 392                  assert_eq!((99 as $T).lcm(&17), 1683 as $T);
 393              }
 394  
 395              #[test]
 396              fn test_divides() {
 397                  assert!((6 as $T).divides(&(6 as $T)));
 398                  assert!((6 as $T).divides(&(3 as $T)));
 399                  assert!((6 as $T).divides(&(1 as $T)));
 400              }
 401  
 402              #[test]
 403              fn test_even() {
 404                  assert_eq!((0 as $T).is_even(), true);
 405                  assert_eq!((1 as $T).is_even(), false);
 406                  assert_eq!((2 as $T).is_even(), true);
 407                  assert_eq!((3 as $T).is_even(), false);
 408                  assert_eq!((4 as $T).is_even(), true);
 409              }
 410  
 411              #[test]
 412              fn test_odd() {
 413                  assert_eq!((0 as $T).is_odd(), false);
 414                  assert_eq!((1 as $T).is_odd(), true);
 415                  assert_eq!((2 as $T).is_odd(), false);
 416                  assert_eq!((3 as $T).is_odd(), true);
 417                  assert_eq!((4 as $T).is_odd(), false);
 418              }
 419          }
 420      )
 421  }
 422  
 423  impl_integer_for_uint!(u8,   test_integer_u8)
 424  impl_integer_for_uint!(u16,  test_integer_u16)
 425  impl_integer_for_uint!(u32,  test_integer_u32)
 426  impl_integer_for_uint!(u64,  test_integer_u64)
 427  impl_integer_for_uint!(uint, test_integer_uint)