Removed use of globs present in earlier versions of modules.
Fix tutorial.md to reflect `extra::rational` ==> `num::rational`.
################################################################################
TARGET_CRATES := std extra green rustuv native flate arena glob term semver \
- uuid serialize sync getopts collections
+ uuid serialize sync getopts collections num
HOST_CRATES := syntax rustc rustdoc fourcc
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc
DEPS_getopts := std
DEPS_collections := std serialize
DEPS_fourcc := syntax std
+DEPS_num := std extra
TOOL_DEPS_compiletest := extra green rustuv getopts
TOOL_DEPS_rustdoc := rustdoc green rustuv
* [The Rust compiler, `librustc`](rustc/index.html)
* [The `arena` allocation library](arena/index.html)
+* [The `num` arbitrary precision numerics library](num/index.html)
* [The `collections` library](collections/index.html)
* [The `flate` compression library](flate/index.html)
* [The `fourcc` four-character code library](fourcc/index.html)
For that, Rust offers you the `extern mod` declaration:
~~~
-extern mod extra;
-// extra ships with Rust, you'll find more details further down.
+extern mod num;
+// `num` ships with Rust (much like `extra`; more details further down).
fn main() {
// The rational number '1/2':
- let one_half = ::extra::rational::Ratio::new(1, 2);
+ let one_half = ::num::rational::Ratio::new(1, 2);
}
~~~
Which can result in something like this:
~~~
-extern mod extra;
+extern mod num;
use farm::dog;
-use extra::rational::Ratio;
+use num::rational::Ratio;
mod farm {
pub fn dog() { println!("woof"); }
## The extra library
-Rust also ships with the [extra library], an accumulation of useful things,
+Rust ships with crates such as the [extra library], an accumulation of useful things,
that are however not important enough to deserve a place in the standard
-library. You can use them by linking to `extra` with an `extern mod extra;`.
+library. You can link to a library such as `extra` with an `extern mod extra;`.
[extra library]: extra/index.html
pub mod base64;
pub mod workcache;
pub mod enum_set;
-#[path="num/bigint.rs"]
-pub mod bigint;
-#[path="num/rational.rs"]
-pub mod rational;
-#[path="num/complex.rs"]
-pub mod complex;
pub mod stats;
pub mod hex;
+++ /dev/null
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-A Big integer (signed version: `BigInt`, unsigned version: `BigUint`).
-
-A `BigUint` is represented as an array of `BigDigit`s.
-A `BigInt` is a combination of `BigUint` and `Sign`.
-*/
-
-#[allow(missing_doc)];
-#[allow(non_uppercase_statics)];
-
-use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
-use std::num;
-use std::num::{Zero, One, ToStrRadix, FromStrRadix, Orderable};
-use std::num::{Bitwise, ToPrimitive, FromPrimitive};
-use std::rand::Rng;
-use std::str;
-use std::uint;
-use std::{i64, u64};
-use std::vec;
-
-/**
-A `BigDigit` is a `BigUint`'s composing element.
-
-A `BigDigit` is half the size of machine word size.
-*/
-#[cfg(target_word_size = "32")]
-pub type BigDigit = u16;
-
-/**
-A `BigDigit` is a `BigUint`'s composing element.
-
-A `BigDigit` is half the size of machine word size.
-*/
-#[cfg(target_word_size = "64")]
-pub type BigDigit = u32;
-
-pub static ZERO_BIG_DIGIT: BigDigit = 0;
-
-pub mod BigDigit {
- use bigint::BigDigit;
-
- #[cfg(target_word_size = "32")]
- pub static bits: uint = 16;
-
- #[cfg(target_word_size = "64")]
- pub static bits: uint = 32;
-
- pub static base: uint = 1 << bits;
- static lo_mask: uint = (-1 as uint) >> bits;
-
- #[inline]
- fn get_hi(n: uint) -> BigDigit { (n >> bits) as BigDigit }
- #[inline]
- fn get_lo(n: uint) -> BigDigit { (n & lo_mask) as BigDigit }
-
- /// Split one machine sized unsigned integer into two `BigDigit`s.
- #[inline]
- pub fn from_uint(n: uint) -> (BigDigit, BigDigit) {
- (get_hi(n), get_lo(n))
- }
-
- /// Join two `BigDigit`s into one machine sized unsigned integer
- #[inline]
- pub fn to_uint(hi: BigDigit, lo: BigDigit) -> uint {
- (lo as uint) | ((hi as uint) << bits)
- }
-}
-
-/**
-A big unsigned integer type.
-
-A `BigUint`-typed value `BigUint { data: ~[a, b, c] }` represents a number
-`(a + b * BigDigit::base + c * BigDigit::base^2)`.
-*/
-#[deriving(Clone)]
-pub struct BigUint {
- priv data: ~[BigDigit]
-}
-
-impl Eq for BigUint {
- #[inline]
- fn eq(&self, other: &BigUint) -> bool { self.equals(other) }
-}
-
-impl TotalEq for BigUint {
- #[inline]
- fn equals(&self, other: &BigUint) -> bool {
- match self.cmp(other) { Equal => true, _ => false }
- }
-}
-
-impl Ord for BigUint {
- #[inline]
- fn lt(&self, other: &BigUint) -> bool {
- match self.cmp(other) { Less => true, _ => false}
- }
-}
-
-impl TotalOrd for BigUint {
- #[inline]
- fn cmp(&self, other: &BigUint) -> Ordering {
- let (s_len, o_len) = (self.data.len(), other.data.len());
- if s_len < o_len { return Less; }
- if s_len > o_len { return Greater; }
-
- for (&self_i, &other_i) in self.data.rev_iter().zip(other.data.rev_iter()) {
- if self_i < other_i { return Less; }
- if self_i > other_i { return Greater; }
- }
- return Equal;
- }
-}
-
-impl ToStr for BigUint {
- #[inline]
- fn to_str(&self) -> ~str { self.to_str_radix(10) }
-}
-
-impl FromStr for BigUint {
- #[inline]
- fn from_str(s: &str) -> Option<BigUint> {
- FromStrRadix::from_str_radix(s, 10)
- }
-}
-
-impl Num for BigUint {}
-
-impl Orderable for BigUint {
- #[inline]
- fn min(&self, other: &BigUint) -> BigUint {
- if self < other { self.clone() } else { other.clone() }
- }
-
- #[inline]
- fn max(&self, other: &BigUint) -> BigUint {
- if self > other { self.clone() } else { other.clone() }
- }
-
- #[inline]
- fn clamp(&self, mn: &BigUint, mx: &BigUint) -> BigUint {
- if self > mx { mx.clone() } else
- if self < mn { mn.clone() } else { self.clone() }
- }
-}
-
-impl BitAnd<BigUint, BigUint> for BigUint {
- fn bitand(&self, other: &BigUint) -> BigUint {
- let new_len = num::min(self.data.len(), other.data.len());
- let anded = vec::from_fn(new_len, |i| {
- // i will never be less than the size of either data vector
- let ai = self.data[i];
- let bi = other.data[i];
- ai & bi
- });
- return BigUint::new(anded);
- }
-}
-
-impl BitOr<BigUint, BigUint> for BigUint {
- fn bitor(&self, other: &BigUint) -> BigUint {
- let new_len = num::max(self.data.len(), other.data.len());
- let ored = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
- ai | bi
- });
- return BigUint::new(ored);
- }
-}
-
-impl BitXor<BigUint, BigUint> for BigUint {
- fn bitxor(&self, other: &BigUint) -> BigUint {
- let new_len = num::max(self.data.len(), other.data.len());
- let xored = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
- ai ^ bi
- });
- return BigUint::new(xored);
- }
-}
-
-impl Shl<uint, BigUint> for BigUint {
- #[inline]
- fn shl(&self, rhs: &uint) -> BigUint {
- let n_unit = *rhs / BigDigit::bits;
- let n_bits = *rhs % BigDigit::bits;
- return self.shl_unit(n_unit).shl_bits(n_bits);
- }
-}
-
-impl Shr<uint, BigUint> for BigUint {
- #[inline]
- fn shr(&self, rhs: &uint) -> BigUint {
- let n_unit = *rhs / BigDigit::bits;
- let n_bits = *rhs % BigDigit::bits;
- return self.shr_unit(n_unit).shr_bits(n_bits);
- }
-}
-
-impl Zero for BigUint {
- #[inline]
- fn zero() -> BigUint { BigUint::new(~[]) }
-
- #[inline]
- fn is_zero(&self) -> bool { self.data.is_empty() }
-}
-
-impl One for BigUint {
- #[inline]
- fn one() -> BigUint { BigUint::new(~[1]) }
-}
-
-impl Unsigned for BigUint {}
-
-impl Add<BigUint, BigUint> for BigUint {
- fn add(&self, other: &BigUint) -> BigUint {
- let new_len = num::max(self.data.len(), other.data.len());
-
- let mut carry = 0;
- let mut sum = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
- let (hi, lo) = BigDigit::from_uint(
- (ai as uint) + (bi as uint) + (carry as uint)
- );
- carry = hi;
- lo
- });
- if carry != 0 { sum.push(carry); }
- return BigUint::new(sum);
- }
-}
-
-impl Sub<BigUint, BigUint> for BigUint {
- fn sub(&self, other: &BigUint) -> BigUint {
- let new_len = num::max(self.data.len(), other.data.len());
-
- let mut borrow = 0;
- let diff = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
- let (hi, lo) = BigDigit::from_uint(
- (BigDigit::base) +
- (ai as uint) - (bi as uint) - (borrow as uint)
- );
- /*
- hi * (base) + lo == 1*(base) + ai - bi - borrow
- => ai - bi - borrow < 0 <=> hi == 0
- */
- borrow = if hi == 0 { 1 } else { 0 };
- lo
- });
-
- assert_eq!(borrow, 0); // <=> assert!((self >= other));
- return BigUint::new(diff);
- }
-}
-
-impl Mul<BigUint, BigUint> for BigUint {
- fn mul(&self, other: &BigUint) -> BigUint {
- if self.is_zero() || other.is_zero() { return Zero::zero(); }
-
- let (s_len, o_len) = (self.data.len(), other.data.len());
- if s_len == 1 { return mul_digit(other, self.data[0]); }
- if o_len == 1 { return mul_digit(self, other.data[0]); }
-
- // Using Karatsuba multiplication
- // (a1 * base + a0) * (b1 * base + b0)
- // = a1*b1 * base^2 +
- // (a1*b1 + a0*b0 - (a1-b0)*(b1-a0)) * base +
- // a0*b0
- let half_len = num::max(s_len, o_len) / 2;
- let (sHi, sLo) = cut_at(self, half_len);
- let (oHi, oLo) = cut_at(other, half_len);
-
- let ll = sLo * oLo;
- let hh = sHi * oHi;
- let mm = {
- let (s1, n1) = sub_sign(sHi, sLo);
- let (s2, n2) = sub_sign(oHi, oLo);
- match (s1, s2) {
- (Equal, _) | (_, Equal) => hh + ll,
- (Less, Greater) | (Greater, Less) => hh + ll + (n1 * n2),
- (Less, Less) | (Greater, Greater) => hh + ll - (n1 * n2)
- }
- };
-
- return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2);
-
-
- fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
- if n == 0 { return Zero::zero(); }
- if n == 1 { return (*a).clone(); }
-
- let mut carry = 0;
- let mut prod = a.data.iter().map(|ai| {
- let (hi, lo) = BigDigit::from_uint(
- (*ai as uint) * (n as uint) + (carry as uint)
- );
- carry = hi;
- lo
- }).collect::<~[BigDigit]>();
- if carry != 0 { prod.push(carry); }
- return BigUint::new(prod);
- }
-
- #[inline]
- fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
- let mid = num::min(a.data.len(), n);
- return (BigUint::from_slice(a.data.slice(mid, a.data.len())),
- BigUint::from_slice(a.data.slice(0, mid)));
- }
-
- #[inline]
- fn sub_sign(a: BigUint, b: BigUint) -> (Ordering, BigUint) {
- match a.cmp(&b) {
- Less => (Less, b - a),
- Greater => (Greater, a - b),
- _ => (Equal, Zero::zero())
- }
- }
- }
-}
-
-impl Div<BigUint, BigUint> for BigUint {
- #[inline]
- fn div(&self, other: &BigUint) -> BigUint {
- let (q, _) = self.div_rem(other);
- return q;
- }
-}
-
-impl Rem<BigUint, BigUint> for BigUint {
- #[inline]
- fn rem(&self, other: &BigUint) -> BigUint {
- let (_, r) = self.div_rem(other);
- return r;
- }
-}
-
-impl Neg<BigUint> for BigUint {
- #[inline]
- fn neg(&self) -> BigUint { fail!() }
-}
-
-impl Integer for BigUint {
- #[inline]
- fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
- self.div_mod_floor(other)
- }
-
- #[inline]
- fn div_floor(&self, other: &BigUint) -> BigUint {
- let (d, _) = self.div_mod_floor(other);
- return d;
- }
-
- #[inline]
- fn mod_floor(&self, other: &BigUint) -> BigUint {
- let (_, m) = self.div_mod_floor(other);
- return m;
- }
-
- fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) {
- if other.is_zero() { fail!() }
- if self.is_zero() { return (Zero::zero(), Zero::zero()); }
- if *other == One::one() { return ((*self).clone(), Zero::zero()); }
-
- match self.cmp(other) {
- Less => return (Zero::zero(), (*self).clone()),
- Equal => return (One::one(), Zero::zero()),
- Greater => {} // Do nothing
- }
-
- let mut shift = 0;
- let mut n = *other.data.last().unwrap();
- while n < (1 << BigDigit::bits - 2) {
- n <<= 1;
- shift += 1;
- }
- assert!(shift < BigDigit::bits);
- let (d, m) = div_mod_floor_inner(self << shift, other << shift);
- return (d, m >> shift);
-
-
- fn div_mod_floor_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
- let mut m = a;
- let mut d: BigUint = Zero::zero();
- let mut n = 1;
- while m >= b {
- let (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
- let mut d0 = d0;
- let mut prod = b * d0;
- while prod > m {
- // FIXME(#6050): overloaded operators force moves with generic types
- // d0 -= d_unit
- d0 = d0 - d_unit;
- // FIXME(#6050): overloaded operators force moves with generic types
- // prod = prod - b_unit;
- prod = prod - b_unit
- }
- if d0.is_zero() {
- n = 2;
- continue;
- }
- n = 1;
- // FIXME(#6102): Assignment operator for BigInt causes ICE
- // d += d0;
- d = d + d0;
- // FIXME(#6102): Assignment operator for BigInt causes ICE
- // m -= prod;
- m = m - prod;
- }
- return (d, m);
- }
-
-
- fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
- -> (BigUint, BigUint, BigUint) {
- if a.data.len() < n {
- return (Zero::zero(), Zero::zero(), (*a).clone());
- }
-
- let an = a.data.slice(a.data.len() - n, a.data.len());
- let bn = *b.data.last().unwrap();
- let mut d = ~[];
- let mut carry = 0;
- for elt in an.rev_iter() {
- let ai = BigDigit::to_uint(carry, *elt);
- let di = ai / (bn as uint);
- assert!(di < BigDigit::base);
- carry = (ai % (bn as uint)) as BigDigit;
- d = ~[di as BigDigit] + d;
- }
-
- let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
- if shift == 0 {
- return (BigUint::new(d), One::one(), (*b).clone());
- }
- let one: BigUint = One::one();
- return (BigUint::from_slice(d).shl_unit(shift),
- one.shl_unit(shift),
- b.shl_unit(shift));
- }
- }
-
- /**
- * Calculates the Greatest Common Divisor (GCD) of the number and `other`
- *
- * The result is always positive
- */
- #[inline]
- fn gcd(&self, other: &BigUint) -> BigUint {
- // Use Euclid's algorithm
- let mut m = (*self).clone();
- let mut n = (*other).clone();
- while !m.is_zero() {
- let temp = m;
- m = n % temp;
- n = temp;
- }
- return n;
- }
-
- /**
- * Calculates the Lowest Common Multiple (LCM) of the number and `other`
- */
- #[inline]
- fn lcm(&self, other: &BigUint) -> BigUint { ((*self * *other) / self.gcd(other)) }
-
- /// Returns `true` if the number can be divided by `other` without leaving a remainder
- #[inline]
- fn is_multiple_of(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
-
- /// Returns `true` if the number is divisible by `2`
- #[inline]
- fn is_even(&self) -> bool {
- // Considering only the last digit.
- if self.data.is_empty() {
- true
- } else {
- self.data[0].is_even()
- }
- }
-
- /// Returns `true` if the number is not divisible by `2`
- #[inline]
- fn is_odd(&self) -> bool { !self.is_even() }
-}
-
-impl ToPrimitive for BigUint {
- #[inline]
- fn to_i64(&self) -> Option<i64> {
- self.to_u64().and_then(|n| {
- // If top bit of u64 is set, it's too large to convert to i64.
- if n >> 63 == 0 {
- Some(n as i64)
- } else {
- None
- }
- })
- }
-
- #[cfg(target_word_size = "32")]
- #[inline]
- fn to_u64(&self) -> Option<u64> {
- match self.data {
- [] => {
- Some(0)
- }
- [n0] => {
- Some(n0 as u64)
- }
- [n0, n1] => {
- Some(BigDigit::to_uint(n1, n0) as u64)
- }
- [n0, n1, n2] => {
- let n_lo = BigDigit::to_uint(n1, n0) as u64;
- let n_hi = n2 as u64;
- Some((n_hi << 32) + n_lo)
- }
- [n0, n1, n2, n3] => {
- let n_lo = BigDigit::to_uint(n1, n0) as u64;
- let n_hi = BigDigit::to_uint(n3, n2) as u64;
- Some((n_hi << 32) + n_lo)
- }
- _ => None
- }
- }
-
- #[cfg(target_word_size = "64")]
- #[inline]
- fn to_u64(&self) -> Option<u64> {
- match self.data {
- [] => {
- Some(0)
- }
- [n0] => {
- Some(n0 as u64)
- }
- [n0, n1] => {
- Some(BigDigit::to_uint(n1, n0) as u64)
- }
- _ => None
- }
- }
-}
-
-impl FromPrimitive for BigUint {
- #[inline]
- fn from_i64(n: i64) -> Option<BigUint> {
- if n > 0 {
- FromPrimitive::from_u64(n as u64)
- } else if n == 0 {
- Some(Zero::zero())
- } else {
- None
- }
- }
-
- #[cfg(target_word_size = "32")]
- #[inline]
- fn from_u64(n: u64) -> Option<BigUint> {
- let n_lo = (n & 0x0000_0000_FFFF_FFFF) as uint;
- let n_hi = (n >> 32) as uint;
-
- let n = match (BigDigit::from_uint(n_hi), BigDigit::from_uint(n_lo)) {
- ((0, 0), (0, 0)) => Zero::zero(),
- ((0, 0), (0, n0)) => BigUint::new(~[n0]),
- ((0, 0), (n1, n0)) => BigUint::new(~[n0, n1]),
- ((0, n2), (n1, n0)) => BigUint::new(~[n0, n1, n2]),
- ((n3, n2), (n1, n0)) => BigUint::new(~[n0, n1, n2, n3]),
- };
- Some(n)
- }
-
- #[cfg(target_word_size = "64")]
- #[inline]
- fn from_u64(n: u64) -> Option<BigUint> {
- let n = match BigDigit::from_uint(n as uint) {
- (0, 0) => Zero::zero(),
- (0, n0) => BigUint::new(~[n0]),
- (n1, n0) => BigUint::new(~[n0, n1])
- };
- Some(n)
- }
-}
-
-/// A generic trait for converting a value to a `BigUint`.
-pub trait ToBigUint {
- /// Converts the value of `self` to a `BigUint`.
- fn to_biguint(&self) -> Option<BigUint>;
-}
-
-impl ToBigUint for BigInt {
- #[inline]
- fn to_biguint(&self) -> Option<BigUint> {
- if self.sign == Plus {
- Some(self.data.clone())
- } else if self.sign == Zero {
- Some(Zero::zero())
- } else {
- None
- }
- }
-}
-
-impl ToBigUint for BigUint {
- #[inline]
- fn to_biguint(&self) -> Option<BigUint> {
- Some(self.clone())
- }
-}
-
-macro_rules! impl_to_biguint(
- ($T:ty, $from_ty:path) => {
- impl ToBigUint for $T {
- #[inline]
- fn to_biguint(&self) -> Option<BigUint> {
- $from_ty(*self)
- }
- }
- }
-)
-
-impl_to_biguint!(int, FromPrimitive::from_int)
-impl_to_biguint!(i8, FromPrimitive::from_i8)
-impl_to_biguint!(i16, FromPrimitive::from_i16)
-impl_to_biguint!(i32, FromPrimitive::from_i32)
-impl_to_biguint!(i64, FromPrimitive::from_i64)
-impl_to_biguint!(uint, FromPrimitive::from_uint)
-impl_to_biguint!(u8, FromPrimitive::from_u8)
-impl_to_biguint!(u16, FromPrimitive::from_u16)
-impl_to_biguint!(u32, FromPrimitive::from_u32)
-impl_to_biguint!(u64, FromPrimitive::from_u64)
-
-impl ToStrRadix for BigUint {
- fn to_str_radix(&self, radix: uint) -> ~str {
- assert!(1 < radix && radix <= 16);
- let (base, max_len) = get_radix_base(radix);
- if base == BigDigit::base {
- return fill_concat(self.data, radix, max_len)
- }
- return fill_concat(convert_base((*self).clone(), base), radix, max_len);
-
- fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
- let divider = FromPrimitive::from_uint(base).unwrap();
- let mut result = ~[];
- let mut m = n;
- while m >= divider {
- let (d, m0) = m.div_mod_floor(÷r);
- result.push(m0.to_uint().unwrap() as BigDigit);
- m = d;
- }
- if !m.is_zero() {
- result.push(m.to_uint().unwrap() as BigDigit);
- }
- return result;
- }
-
- fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
- if v.is_empty() { return ~"0" }
- let mut s = str::with_capacity(v.len() * l);
- for n in v.rev_iter() {
- let ss = (*n as uint).to_str_radix(radix);
- s.push_str("0".repeat(l - ss.len()));
- s.push_str(ss);
- }
- s.trim_left_chars(&'0').to_owned()
- }
- }
-}
-
-impl FromStrRadix for BigUint {
- /// Creates and initializes a `BigUint`.
- #[inline]
- fn from_str_radix(s: &str, radix: uint)
- -> Option<BigUint> {
- BigUint::parse_bytes(s.as_bytes(), radix)
- }
-}
-
-impl BigUint {
- /// Creates and initializes a `BigUint`.
- #[inline]
- pub fn new(v: ~[BigDigit]) -> BigUint {
- // omit trailing zeros
- let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
-
- if new_len == v.len() { return BigUint { data: v }; }
- let mut v = v;
- v.truncate(new_len);
- return BigUint { data: v };
- }
-
- /// Creates and initializes a `BigUint`.
- #[inline]
- pub fn from_slice(slice: &[BigDigit]) -> BigUint {
- return BigUint::new(slice.to_owned());
- }
-
- /// Creates and initializes a `BigUint`.
- pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigUint> {
- let (base, unit_len) = get_radix_base(radix);
- let base_num = match FromPrimitive::from_uint(base) {
- Some(base_num) => base_num,
- None => { return None; }
- };
-
- let mut end = buf.len();
- let mut n: BigUint = Zero::zero();
- let mut power: BigUint = One::one();
- loop {
- let start = num::max(end, unit_len) - unit_len;
- match uint::parse_bytes(buf.slice(start, end), radix) {
- Some(d) => {
- let d: Option<BigUint> = FromPrimitive::from_uint(d);
- match d {
- Some(d) => {
- // FIXME(#6102): Assignment operator for BigInt
- // causes ICE:
- // n += d * power;
- n = n + d * power;
- }
- None => { return None; }
- }
- }
- None => { return None; }
- }
- if end <= unit_len {
- return Some(n);
- }
- end -= unit_len;
- // FIXME(#6050): overloaded operators force moves with generic types
- // power *= base_num;
- power = power * base_num;
- }
- }
-
- #[inline]
- fn shl_unit(&self, n_unit: uint) -> BigUint {
- if n_unit == 0 || self.is_zero() { return (*self).clone(); }
-
- return BigUint::new(vec::from_elem(n_unit, ZERO_BIG_DIGIT)
- + self.data);
- }
-
- #[inline]
- fn shl_bits(&self, n_bits: uint) -> BigUint {
- if n_bits == 0 || self.is_zero() { return (*self).clone(); }
-
- let mut carry = 0;
- let mut shifted = self.data.iter().map(|elem| {
- let (hi, lo) = BigDigit::from_uint(
- (*elem as uint) << n_bits | (carry as uint)
- );
- carry = hi;
- lo
- }).collect::<~[BigDigit]>();
- if carry != 0 { shifted.push(carry); }
- return BigUint::new(shifted);
- }
-
- #[inline]
- fn shr_unit(&self, n_unit: uint) -> BigUint {
- if n_unit == 0 { return (*self).clone(); }
- if self.data.len() < n_unit { return Zero::zero(); }
- return BigUint::from_slice(
- self.data.slice(n_unit, self.data.len())
- );
- }
-
- #[inline]
- fn shr_bits(&self, n_bits: uint) -> BigUint {
- if n_bits == 0 || self.data.is_empty() { return (*self).clone(); }
-
- let mut borrow = 0;
- let mut shifted = ~[];
- for elem in self.data.rev_iter() {
- shifted = ~[(*elem >> n_bits) | borrow] + shifted;
- borrow = *elem << (BigDigit::bits - n_bits);
- }
- return BigUint::new(shifted);
- }
-
- /// Determines the fewest bits necessary to express the `BigUint`.
- pub fn bits(&self) -> uint {
- if self.is_zero() { return 0; }
- let zeros = self.data.last().unwrap().leading_zeros();
- return self.data.len()*BigDigit::bits - (zeros as uint);
- }
-}
-
-#[cfg(target_word_size = "32")]
-#[inline]
-fn get_radix_base(radix: uint) -> (uint, uint) {
- assert!(1 < radix && radix <= 16);
- match radix {
- 2 => (65536, 16),
- 3 => (59049, 10),
- 4 => (65536, 8),
- 5 => (15625, 6),
- 6 => (46656, 6),
- 7 => (16807, 5),
- 8 => (32768, 5),
- 9 => (59049, 5),
- 10 => (10000, 4),
- 11 => (14641, 4),
- 12 => (20736, 4),
- 13 => (28561, 4),
- 14 => (38416, 4),
- 15 => (50625, 4),
- 16 => (65536, 4),
- _ => fail!()
- }
-}
-
-#[cfg(target_word_size = "64")]
-#[inline]
-fn get_radix_base(radix: uint) -> (uint, uint) {
- assert!(1 < radix && radix <= 16);
- match radix {
- 2 => (4294967296, 32),
- 3 => (3486784401, 20),
- 4 => (4294967296, 16),
- 5 => (1220703125, 13),
- 6 => (2176782336, 12),
- 7 => (1977326743, 11),
- 8 => (1073741824, 10),
- 9 => (3486784401, 10),
- 10 => (1000000000, 9),
- 11 => (2357947691, 9),
- 12 => (429981696, 8),
- 13 => (815730721, 8),
- 14 => (1475789056, 8),
- 15 => (2562890625, 8),
- 16 => (4294967296, 8),
- _ => fail!()
- }
-}
-
-/// A Sign is a `BigInt`'s composing element.
-#[deriving(Eq, Clone)]
-pub enum Sign { Minus, Zero, Plus }
-
-impl Ord for Sign {
- #[inline]
- fn lt(&self, other: &Sign) -> bool {
- match self.cmp(other) { Less => true, _ => false}
- }
-}
-
-impl TotalEq for Sign {
- #[inline]
- fn equals(&self, other: &Sign) -> bool { *self == *other }
-}
-impl TotalOrd for Sign {
- #[inline]
- fn cmp(&self, other: &Sign) -> Ordering {
- match (*self, *other) {
- (Minus, Minus) | (Zero, Zero) | (Plus, Plus) => Equal,
- (Minus, Zero) | (Minus, Plus) | (Zero, Plus) => Less,
- _ => Greater
- }
- }
-}
-
-impl Neg<Sign> for Sign {
- /// Negate Sign value.
- #[inline]
- fn neg(&self) -> Sign {
- match *self {
- Minus => Plus,
- Zero => Zero,
- Plus => Minus
- }
- }
-}
-
-/// A big signed integer type.
-#[deriving(Clone)]
-pub struct BigInt {
- priv sign: Sign,
- priv data: BigUint
-}
-
-impl Eq for BigInt {
- #[inline]
- fn eq(&self, other: &BigInt) -> bool { self.equals(other) }
-}
-
-impl TotalEq for BigInt {
- #[inline]
- fn equals(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Equal => true, _ => false }
- }
-}
-
-impl Ord for BigInt {
- #[inline]
- fn lt(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Less => true, _ => false}
- }
-}
-
-impl TotalOrd for BigInt {
- #[inline]
- fn cmp(&self, other: &BigInt) -> Ordering {
- let scmp = self.sign.cmp(&other.sign);
- if scmp != Equal { return scmp; }
-
- match self.sign {
- Zero => Equal,
- Plus => self.data.cmp(&other.data),
- Minus => other.data.cmp(&self.data),
- }
- }
-}
-
-impl ToStr for BigInt {
- #[inline]
- fn to_str(&self) -> ~str { self.to_str_radix(10) }
-}
-
-impl FromStr for BigInt {
- #[inline]
- fn from_str(s: &str) -> Option<BigInt> {
- FromStrRadix::from_str_radix(s, 10)
- }
-}
-
-impl Num for BigInt {}
-
-impl Orderable for BigInt {
- #[inline]
- fn min(&self, other: &BigInt) -> BigInt {
- if self < other { self.clone() } else { other.clone() }
- }
-
- #[inline]
- fn max(&self, other: &BigInt) -> BigInt {
- if self > other { self.clone() } else { other.clone() }
- }
-
- #[inline]
- fn clamp(&self, mn: &BigInt, mx: &BigInt) -> BigInt {
- if self > mx { mx.clone() } else
- if self < mn { mn.clone() } else { self.clone() }
- }
-}
-
-impl Shl<uint, BigInt> for BigInt {
- #[inline]
- fn shl(&self, rhs: &uint) -> BigInt {
- BigInt::from_biguint(self.sign, self.data << *rhs)
- }
-}
-
-impl Shr<uint, BigInt> for BigInt {
- #[inline]
- fn shr(&self, rhs: &uint) -> BigInt {
- BigInt::from_biguint(self.sign, self.data >> *rhs)
- }
-}
-
-impl Zero for BigInt {
- #[inline]
- fn zero() -> BigInt {
- BigInt::from_biguint(Zero, Zero::zero())
- }
-
- #[inline]
- fn is_zero(&self) -> bool { self.sign == Zero }
-}
-
-impl One for BigInt {
- #[inline]
- fn one() -> BigInt {
- BigInt::from_biguint(Plus, One::one())
- }
-}
-
-impl Signed for BigInt {
- #[inline]
- fn abs(&self) -> BigInt {
- match self.sign {
- Plus | Zero => self.clone(),
- Minus => BigInt::from_biguint(Plus, self.data.clone())
- }
- }
-
- #[inline]
- fn abs_sub(&self, other: &BigInt) -> BigInt {
- if *self <= *other { Zero::zero() } else { *self - *other }
- }
-
- #[inline]
- fn signum(&self) -> BigInt {
- match self.sign {
- Plus => BigInt::from_biguint(Plus, One::one()),
- Minus => BigInt::from_biguint(Minus, One::one()),
- Zero => Zero::zero(),
- }
- }
-
- #[inline]
- fn is_positive(&self) -> bool { self.sign == Plus }
-
- #[inline]
- fn is_negative(&self) -> bool { self.sign == Minus }
-}
-
-impl Add<BigInt, BigInt> for BigInt {
- #[inline]
- fn add(&self, other: &BigInt) -> BigInt {
- match (self.sign, other.sign) {
- (Zero, _) => other.clone(),
- (_, Zero) => self.clone(),
- (Plus, Plus) => BigInt::from_biguint(Plus,
- self.data + other.data),
- (Plus, Minus) => self - (-*other),
- (Minus, Plus) => other - (-*self),
- (Minus, Minus) => -((-self) + (-*other))
- }
- }
-}
-
-impl Sub<BigInt, BigInt> for BigInt {
- #[inline]
- fn sub(&self, other: &BigInt) -> BigInt {
- match (self.sign, other.sign) {
- (Zero, _) => -other,
- (_, Zero) => self.clone(),
- (Plus, Plus) => match self.data.cmp(&other.data) {
- Less => BigInt::from_biguint(Minus, other.data - self.data),
- Greater => BigInt::from_biguint(Plus, self.data - other.data),
- Equal => Zero::zero()
- },
- (Plus, Minus) => self + (-*other),
- (Minus, Plus) => -((-self) + *other),
- (Minus, Minus) => (-other) - (-*self)
- }
- }
-}
-
-impl Mul<BigInt, BigInt> for BigInt {
- #[inline]
- fn mul(&self, other: &BigInt) -> BigInt {
- match (self.sign, other.sign) {
- (Zero, _) | (_, Zero) => Zero::zero(),
- (Plus, Plus) | (Minus, Minus) => {
- BigInt::from_biguint(Plus, self.data * other.data)
- },
- (Plus, Minus) | (Minus, Plus) => {
- BigInt::from_biguint(Minus, self.data * other.data)
- }
- }
- }
-}
-
-impl Div<BigInt, BigInt> for BigInt {
- #[inline]
- fn div(&self, other: &BigInt) -> BigInt {
- let (q, _) = self.div_rem(other);
- return q;
- }
-}
-
-impl Rem<BigInt, BigInt> for BigInt {
- #[inline]
- fn rem(&self, other: &BigInt) -> BigInt {
- let (_, r) = self.div_rem(other);
- return r;
- }
-}
-
-impl Neg<BigInt> for BigInt {
- #[inline]
- fn neg(&self) -> BigInt {
- BigInt::from_biguint(self.sign.neg(), self.data.clone())
- }
-}
-
-impl Integer for BigInt {
- #[inline]
- fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
- // r.sign == self.sign
- let (d_ui, r_ui) = self.data.div_mod_floor(&other.data);
- let d = BigInt::from_biguint(Plus, d_ui);
- let r = BigInt::from_biguint(Plus, r_ui);
- match (self.sign, other.sign) {
- (_, Zero) => fail!(),
- (Plus, Plus) | (Zero, Plus) => ( d, r),
- (Plus, Minus) | (Zero, Minus) => (-d, r),
- (Minus, Plus) => (-d, -r),
- (Minus, Minus) => ( d, -r)
- }
- }
-
- #[inline]
- fn div_floor(&self, other: &BigInt) -> BigInt {
- let (d, _) = self.div_mod_floor(other);
- return d;
- }
-
- #[inline]
- fn mod_floor(&self, other: &BigInt) -> BigInt {
- let (_, m) = self.div_mod_floor(other);
- return m;
- }
-
- fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
- // m.sign == other.sign
- let (d_ui, m_ui) = self.data.div_rem(&other.data);
- let d = BigInt::from_biguint(Plus, d_ui);
- let m = BigInt::from_biguint(Plus, m_ui);
- match (self.sign, other.sign) {
- (_, Zero) => fail!(),
- (Plus, Plus) | (Zero, Plus) => (d, m),
- (Plus, Minus) | (Zero, Minus) => if m.is_zero() {
- (-d, Zero::zero())
- } else {
- (-d - One::one(), m + *other)
- },
- (Minus, Plus) => if m.is_zero() {
- (-d, Zero::zero())
- } else {
- (-d - One::one(), other - m)
- },
- (Minus, Minus) => (d, -m)
- }
- }
-
- /**
- * Calculates the Greatest Common Divisor (GCD) of the number and `other`
- *
- * The result is always positive
- */
- #[inline]
- fn gcd(&self, other: &BigInt) -> BigInt {
- BigInt::from_biguint(Plus, self.data.gcd(&other.data))
- }
-
- /**
- * Calculates the Lowest Common Multiple (LCM) of the number and `other`
- */
- #[inline]
- fn lcm(&self, other: &BigInt) -> BigInt {
- BigInt::from_biguint(Plus, self.data.lcm(&other.data))
- }
-
- /// Returns `true` if the number can be divided by `other` without leaving a remainder
- #[inline]
- fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) }
-
- /// Returns `true` if the number is divisible by `2`
- #[inline]
- fn is_even(&self) -> bool { self.data.is_even() }
-
- /// Returns `true` if the number is not divisible by `2`
- #[inline]
- fn is_odd(&self) -> bool { self.data.is_odd() }
-}
-
-impl ToPrimitive for BigInt {
- #[inline]
- fn to_i64(&self) -> Option<i64> {
- match self.sign {
- Plus => self.data.to_i64(),
- Zero => Some(0),
- Minus => {
- self.data.to_u64().and_then(|n| {
- let m: u64 = 1 << 63;
- if n < m {
- Some(-(n as i64))
- } else if n == m {
- Some(i64::MIN)
- } else {
- None
- }
- })
- }
- }
- }
-
- #[inline]
- fn to_u64(&self) -> Option<u64> {
- match self.sign {
- Plus => self.data.to_u64(),
- Zero => Some(0),
- Minus => None
- }
- }
-}
-
-impl FromPrimitive for BigInt {
- #[inline]
- fn from_i64(n: i64) -> Option<BigInt> {
- if n > 0 {
- FromPrimitive::from_u64(n as u64).and_then(|n| {
- Some(BigInt::from_biguint(Plus, n))
- })
- } else if n < 0 {
- FromPrimitive::from_u64(u64::MAX - (n as u64) + 1).and_then(
- |n| {
- Some(BigInt::from_biguint(Minus, n))
- })
- } else {
- Some(Zero::zero())
- }
- }
-
- #[inline]
- fn from_u64(n: u64) -> Option<BigInt> {
- if n == 0 {
- Some(Zero::zero())
- } else {
- FromPrimitive::from_u64(n).and_then(|n| {
- Some(BigInt::from_biguint(Plus, n))
- })
- }
- }
-}
-
-/// A generic trait for converting a value to a `BigInt`.
-pub trait ToBigInt {
- /// Converts the value of `self` to a `BigInt`.
- fn to_bigint(&self) -> Option<BigInt>;
-}
-
-impl ToBigInt for BigInt {
- #[inline]
- fn to_bigint(&self) -> Option<BigInt> {
- Some(self.clone())
- }
-}
-
-impl ToBigInt for BigUint {
- #[inline]
- fn to_bigint(&self) -> Option<BigInt> {
- if self.is_zero() {
- Some(Zero::zero())
- } else {
- Some(BigInt { sign: Plus, data: self.clone() })
- }
- }
-}
-
-macro_rules! impl_to_bigint(
- ($T:ty, $from_ty:path) => {
- impl ToBigInt for $T {
- #[inline]
- fn to_bigint(&self) -> Option<BigInt> {
- $from_ty(*self)
- }
- }
- }
-)
-
-impl_to_bigint!(int, FromPrimitive::from_int)
-impl_to_bigint!(i8, FromPrimitive::from_i8)
-impl_to_bigint!(i16, FromPrimitive::from_i16)
-impl_to_bigint!(i32, FromPrimitive::from_i32)
-impl_to_bigint!(i64, FromPrimitive::from_i64)
-impl_to_bigint!(uint, FromPrimitive::from_uint)
-impl_to_bigint!(u8, FromPrimitive::from_u8)
-impl_to_bigint!(u16, FromPrimitive::from_u16)
-impl_to_bigint!(u32, FromPrimitive::from_u32)
-impl_to_bigint!(u64, FromPrimitive::from_u64)
-
-impl ToStrRadix for BigInt {
- #[inline]
- fn to_str_radix(&self, radix: uint) -> ~str {
- match self.sign {
- Plus => self.data.to_str_radix(radix),
- Zero => ~"0",
- Minus => ~"-" + self.data.to_str_radix(radix)
- }
- }
-}
-
-impl FromStrRadix for BigInt {
- /// Creates and initializes a BigInt.
- #[inline]
- fn from_str_radix(s: &str, radix: uint) -> Option<BigInt> {
- BigInt::parse_bytes(s.as_bytes(), radix)
- }
-}
-
-trait RandBigInt {
- /// Generate a random `BigUint` of the given bit size.
- fn gen_biguint(&mut self, bit_size: uint) -> BigUint;
-
- /// Generate a random BigInt of the given bit size.
- fn gen_bigint(&mut self, bit_size: uint) -> BigInt;
-
- /// Generate a random `BigUint` less than the given bound. Fails
- /// when the bound is zero.
- fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
-
- /// Generate a random `BigUint` within the given range. The lower
- /// bound is inclusive; the upper bound is exclusive. Fails when
- /// the upper bound is not greater than the lower bound.
- fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
-
- /// Generate a random `BigInt` within the given range. The lower
- /// bound is inclusive; the upper bound is exclusive. Fails when
- /// the upper bound is not greater than the lower bound.
- fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
-}
-
-impl<R: Rng> RandBigInt for R {
- fn gen_biguint(&mut self, bit_size: uint) -> BigUint {
- let (digits, rem) = bit_size.div_rem(&BigDigit::bits);
- let mut data = vec::with_capacity(digits+1);
- for _ in range(0, digits) {
- data.push(self.gen());
- }
- if rem > 0 {
- let final_digit: BigDigit = self.gen();
- data.push(final_digit >> (BigDigit::bits - rem));
- }
- return BigUint::new(data);
- }
-
- fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
- // Generate a random BigUint...
- let biguint = self.gen_biguint(bit_size);
- // ...and then randomly assign it a Sign...
- let sign = if biguint.is_zero() {
- // ...except that if the BigUint is zero, we need to try
- // again with probability 0.5. This is because otherwise,
- // the probability of generating a zero BigInt would be
- // double that of any other number.
- if self.gen() {
- return self.gen_bigint(bit_size);
- } else {
- Zero
- }
- } else if self.gen() {
- Plus
- } else {
- Minus
- };
- return BigInt::from_biguint(sign, biguint);
- }
-
- fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
- assert!(!bound.is_zero());
- let bits = bound.bits();
- loop {
- let n = self.gen_biguint(bits);
- if n < *bound { return n; }
- }
- }
-
- fn gen_biguint_range(&mut self,
- lbound: &BigUint,
- ubound: &BigUint)
- -> BigUint {
- assert!(*lbound < *ubound);
- return *lbound + self.gen_biguint_below(&(*ubound - *lbound));
- }
-
- fn gen_bigint_range(&mut self,
- lbound: &BigInt,
- ubound: &BigInt)
- -> BigInt {
- assert!(*lbound < *ubound);
- let delta = (*ubound - *lbound).to_biguint().unwrap();
- return *lbound + self.gen_biguint_below(&delta).to_bigint().unwrap();
- }
-}
-
-impl BigInt {
- /// Creates and initializes a BigInt.
- #[inline]
- pub fn new(sign: Sign, v: ~[BigDigit]) -> BigInt {
- BigInt::from_biguint(sign, BigUint::new(v))
- }
-
- /// Creates and initializes a `BigInt`.
- #[inline]
- pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
- if sign == Zero || data.is_zero() {
- return BigInt { sign: Zero, data: Zero::zero() };
- }
- return BigInt { sign: sign, data: data };
- }
-
- /// Creates and initializes a `BigInt`.
- #[inline]
- pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
- BigInt::from_biguint(sign, BigUint::from_slice(slice))
- }
-
- /// Creates and initializes a `BigInt`.
- pub fn parse_bytes(buf: &[u8], radix: uint)
- -> Option<BigInt> {
- if buf.is_empty() { return None; }
- let mut sign = Plus;
- let mut start = 0;
- if buf[0] == ('-' as u8) {
- sign = Minus;
- start = 1;
- }
- return BigUint::parse_bytes(buf.slice(start, buf.len()), radix)
- .map(|bu| BigInt::from_biguint(sign, bu));
- }
-
- /// Converts this `BigInt` into a `BigUint`, if it's not negative.
- #[inline]
- pub fn to_biguint(&self) -> Option<BigUint> {
- match self.sign {
- Plus => Some(self.data.clone()),
- Zero => Some(Zero::zero()),
- Minus => None
- }
- }
-}
-
-#[cfg(test)]
-mod biguint_tests {
- use super::*;
- use super::RandBigInt;
-
- use std::cmp::{Less, Equal, Greater};
- use std::i64;
- use std::num::{Zero, One, FromStrRadix};
- use std::num::{ToPrimitive, FromPrimitive};
- use std::rand::{task_rng};
- use std::str;
- use std::u64;
- use std::vec;
-
- #[test]
- fn test_from_slice() {
- fn check(slice: &[BigDigit], data: &[BigDigit]) {
- assert!(data == BigUint::from_slice(slice).data);
- }
- check([1], [1]);
- check([0, 0, 0], []);
- check([1, 2, 0, 0], [1, 2]);
- check([0, 0, 1, 2], [0, 0, 1, 2]);
- check([0, 0, 1, 2, 0, 0], [0, 0, 1, 2]);
- check([-1], [-1]);
- }
-
- #[test]
- fn test_cmp() {
- let data: ~[BigUint] = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1] ]
- .map(|v| BigUint::from_slice(*v));
- for (i, ni) in data.iter().enumerate() {
- for (j0, nj) in data.slice(i, data.len()).iter().enumerate() {
- let j = j0 + i;
- if i == j {
- assert_eq!(ni.cmp(nj), Equal);
- assert_eq!(nj.cmp(ni), Equal);
- assert_eq!(ni, nj);
- assert!(!(ni != nj));
- assert!(ni <= nj);
- assert!(ni >= nj);
- assert!(!(ni < nj));
- assert!(!(ni > nj));
- } else {
- assert_eq!(ni.cmp(nj), Less);
- assert_eq!(nj.cmp(ni), Greater);
-
- assert!(!(ni == nj));
- assert!(ni != nj);
-
- assert!(ni <= nj);
- assert!(!(ni >= nj));
- assert!(ni < nj);
- assert!(!(ni > nj));
-
- assert!(!(nj <= ni));
- assert!(nj >= ni);
- assert!(!(nj < ni));
- assert!(nj > ni);
- }
- }
- }
- }
-
- #[test]
- fn test_bitand() {
- fn check(left: ~[BigDigit],
- right: ~[BigDigit],
- expected: ~[BigDigit]) {
- assert_eq!(BigUint::new(left) & BigUint::new(right),
- BigUint::new(expected));
- }
- check(~[], ~[], ~[]);
- check(~[268, 482, 17],
- ~[964, 54],
- ~[260, 34]);
- }
-
- #[test]
- fn test_bitor() {
- fn check(left: ~[BigDigit],
- right: ~[BigDigit],
- expected: ~[BigDigit]) {
- assert_eq!(BigUint::new(left) | BigUint::new(right),
- BigUint::new(expected));
- }
- check(~[], ~[], ~[]);
- check(~[268, 482, 17],
- ~[964, 54],
- ~[972, 502, 17]);
- }
-
- #[test]
- fn test_bitxor() {
- fn check(left: ~[BigDigit],
- right: ~[BigDigit],
- expected: ~[BigDigit]) {
- assert_eq!(BigUint::new(left) ^ BigUint::new(right),
- BigUint::new(expected));
- }
- check(~[], ~[], ~[]);
- check(~[268, 482, 17],
- ~[964, 54],
- ~[712, 468, 17]);
- }
-
- #[test]
- fn test_shl() {
- fn check(s: &str, shift: uint, ans: &str) {
- let opt_biguint: Option<BigUint> = FromStrRadix::from_str_radix(s, 16);
- let bu = (opt_biguint.unwrap() << shift).to_str_radix(16);
- assert_eq!(bu.as_slice(), ans);
- }
-
- check("0", 3, "0");
- check("1", 3, "8");
-
- check("1" + "0000" + "0000" + "0000" + "0001" + "0000" + "0000" + "0000" + "0001", 3,
- "8" + "0000" + "0000" + "0000" + "0008" + "0000" + "0000" + "0000" + "0008");
- check("1" + "0000" + "0001" + "0000" + "0001", 2,
- "4" + "0000" + "0004" + "0000" + "0004");
- check("1" + "0001" + "0001", 1,
- "2" + "0002" + "0002");
-
- check("" + "4000" + "0000" + "0000" + "0000", 3,
- "2" + "0000" + "0000" + "0000" + "0000");
- check("" + "4000" + "0000", 2,
- "1" + "0000" + "0000");
- check("" + "4000", 2,
- "1" + "0000");
-
- check("" + "4000" + "0000" + "0000" + "0000", 67,
- "2" + "0000" + "0000" + "0000" + "0000" + "0000" + "0000" + "0000" + "0000");
- check("" + "4000" + "0000", 35,
- "2" + "0000" + "0000" + "0000" + "0000");
- check("" + "4000", 19,
- "2" + "0000" + "0000");
-
- check("" + "fedc" + "ba98" + "7654" + "3210" + "fedc" + "ba98" + "7654" + "3210", 4,
- "f" + "edcb" + "a987" + "6543" + "210f" + "edcb" + "a987" + "6543" + "2100");
- check("88887777666655554444333322221111", 16,
- "888877776666555544443333222211110000");
- }
-
- #[test]
- fn test_shr() {
- fn check(s: &str, shift: uint, ans: &str) {
- let opt_biguint: Option<BigUint> =
- FromStrRadix::from_str_radix(s, 16);
- let bu = (opt_biguint.unwrap() >> shift).to_str_radix(16);
- assert_eq!(bu.as_slice(), ans);
- }
-
- check("0", 3, "0");
- check("f", 3, "1");
-
- check("1" + "0000" + "0000" + "0000" + "0001" + "0000" + "0000" + "0000" + "0001", 3,
- "" + "2000" + "0000" + "0000" + "0000" + "2000" + "0000" + "0000" + "0000");
- check("1" + "0000" + "0001" + "0000" + "0001", 2,
- "" + "4000" + "0000" + "4000" + "0000");
- check("1" + "0001" + "0001", 1,
- "" + "8000" + "8000");
-
- check("2" + "0000" + "0000" + "0000" + "0001" + "0000" + "0000" + "0000" + "0001", 67,
- "" + "4000" + "0000" + "0000" + "0000");
- check("2" + "0000" + "0001" + "0000" + "0001", 35,
- "" + "4000" + "0000");
- check("2" + "0001" + "0001", 19,
- "" + "4000");
-
- check("1" + "0000" + "0000" + "0000" + "0000", 1,
- "" + "8000" + "0000" + "0000" + "0000");
- check("1" + "0000" + "0000", 1,
- "" + "8000" + "0000");
- check("1" + "0000", 1,
- "" + "8000");
- check("f" + "edcb" + "a987" + "6543" + "210f" + "edcb" + "a987" + "6543" + "2100", 4,
- "" + "fedc" + "ba98" + "7654" + "3210" + "fedc" + "ba98" + "7654" + "3210");
-
- check("888877776666555544443333222211110000", 16,
- "88887777666655554444333322221111");
- }
-
- #[cfg(target_word_size = "32")]
- #[test]
- fn test_convert_i64() {
- fn check(b1: BigUint, i: i64) {
- let b2: BigUint = FromPrimitive::from_i64(i).unwrap();
- assert!(b1 == b2);
- assert!(b1.to_i64().unwrap() == i);
- }
-
- check(Zero::zero(), 0);
- check(One::one(), 1);
- check(i64::MAX.to_biguint().unwrap(), i64::MAX);
-
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1 ]), (1 << (2*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 1 ]), (1 << (2*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1 ]), (1 << (3*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 0, 1 ]), (1 << (3*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1, -1 >> 1]), i64::MAX);
-
- assert_eq!(i64::MIN.to_biguint(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1, -1 ]).to_i64(), None);
- assert_eq!(BigUint::new(~[ 0, 0, 0, 0, 1]).to_i64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_i64(), None);
- }
-
- #[cfg(target_word_size = "64")]
- #[test]
- fn test_convert_i64() {
- fn check(b1: BigUint, i: i64) {
- let b2: BigUint = FromPrimitive::from_i64(i).unwrap();
- assert!(b1 == b2);
- assert!(b1.to_i64().unwrap() == i);
- }
-
- check(Zero::zero(), 0);
- check(One::one(), 1);
- check(i64::MAX.to_biguint().unwrap(), i64::MAX);
-
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1 >> 1]), i64::MAX);
-
- assert_eq!(i64::MIN.to_biguint(), None);
- assert_eq!(BigUint::new(~[-1, -1 ]).to_i64(), None);
- assert_eq!(BigUint::new(~[ 0, 0, 1]).to_i64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1]).to_i64(), None);
- }
-
- #[cfg(target_word_size = "32")]
- #[test]
- fn test_convert_u64() {
- fn check(b1: BigUint, u: u64) {
- let b2: BigUint = FromPrimitive::from_u64(u).unwrap();
- assert!(b1 == b2);
- assert!(b1.to_u64().unwrap() == u);
- }
-
- check(Zero::zero(), 0);
- check(One::one(), 1);
- check(u64::MIN.to_biguint().unwrap(), u64::MIN);
- check(u64::MAX.to_biguint().unwrap(), u64::MAX);
-
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1 ]), (1 << (2*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 1 ]), (1 << (2*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1 ]), (1 << (3*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 0, 1]), (1 << (3*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1, -1]), u64::MAX);
-
- assert_eq!(BigUint::new(~[ 0, 0, 0, 0, 1]).to_u64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_u64(), None);
- }
-
- #[cfg(target_word_size = "64")]
- #[test]
- fn test_convert_u64() {
- fn check(b1: BigUint, u: u64) {
- let b2: BigUint = FromPrimitive::from_u64(u).unwrap();
- assert!(b1 == b2);
- assert!(b1.to_u64().unwrap() == u);
- }
-
- check(Zero::zero(), 0);
- check(One::one(), 1);
- check(u64::MIN.to_biguint().unwrap(), u64::MIN);
- check(u64::MAX.to_biguint().unwrap(), u64::MAX);
-
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1]), u64::MAX);
-
- assert_eq!(BigUint::new(~[ 0, 0, 1]).to_u64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1]).to_u64(), None);
- }
-
- #[test]
- fn test_convert_to_bigint() {
- fn check(n: BigUint, ans: BigInt) {
- assert_eq!(n.to_bigint().unwrap(), ans);
- assert_eq!(n.to_bigint().unwrap().to_biguint().unwrap(), n);
- }
- check(Zero::zero(), Zero::zero());
- check(BigUint::new(~[1,2,3]),
- BigInt::from_biguint(Plus, BigUint::new(~[1,2,3])));
- }
-
- static sum_triples: &'static [(&'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit])] = &[
- (&[], &[], &[]),
- (&[], &[ 1], &[ 1]),
- (&[ 1], &[ 1], &[ 2]),
- (&[ 1], &[ 1, 1], &[ 2, 1]),
- (&[ 1], &[-1], &[ 0, 1]),
- (&[ 1], &[-1, -1], &[ 0, 0, 1]),
- (&[-1, -1], &[-1, -1], &[-2, -1, 1]),
- (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
- (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
- ];
-
- #[test]
- fn test_add() {
- for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
-
- assert!(a + b == c);
- assert!(b + a == c);
- }
- }
-
- #[test]
- fn test_sub() {
- for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
-
- assert!(c - a == b);
- assert!(c - b == a);
- }
- }
-
- static mul_triples: &'static [(&'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit])] = &[
- (&[], &[], &[]),
- (&[], &[ 1], &[]),
- (&[ 2], &[], &[]),
- (&[ 1], &[ 1], &[1]),
- (&[ 2], &[ 3], &[ 6]),
- (&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
- (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
- (&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
- (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
- (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
- (&[-1], &[-1], &[ 1, -2]),
- (&[-1, -1], &[-1], &[ 1, -1, -2]),
- (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
- (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
- (&[-1/2 + 1], &[ 2], &[ 0, 1]),
- (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]),
- (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
- (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
- (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
- (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
- (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
- ];
-
- static div_rem_quadruples: &'static [(&'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit])]
- = &[
- (&[ 1], &[ 2], &[], &[1]),
- (&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
- (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
- (&[ 0, 1], &[-1], &[1], &[1]),
- (&[-1, -1], &[-2], &[2, 1], &[3])
- ];
-
- #[test]
- fn test_mul() {
- for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
-
- assert!(a * b == c);
- assert!(b * a == c);
- }
-
- for elm in div_rem_quadruples.iter() {
- let (aVec, bVec, cVec, dVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
- let d = BigUint::from_slice(dVec);
-
- assert!(a == b * c + d);
- assert!(a == c * b + d);
- }
- }
-
- #[test]
- fn test_div_rem() {
- for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
-
- if !a.is_zero() {
- assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero()));
- }
- if !b.is_zero() {
- assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero()));
- }
- }
-
- for elm in div_rem_quadruples.iter() {
- let (aVec, bVec, cVec, dVec) = *elm;
- let a = BigUint::from_slice(aVec);
- let b = BigUint::from_slice(bVec);
- let c = BigUint::from_slice(cVec);
- let d = BigUint::from_slice(dVec);
-
- if !b.is_zero() { assert!(a.div_rem(&b) == (c, d)); }
- }
- }
-
- #[test]
- fn test_gcd() {
- fn check(a: uint, b: uint, c: uint) {
- let big_a: BigUint = FromPrimitive::from_uint(a).unwrap();
- let big_b: BigUint = FromPrimitive::from_uint(b).unwrap();
- let big_c: BigUint = FromPrimitive::from_uint(c).unwrap();
-
- assert_eq!(big_a.gcd(&big_b), big_c);
- }
-
- check(10, 2, 2);
- check(10, 3, 1);
- check(0, 3, 3);
- check(3, 3, 3);
- check(56, 42, 14);
- }
-
- #[test]
- fn test_lcm() {
- fn check(a: uint, b: uint, c: uint) {
- let big_a: BigUint = FromPrimitive::from_uint(a).unwrap();
- let big_b: BigUint = FromPrimitive::from_uint(b).unwrap();
- let big_c: BigUint = FromPrimitive::from_uint(c).unwrap();
-
- assert_eq!(big_a.lcm(&big_b), big_c);
- }
-
- check(1, 0, 0);
- check(0, 1, 0);
- check(1, 1, 1);
- check(8, 9, 72);
- check(11, 5, 55);
- check(99, 17, 1683);
- }
-
- #[test]
- fn test_is_even() {
- let one: BigUint = FromStr::from_str("1").unwrap();
- let two: BigUint = FromStr::from_str("2").unwrap();
- let thousand: BigUint = FromStr::from_str("1000").unwrap();
- let big: BigUint = FromStr::from_str("1000000000000000000000").unwrap();
- let bigger: BigUint = FromStr::from_str("1000000000000000000001").unwrap();
- assert!(one.is_odd());
- assert!(two.is_even());
- assert!(thousand.is_even());
- assert!(big.is_even());
- assert!(bigger.is_odd());
- assert!((one << 64).is_even());
- assert!(((one << 64) + one).is_odd());
- }
-
- fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
- let bits = BigDigit::bits;
- ~[( Zero::zero(), ~[
- (2, ~"0"), (3, ~"0")
- ]), ( BigUint::from_slice([ 0xff ]), ~[
- (2, ~"11111111"),
- (3, ~"100110"),
- (4, ~"3333"),
- (5, ~"2010"),
- (6, ~"1103"),
- (7, ~"513"),
- (8, ~"377"),
- (9, ~"313"),
- (10, ~"255"),
- (11, ~"212"),
- (12, ~"193"),
- (13, ~"168"),
- (14, ~"143"),
- (15, ~"120"),
- (16, ~"ff")
- ]), ( BigUint::from_slice([ 0xfff ]), ~[
- (2, ~"111111111111"),
- (4, ~"333333"),
- (16, ~"fff")
- ]), ( BigUint::from_slice([ 1, 2 ]), ~[
- (2,
- ~"10" +
- str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
- (4,
- ~"2" +
- str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
- (10, match bits {
- 32 => ~"8589934593", 16 => ~"131073", _ => fail!()
- }),
- (16,
- ~"2" +
- str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
- ]), ( BigUint::from_slice([ 1, 2, 3 ]), ~[
- (2,
- ~"11" +
- str::from_chars(vec::from_elem(bits - 2, '0')) + "10" +
- str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
- (4,
- ~"3" +
- str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "2" +
- str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
- (10, match bits {
- 32 => ~"55340232229718589441",
- 16 => ~"12885032961",
- _ => fail!()
- }),
- (16, ~"3" +
- str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "2" +
- str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
- ]) ]
- }
-
- #[test]
- fn test_to_str_radix() {
- let r = to_str_pairs();
- for num_pair in r.iter() {
- let &(ref n, ref rs) = num_pair;
- for str_pair in rs.iter() {
- let &(ref radix, ref str) = str_pair;
- assert_eq!(&n.to_str_radix(*radix), str);
- }
- }
- }
-
- #[test]
- fn test_from_str_radix() {
- let r = to_str_pairs();
- for num_pair in r.iter() {
- let &(ref n, ref rs) = num_pair;
- for str_pair in rs.iter() {
- let &(ref radix, ref str) = str_pair;
- assert_eq!(n, &FromStrRadix::from_str_radix(*str, *radix).unwrap());
- }
- }
-
- let zed: Option<BigUint> = FromStrRadix::from_str_radix("Z", 10);
- assert_eq!(zed, None);
- let blank: Option<BigUint> = FromStrRadix::from_str_radix("_", 2);
- assert_eq!(blank, None);
- let minus_one: Option<BigUint> = FromStrRadix::from_str_radix("-1",
- 10);
- assert_eq!(minus_one, None);
- }
-
- #[test]
- fn test_factor() {
- fn factor(n: uint) -> BigUint {
- let mut f: BigUint = One::one();
- for i in range(2, n + 1) {
- // FIXME(#6102): Assignment operator for BigInt causes ICE
- // f *= FromPrimitive::from_uint(i);
- f = f * FromPrimitive::from_uint(i).unwrap();
- }
- return f;
- }
-
- fn check(n: uint, s: &str) {
- let n = factor(n);
- let ans = match FromStrRadix::from_str_radix(s, 10) {
- Some(x) => x, None => fail!()
- };
- assert_eq!(n, ans);
- }
-
- check(3, "6");
- check(10, "3628800");
- check(20, "2432902008176640000");
- check(30, "265252859812191058636308480000000");
- }
-
- #[test]
- fn test_bits() {
- assert_eq!(BigUint::new(~[0,0,0,0]).bits(), 0);
- let n: BigUint = FromPrimitive::from_uint(0).unwrap();
- assert_eq!(n.bits(), 0);
- let n: BigUint = FromPrimitive::from_uint(1).unwrap();
- assert_eq!(n.bits(), 1);
- let n: BigUint = FromPrimitive::from_uint(3).unwrap();
- assert_eq!(n.bits(), 2);
- let n: BigUint = FromStrRadix::from_str_radix("4000000000", 16).unwrap();
- assert_eq!(n.bits(), 39);
- let one: BigUint = One::one();
- assert_eq!((one << 426).bits(), 427);
- }
-
- #[test]
- fn test_rand() {
- let mut rng = task_rng();
- let _n: BigUint = rng.gen_biguint(137);
- assert!(rng.gen_biguint(0).is_zero());
- }
-
- #[test]
- fn test_rand_range() {
- let mut rng = task_rng();
-
- for _ in range(0, 10) {
- assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_uint(236).unwrap(),
- &FromPrimitive::from_uint(237).unwrap()),
- FromPrimitive::from_uint(236).unwrap());
- }
-
- let l = FromPrimitive::from_uint(403469000 + 2352).unwrap();
- let u = FromPrimitive::from_uint(403469000 + 3513).unwrap();
- for _ in range(0, 1000) {
- let n: BigUint = rng.gen_biguint_below(&u);
- assert!(n < u);
-
- let n: BigUint = rng.gen_biguint_range(&l, &u);
- assert!(n >= l);
- assert!(n < u);
- }
- }
-
- #[test]
- #[should_fail]
- fn test_zero_rand_range() {
- task_rng().gen_biguint_range(&FromPrimitive::from_uint(54).unwrap(),
- &FromPrimitive::from_uint(54).unwrap());
- }
-
- #[test]
- #[should_fail]
- fn test_negative_rand_range() {
- let mut rng = task_rng();
- let l = FromPrimitive::from_uint(2352).unwrap();
- let u = FromPrimitive::from_uint(3513).unwrap();
- // Switching u and l should fail:
- let _n: BigUint = rng.gen_biguint_range(&u, &l);
- }
-}
-
-#[cfg(test)]
-mod bigint_tests {
- use super::*;
- use super::RandBigInt;
-
- use std::cmp::{Less, Equal, Greater};
- use std::i64;
- use std::num::{Zero, One, FromStrRadix};
- use std::num::{ToPrimitive, FromPrimitive};
- use std::rand::{task_rng};
- use std::u64;
-
- #[test]
- fn test_from_biguint() {
- fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) {
- let inp = BigInt::from_biguint(inp_s, FromPrimitive::from_uint(inp_n).unwrap());
- let ans = BigInt { sign: ans_s, data: FromPrimitive::from_uint(ans_n).unwrap()};
- assert_eq!(inp, ans);
- }
- check(Plus, 1, Plus, 1);
- check(Plus, 0, Zero, 0);
- check(Minus, 1, Minus, 1);
- check(Zero, 1, Zero, 0);
- }
-
- #[test]
- fn test_cmp() {
- let vs = [ &[2 as BigDigit], &[1, 1], &[2, 1], &[1, 1, 1] ];
- let mut nums = ~[];
- for s in vs.rev_iter() {
- nums.push(BigInt::from_slice(Minus, *s));
- }
- nums.push(Zero::zero());
- nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
-
- for (i, ni) in nums.iter().enumerate() {
- for (j0, nj) in nums.slice(i, nums.len()).iter().enumerate() {
- let j = i + j0;
- if i == j {
- assert_eq!(ni.cmp(nj), Equal);
- assert_eq!(nj.cmp(ni), Equal);
- assert_eq!(ni, nj);
- assert!(!(ni != nj));
- assert!(ni <= nj);
- assert!(ni >= nj);
- assert!(!(ni < nj));
- assert!(!(ni > nj));
- } else {
- assert_eq!(ni.cmp(nj), Less);
- assert_eq!(nj.cmp(ni), Greater);
-
- assert!(!(ni == nj));
- assert!(ni != nj);
-
- assert!(ni <= nj);
- assert!(!(ni >= nj));
- assert!(ni < nj);
- assert!(!(ni > nj));
-
- assert!(!(nj <= ni));
- assert!(nj >= ni);
- assert!(!(nj < ni));
- assert!(nj > ni);
- }
- }
- }
- }
-
- #[test]
- fn test_convert_i64() {
- fn check(b1: BigInt, i: i64) {
- let b2: BigInt = FromPrimitive::from_i64(i).unwrap();
- assert!(b1 == b2);
- assert!(b1.to_i64().unwrap() == i);
- }
-
- check(Zero::zero(), 0);
- check(One::one(), 1);
- check(i64::MIN.to_bigint().unwrap(), i64::MIN);
- check(i64::MAX.to_bigint().unwrap(), i64::MAX);
-
- assert_eq!(
- (i64::MAX as u64 + 1).to_bigint().unwrap().to_i64(),
- None);
-
- assert_eq!(
- BigInt::from_biguint(Plus, BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
- None);
-
- assert_eq!(
- BigInt::from_biguint(Minus, BigUint::new(~[1, 0, 0, 1<<(BigDigit::bits-1)])).to_i64(),
- None);
-
- assert_eq!(
- BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
- None);
- }
-
- #[test]
- fn test_convert_u64() {
- fn check(b1: BigInt, u: u64) {
- let b2: BigInt = FromPrimitive::from_u64(u).unwrap();
- assert!(b1 == b2);
- assert!(b1.to_u64().unwrap() == u);
- }
-
- check(Zero::zero(), 0);
- check(One::one(), 1);
- check(u64::MIN.to_bigint().unwrap(), u64::MIN);
- check(u64::MAX.to_bigint().unwrap(), u64::MAX);
-
- assert_eq!(
- BigInt::from_biguint(Plus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(),
- None);
-
- let max_value: BigUint = FromPrimitive::from_u64(u64::MAX).unwrap();
- assert_eq!(BigInt::from_biguint(Minus, max_value).to_u64(), None);
- assert_eq!(BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(), None);
- }
-
- #[test]
- fn test_convert_to_biguint() {
- fn check(n: BigInt, ans_1: BigUint) {
- assert_eq!(n.to_biguint().unwrap(), ans_1);
- assert_eq!(n.to_biguint().unwrap().to_bigint().unwrap(), n);
- }
- let zero: BigInt = Zero::zero();
- let unsigned_zero: BigUint = Zero::zero();
- let positive = BigInt::from_biguint(
- Plus, BigUint::new(~[1,2,3]));
- let negative = -positive;
-
- check(zero, unsigned_zero);
- check(positive, BigUint::new(~[1,2,3]));
-
- assert_eq!(negative.to_biguint(), None);
- }
-
- static sum_triples: &'static [(&'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit])] = &[
- (&[], &[], &[]),
- (&[], &[ 1], &[ 1]),
- (&[ 1], &[ 1], &[ 2]),
- (&[ 1], &[ 1, 1], &[ 2, 1]),
- (&[ 1], &[-1], &[ 0, 1]),
- (&[ 1], &[-1, -1], &[ 0, 0, 1]),
- (&[-1, -1], &[-1, -1], &[-2, -1, 1]),
- (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
- (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
- ];
-
- #[test]
- fn test_add() {
- for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
-
- assert!(a + b == c);
- assert!(b + a == c);
- assert!(c + (-a) == b);
- assert!(c + (-b) == a);
- assert!(a + (-c) == (-b));
- assert!(b + (-c) == (-a));
- assert!((-a) + (-b) == (-c))
- assert!(a + (-a) == Zero::zero());
- }
- }
-
- #[test]
- fn test_sub() {
- for elm in sum_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
-
- assert!(c - a == b);
- assert!(c - b == a);
- assert!((-b) - a == (-c))
- assert!((-a) - b == (-c))
- assert!(b - (-a) == c);
- assert!(a - (-b) == c);
- assert!((-c) - (-a) == (-b));
- assert!(a - a == Zero::zero());
- }
- }
-
- static mul_triples: &'static [(&'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit])] = &[
- (&[], &[], &[]),
- (&[], &[ 1], &[]),
- (&[ 2], &[], &[]),
- (&[ 1], &[ 1], &[1]),
- (&[ 2], &[ 3], &[ 6]),
- (&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
- (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
- (&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
- (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
- (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
- (&[-1], &[-1], &[ 1, -2]),
- (&[-1, -1], &[-1], &[ 1, -1, -2]),
- (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
- (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
- (&[-1/2 + 1], &[ 2], &[ 0, 1]),
- (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]),
- (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
- (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
- (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
- (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
- (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
- ];
-
- static div_rem_quadruples: &'static [(&'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit],
- &'static [BigDigit])]
- = &[
- (&[ 1], &[ 2], &[], &[1]),
- (&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
- (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
- (&[ 0, 1], &[-1], &[1], &[1]),
- (&[-1, -1], &[-2], &[2, 1], &[3])
- ];
-
- #[test]
- fn test_mul() {
- for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
-
- assert!(a * b == c);
- assert!(b * a == c);
-
- assert!((-a) * b == -c);
- assert!((-b) * a == -c);
- }
-
- for elm in div_rem_quadruples.iter() {
- let (aVec, bVec, cVec, dVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
- let d = BigInt::from_slice(Plus, dVec);
-
- assert!(a == b * c + d);
- assert!(a == c * b + d);
- }
- }
-
- #[test]
- fn test_div_mod_floor() {
- fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
- let (d, m) = a.div_mod_floor(b);
- if !m.is_zero() {
- assert_eq!(m.sign, b.sign);
- }
- assert!(m.abs() <= b.abs());
- assert!(*a == b * d + m);
- assert!(d == *ans_d);
- assert!(m == *ans_m);
- }
-
- fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) {
- if m.is_zero() {
- check_sub(a, b, d, m);
- check_sub(a, &b.neg(), &d.neg(), m);
- check_sub(&a.neg(), b, &d.neg(), m);
- check_sub(&a.neg(), &b.neg(), d, m);
- } else {
- check_sub(a, b, d, m);
- check_sub(a, &b.neg(), &(d.neg() - One::one()), &(m - *b));
- check_sub(&a.neg(), b, &(d.neg() - One::one()), &(b - *m));
- check_sub(&a.neg(), &b.neg(), d, &m.neg());
- }
- }
-
- for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
-
- if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
- if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
- }
-
- for elm in div_rem_quadruples.iter() {
- let (aVec, bVec, cVec, dVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
- let d = BigInt::from_slice(Plus, dVec);
-
- if !b.is_zero() {
- check(&a, &b, &c, &d);
- }
- }
- }
-
-
- #[test]
- fn test_div_rem() {
- fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
- let (q, r) = a.div_rem(b);
- if !r.is_zero() {
- assert_eq!(r.sign, a.sign);
- }
- assert!(r.abs() <= b.abs());
- assert!(*a == b * q + r);
- assert!(q == *ans_q);
- assert!(r == *ans_r);
- }
-
- fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) {
- check_sub(a, b, q, r);
- check_sub(a, &b.neg(), &q.neg(), r);
- check_sub(&a.neg(), b, &q.neg(), &r.neg());
- check_sub(&a.neg(), &b.neg(), q, &r.neg());
- }
- for elm in mul_triples.iter() {
- let (aVec, bVec, cVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
-
- if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
- if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
- }
-
- for elm in div_rem_quadruples.iter() {
- let (aVec, bVec, cVec, dVec) = *elm;
- let a = BigInt::from_slice(Plus, aVec);
- let b = BigInt::from_slice(Plus, bVec);
- let c = BigInt::from_slice(Plus, cVec);
- let d = BigInt::from_slice(Plus, dVec);
-
- if !b.is_zero() {
- check(&a, &b, &c, &d);
- }
- }
- }
-
- #[test]
- fn test_gcd() {
- fn check(a: int, b: int, c: int) {
- let big_a: BigInt = FromPrimitive::from_int(a).unwrap();
- let big_b: BigInt = FromPrimitive::from_int(b).unwrap();
- let big_c: BigInt = FromPrimitive::from_int(c).unwrap();
-
- assert_eq!(big_a.gcd(&big_b), big_c);
- }
-
- check(10, 2, 2);
- check(10, 3, 1);
- check(0, 3, 3);
- check(3, 3, 3);
- check(56, 42, 14);
- check(3, -3, 3);
- check(-6, 3, 3);
- check(-4, -2, 2);
- }
-
- #[test]
- fn test_lcm() {
- fn check(a: int, b: int, c: int) {
- let big_a: BigInt = FromPrimitive::from_int(a).unwrap();
- let big_b: BigInt = FromPrimitive::from_int(b).unwrap();
- let big_c: BigInt = FromPrimitive::from_int(c).unwrap();
-
- assert_eq!(big_a.lcm(&big_b), big_c);
- }
-
- check(1, 0, 0);
- check(0, 1, 0);
- check(1, 1, 1);
- check(-1, 1, 1);
- check(1, -1, 1);
- check(-1, -1, 1);
- check(8, 9, 72);
- check(11, 5, 55);
- }
-
- #[test]
- fn test_abs_sub() {
- let zero: BigInt = Zero::zero();
- let one: BigInt = One::one();
- assert_eq!((-one).abs_sub(&one), zero);
- let one: BigInt = One::one();
- let zero: BigInt = Zero::zero();
- assert_eq!(one.abs_sub(&one), zero);
- let one: BigInt = One::one();
- let zero: BigInt = Zero::zero();
- assert_eq!(one.abs_sub(&zero), one);
- let one: BigInt = One::one();
- let two: BigInt = FromPrimitive::from_int(2).unwrap();
- assert_eq!(one.abs_sub(&-one), two);
- }
-
- #[test]
- fn test_to_str_radix() {
- fn check(n: int, ans: &str) {
- let n: BigInt = FromPrimitive::from_int(n).unwrap();
- assert!(ans == n.to_str_radix(10));
- }
- check(10, "10");
- check(1, "1");
- check(0, "0");
- check(-1, "-1");
- check(-10, "-10");
- }
-
-
- #[test]
- fn test_from_str_radix() {
- fn check(s: &str, ans: Option<int>) {
- let ans = ans.map(|n| {
- let x: BigInt = FromPrimitive::from_int(n).unwrap();
- x
- });
- assert_eq!(FromStrRadix::from_str_radix(s, 10), ans);
- }
- check("10", Some(10));
- check("1", Some(1));
- check("0", Some(0));
- check("-1", Some(-1));
- check("-10", Some(-10));
- check("Z", None);
- check("_", None);
-
- // issue 10522, this hit an edge case that caused it to
- // attempt to allocate a vector of size (-1u) == huge.
- let x: BigInt = from_str("1" + "0".repeat(36)).unwrap();
- let _y = x.to_str();
- }
-
- #[test]
- fn test_neg() {
- assert!(-BigInt::new(Plus, ~[1, 1, 1]) ==
- BigInt::new(Minus, ~[1, 1, 1]));
- assert!(-BigInt::new(Minus, ~[1, 1, 1]) ==
- BigInt::new(Plus, ~[1, 1, 1]));
- let zero: BigInt = Zero::zero();
- assert_eq!(-zero, zero);
- }
-
- #[test]
- fn test_rand() {
- let mut rng = task_rng();
- let _n: BigInt = rng.gen_bigint(137);
- assert!(rng.gen_bigint(0).is_zero());
- }
-
- #[test]
- fn test_rand_range() {
- let mut rng = task_rng();
-
- for _ in range(0, 10) {
- assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_uint(236).unwrap(),
- &FromPrimitive::from_uint(237).unwrap()),
- FromPrimitive::from_uint(236).unwrap());
- }
-
- fn check(l: BigInt, u: BigInt) {
- let mut rng = task_rng();
- for _ in range(0, 1000) {
- let n: BigInt = rng.gen_bigint_range(&l, &u);
- assert!(n >= l);
- assert!(n < u);
- }
- }
- let l: BigInt = FromPrimitive::from_uint(403469000 + 2352).unwrap();
- let u: BigInt = FromPrimitive::from_uint(403469000 + 3513).unwrap();
- check( l.clone(), u.clone());
- check(-l.clone(), u.clone());
- check(-u.clone(), -l.clone());
- }
-
- #[test]
- #[should_fail]
- fn test_zero_rand_range() {
- task_rng().gen_bigint_range(&FromPrimitive::from_int(54).unwrap(),
- &FromPrimitive::from_int(54).unwrap());
- }
-
- #[test]
- #[should_fail]
- fn test_negative_rand_range() {
- let mut rng = task_rng();
- let l = FromPrimitive::from_uint(2352).unwrap();
- let u = FromPrimitive::from_uint(3513).unwrap();
- // Switching u and l should fail:
- let _n: BigInt = rng.gen_bigint_range(&u, &l);
- }
-}
-
-#[cfg(test)]
-mod bench {
- use super::*;
- use std::iter;
- use std::mem::replace;
- use std::num::{FromPrimitive, Zero, One};
- use extra::test::BenchHarness;
-
- fn factorial(n: uint) -> BigUint {
- let mut f: BigUint = One::one();
- for i in iter::range_inclusive(1, n) {
- f = f * FromPrimitive::from_uint(i).unwrap();
- }
- f
- }
-
- fn fib(n: uint) -> BigUint {
- let mut f0: BigUint = Zero::zero();
- let mut f1: BigUint = One::one();
- for _ in range(0, n) {
- let f2 = f0 + f1;
- f0 = replace(&mut f1, f2);
- }
- f0
- }
-
- #[bench]
- fn factorial_100(bh: &mut BenchHarness) {
- bh.iter(|| {
- factorial(100);
- });
- }
-
- #[bench]
- fn fib_100(bh: &mut BenchHarness) {
- bh.iter(|| {
- fib(100);
- });
- }
-
- #[bench]
- fn to_str(bh: &mut BenchHarness) {
- let fac = factorial(100);
- let fib = fib(100);
- bh.iter(|| {
- fac.to_str();
- });
- bh.iter(|| {
- fib.to_str();
- });
- }
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-//! Complex numbers.
-
-use std::num::{Zero,One,ToStrRadix};
-
-// FIXME #1284: handle complex NaN & infinity etc. This
-// probably doesn't map to C's _Complex correctly.
-
-// FIXME #5734:: Need generic sin/cos for .to/from_polar().
-// FIXME #5735: Need generic sqrt to implement .norm().
-
-
-/// A complex number in Cartesian form.
-#[deriving(Eq,Clone)]
-pub struct Cmplx<T> {
- /// Real portion of the complex number
- re: T,
- /// Imaginary portion of the complex number
- im: T
-}
-
-pub type Complex32 = Cmplx<f32>;
-pub type Complex64 = Cmplx<f64>;
-
-impl<T: Clone + Num> Cmplx<T> {
- /// Create a new Cmplx
- #[inline]
- pub fn new(re: T, im: T) -> Cmplx<T> {
- Cmplx { re: re, im: im }
- }
-
- /**
- Returns the square of the norm (since `T` doesn't necessarily
- have a sqrt function), i.e. `re^2 + im^2`.
- */
- #[inline]
- pub fn norm_sqr(&self) -> T {
- self.re * self.re + self.im * self.im
- }
-
-
- /// Returns the complex conjugate. i.e. `re - i im`
- #[inline]
- pub fn conj(&self) -> Cmplx<T> {
- Cmplx::new(self.re.clone(), -self.im)
- }
-
-
- /// Multiplies `self` by the scalar `t`.
- #[inline]
- pub fn scale(&self, t: T) -> Cmplx<T> {
- Cmplx::new(self.re * t, self.im * t)
- }
-
- /// Divides `self` by the scalar `t`.
- #[inline]
- pub fn unscale(&self, t: T) -> Cmplx<T> {
- Cmplx::new(self.re / t, self.im / t)
- }
-
- /// Returns `1/self`
- #[inline]
- pub fn inv(&self) -> Cmplx<T> {
- let norm_sqr = self.norm_sqr();
- Cmplx::new(self.re / norm_sqr,
- -self.im / norm_sqr)
- }
-}
-
-impl<T: Clone + Real> Cmplx<T> {
- /// Calculate |self|
- #[inline]
- pub fn norm(&self) -> T {
- self.re.hypot(&self.im)
- }
-}
-
-impl<T: Clone + Real> Cmplx<T> {
- /// Calculate the principal Arg of self.
- #[inline]
- pub fn arg(&self) -> T {
- self.im.atan2(&self.re)
- }
- /// Convert to polar form (r, theta), such that `self = r * exp(i
- /// * theta)`
- #[inline]
- pub fn to_polar(&self) -> (T, T) {
- (self.norm(), self.arg())
- }
- /// Convert a polar representation into a complex number.
- #[inline]
- pub fn from_polar(r: &T, theta: &T) -> Cmplx<T> {
- Cmplx::new(r * theta.cos(), r * theta.sin())
- }
-}
-
-/* arithmetic */
-// (a + i b) + (c + i d) == (a + c) + i (b + d)
-impl<T: Clone + Num> Add<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
- #[inline]
- fn add(&self, other: &Cmplx<T>) -> Cmplx<T> {
- Cmplx::new(self.re + other.re, self.im + other.im)
- }
-}
-// (a + i b) - (c + i d) == (a - c) + i (b - d)
-impl<T: Clone + Num> Sub<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
- #[inline]
- fn sub(&self, other: &Cmplx<T>) -> Cmplx<T> {
- Cmplx::new(self.re - other.re, self.im - other.im)
- }
-}
-// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
-impl<T: Clone + Num> Mul<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
- #[inline]
- fn mul(&self, other: &Cmplx<T>) -> Cmplx<T> {
- Cmplx::new(self.re*other.re - self.im*other.im,
- self.re*other.im + self.im*other.re)
- }
-}
-
-// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
-// == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
-impl<T: Clone + Num> Div<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
- #[inline]
- fn div(&self, other: &Cmplx<T>) -> Cmplx<T> {
- let norm_sqr = other.norm_sqr();
- Cmplx::new((self.re*other.re + self.im*other.im) / norm_sqr,
- (self.im*other.re - self.re*other.im) / norm_sqr)
- }
-}
-
-impl<T: Clone + Num> Neg<Cmplx<T>> for Cmplx<T> {
- #[inline]
- fn neg(&self) -> Cmplx<T> {
- Cmplx::new(-self.re, -self.im)
- }
-}
-
-/* constants */
-impl<T: Clone + Num> Zero for Cmplx<T> {
- #[inline]
- fn zero() -> Cmplx<T> {
- Cmplx::new(Zero::zero(), Zero::zero())
- }
-
- #[inline]
- fn is_zero(&self) -> bool {
- self.re.is_zero() && self.im.is_zero()
- }
-}
-
-impl<T: Clone + Num> One for Cmplx<T> {
- #[inline]
- fn one() -> Cmplx<T> {
- Cmplx::new(One::one(), Zero::zero())
- }
-}
-
-/* string conversions */
-impl<T: ToStr + Num + Ord> ToStr for Cmplx<T> {
- fn to_str(&self) -> ~str {
- if self.im < Zero::zero() {
- format!("{}-{}i", self.re.to_str(), (-self.im).to_str())
- } else {
- format!("{}+{}i", self.re.to_str(), self.im.to_str())
- }
- }
-}
-
-impl<T: ToStrRadix + Num + Ord> ToStrRadix for Cmplx<T> {
- fn to_str_radix(&self, radix: uint) -> ~str {
- if self.im < Zero::zero() {
- format!("{}-{}i", self.re.to_str_radix(radix), (-self.im).to_str_radix(radix))
- } else {
- format!("{}+{}i", self.re.to_str_radix(radix), self.im.to_str_radix(radix))
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- #[allow(non_uppercase_statics)];
-
- use super::*;
- use std::num::{Zero,One,Real};
-
- pub static _0_0i : Complex64 = Cmplx { re: 0.0, im: 0.0 };
- pub static _1_0i : Complex64 = Cmplx { re: 1.0, im: 0.0 };
- pub static _1_1i : Complex64 = Cmplx { re: 1.0, im: 1.0 };
- pub static _0_1i : Complex64 = Cmplx { re: 0.0, im: 1.0 };
- pub static _neg1_1i : Complex64 = Cmplx { re: -1.0, im: 1.0 };
- pub static _05_05i : Complex64 = Cmplx { re: 0.5, im: 0.5 };
- pub static all_consts : [Complex64, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];
-
- #[test]
- fn test_consts() {
- // check our constants are what Cmplx::new creates
- fn test(c : Complex64, r : f64, i: f64) {
- assert_eq!(c, Cmplx::new(r,i));
- }
- test(_0_0i, 0.0, 0.0);
- test(_1_0i, 1.0, 0.0);
- test(_1_1i, 1.0, 1.0);
- test(_neg1_1i, -1.0, 1.0);
- test(_05_05i, 0.5, 0.5);
-
- assert_eq!(_0_0i, Zero::zero());
- assert_eq!(_1_0i, One::one());
- }
-
- #[test]
- #[ignore(cfg(target_arch = "x86"))]
- // FIXME #7158: (maybe?) currently failing on x86.
- fn test_norm() {
- fn test(c: Complex64, ns: f64) {
- assert_eq!(c.norm_sqr(), ns);
- assert_eq!(c.norm(), ns.sqrt())
- }
- test(_0_0i, 0.0);
- test(_1_0i, 1.0);
- test(_1_1i, 2.0);
- test(_neg1_1i, 2.0);
- test(_05_05i, 0.5);
- }
-
- #[test]
- fn test_scale_unscale() {
- assert_eq!(_05_05i.scale(2.0), _1_1i);
- assert_eq!(_1_1i.unscale(2.0), _05_05i);
- for &c in all_consts.iter() {
- assert_eq!(c.scale(2.0).unscale(2.0), c);
- }
- }
-
- #[test]
- fn test_conj() {
- for &c in all_consts.iter() {
- assert_eq!(c.conj(), Cmplx::new(c.re, -c.im));
- assert_eq!(c.conj().conj(), c);
- }
- }
-
- #[test]
- fn test_inv() {
- assert_eq!(_1_1i.inv(), _05_05i.conj());
- assert_eq!(_1_0i.inv(), _1_0i.inv());
- }
-
- #[test]
- #[should_fail]
- #[ignore]
- fn test_inv_zero() {
- // FIXME #5736: should this really fail, or just NaN?
- _0_0i.inv();
- }
-
- #[test]
- fn test_arg() {
- fn test(c: Complex64, arg: f64) {
- assert!((c.arg() - arg).abs() < 1.0e-6)
- }
- test(_1_0i, 0.0);
- test(_1_1i, 0.25 * Real::pi());
- test(_neg1_1i, 0.75 * Real::pi());
- test(_05_05i, 0.25 * Real::pi());
- }
-
- #[test]
- fn test_polar_conv() {
- fn test(c: Complex64) {
- let (r, theta) = c.to_polar();
- assert!((c - Cmplx::from_polar(&r, &theta)).norm() < 1e-6);
- }
- for &c in all_consts.iter() { test(c); }
- }
-
- mod arith {
- use super::*;
- use std::num::Zero;
-
- #[test]
- fn test_add() {
- assert_eq!(_05_05i + _05_05i, _1_1i);
- assert_eq!(_0_1i + _1_0i, _1_1i);
- assert_eq!(_1_0i + _neg1_1i, _0_1i);
-
- for &c in all_consts.iter() {
- assert_eq!(_0_0i + c, c);
- assert_eq!(c + _0_0i, c);
- }
- }
-
- #[test]
- fn test_sub() {
- assert_eq!(_05_05i - _05_05i, _0_0i);
- assert_eq!(_0_1i - _1_0i, _neg1_1i);
- assert_eq!(_0_1i - _neg1_1i, _1_0i);
-
- for &c in all_consts.iter() {
- assert_eq!(c - _0_0i, c);
- assert_eq!(c - c, _0_0i);
- }
- }
-
- #[test]
- fn test_mul() {
- assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2.0));
- assert_eq!(_1_1i * _0_1i, _neg1_1i);
-
- // i^2 & i^4
- assert_eq!(_0_1i * _0_1i, -_1_0i);
- assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);
-
- for &c in all_consts.iter() {
- assert_eq!(c * _1_0i, c);
- assert_eq!(_1_0i * c, c);
- }
- }
- #[test]
- fn test_div() {
- assert_eq!(_neg1_1i / _0_1i, _1_1i);
- for &c in all_consts.iter() {
- if c != Zero::zero() {
- assert_eq!(c / c, _1_0i);
- }
- }
- }
- #[test]
- fn test_neg() {
- assert_eq!(-_1_0i + _0_1i, _neg1_1i);
- assert_eq!((-_0_1i) * _0_1i, _1_0i);
- for &c in all_consts.iter() {
- assert_eq!(-(-c), c);
- }
- }
- }
-
- #[test]
- fn test_to_str() {
- fn test(c : Complex64, s: ~str) {
- assert_eq!(c.to_str(), s);
- }
- test(_0_0i, ~"0+0i");
- test(_1_0i, ~"1+0i");
- test(_0_1i, ~"0+1i");
- test(_1_1i, ~"1+1i");
- test(_neg1_1i, ~"-1+1i");
- test(-_neg1_1i, ~"1-1i");
- test(_05_05i, ~"0.5+0.5i");
- }
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Rational numbers
-
-
-use std::cmp;
-use std::from_str::FromStr;
-use std::num::{Zero,One,ToStrRadix,FromStrRadix,Round};
-use super::bigint::{BigInt, BigUint, Sign, Plus, Minus};
-
-/// Represents the ratio between 2 numbers.
-#[deriving(Clone)]
-#[allow(missing_doc)]
-pub struct Ratio<T> {
- priv numer: T,
- priv denom: T
-}
-
-/// Alias for a `Ratio` of machine-sized integers.
-pub type Rational = Ratio<int>;
-pub type Rational32 = Ratio<i32>;
-pub type Rational64 = Ratio<i64>;
-
-/// Alias for arbitrary precision rationals.
-pub type BigRational = Ratio<BigInt>;
-
-impl<T: Clone + Integer + Ord>
- Ratio<T> {
- /// Create a ratio representing the integer `t`.
- #[inline]
- pub fn from_integer(t: T) -> Ratio<T> {
- Ratio::new_raw(t, One::one())
- }
-
- /// Create a ratio without checking for `denom == 0` or reducing.
- #[inline]
- pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
- Ratio { numer: numer, denom: denom }
- }
-
- /// Create a new Ratio. Fails if `denom == 0`.
- #[inline]
- pub fn new(numer: T, denom: T) -> Ratio<T> {
- if denom == Zero::zero() {
- fail!("denominator == 0");
- }
- let mut ret = Ratio::new_raw(numer, denom);
- ret.reduce();
- ret
- }
-
- /// Convert to an integer.
- #[inline]
- pub fn to_integer(&self) -> T {
- self.trunc().numer
- }
-
- /// Gets an immutable reference to the numerator.
- #[inline]
- pub fn numer<'a>(&'a self) -> &'a T {
- &self.numer
- }
-
- /// Gets an immutable reference to the denominator.
- #[inline]
- pub fn denom<'a>(&'a self) -> &'a T {
- &self.denom
- }
-
- /// Return true if the rational number is an integer (denominator is 1).
- #[inline]
- pub fn is_integer(&self) -> bool {
- self.denom == One::one()
- }
-
- /// Put self into lowest terms, with denom > 0.
- fn reduce(&mut self) {
- let g : T = self.numer.gcd(&self.denom);
-
- // FIXME(#6050): overloaded operators force moves with generic types
- // self.numer /= g;
- self.numer = self.numer / g;
- // FIXME(#6050): overloaded operators force moves with generic types
- // self.denom /= g;
- self.denom = self.denom / g;
-
- // keep denom positive!
- if self.denom < Zero::zero() {
- self.numer = -self.numer;
- self.denom = -self.denom;
- }
- }
-
- /// Return a `reduce`d copy of self.
- pub fn reduced(&self) -> Ratio<T> {
- let mut ret = self.clone();
- ret.reduce();
- ret
- }
-
- /// Return the reciprocal
- #[inline]
- pub fn recip(&self) -> Ratio<T> {
- Ratio::new_raw(self.denom.clone(), self.numer.clone())
- }
-}
-
-impl Ratio<BigInt> {
- /// Converts a float into a rational number
- pub fn from_float<T: Float>(f: T) -> Option<BigRational> {
- if !f.is_finite() {
- return None;
- }
- let (mantissa, exponent, sign) = f.integer_decode();
- let bigint_sign: Sign = if sign == 1 { Plus } else { Minus };
- if exponent < 0 {
- let one: BigInt = One::one();
- let denom: BigInt = one << ((-exponent) as uint);
- let numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
- Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom))
- } else {
- let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
- numer = numer << (exponent as uint);
- Some(Ratio::from_integer(BigInt::from_biguint(bigint_sign, numer)))
- }
- }
-}
-
-/* Comparisons */
-
-// comparing a/b and c/d is the same as comparing a*d and b*c, so we
-// abstract that pattern. The following macro takes a trait and either
-// a comma-separated list of "method name -> return value" or just
-// "method name" (return value is bool in that case)
-macro_rules! cmp_impl {
- (impl $imp:ident, $($method:ident),+) => {
- cmp_impl!(impl $imp, $($method -> bool),+)
- };
- // return something other than a Ratio<T>
- (impl $imp:ident, $($method:ident -> $res:ty),+) => {
- impl<T: Mul<T,T> + $imp> $imp for Ratio<T> {
- $(
- #[inline]
- fn $method(&self, other: &Ratio<T>) -> $res {
- (self.numer * other.denom). $method (&(self.denom*other.numer))
- }
- )+
- }
- };
-}
-cmp_impl!(impl Eq, eq, ne)
-cmp_impl!(impl TotalEq, equals)
-cmp_impl!(impl Ord, lt, gt, le, ge)
-cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering)
-
-impl<T: Clone + Integer + Ord> Orderable for Ratio<T> {
- #[inline]
- fn min(&self, other: &Ratio<T>) -> Ratio<T> {
- if *self < *other { self.clone() } else { other.clone() }
- }
-
- #[inline]
- fn max(&self, other: &Ratio<T>) -> Ratio<T> {
- if *self > *other { self.clone() } else { other.clone() }
- }
-
- #[inline]
- fn clamp(&self, mn: &Ratio<T>, mx: &Ratio<T>) -> Ratio<T> {
- if *self > *mx { mx.clone()} else
- if *self < *mn { mn.clone() } else { self.clone() }
- }
-}
-
-
-/* Arithmetic */
-// a/b * c/d = (a*c)/(b*d)
-impl<T: Clone + Integer + Ord>
- Mul<Ratio<T>,Ratio<T>> for Ratio<T> {
- #[inline]
- fn mul(&self, rhs: &Ratio<T>) -> Ratio<T> {
- Ratio::new(self.numer * rhs.numer, self.denom * rhs.denom)
- }
-}
-
-// (a/b) / (c/d) = (a*d)/(b*c)
-impl<T: Clone + Integer + Ord>
- Div<Ratio<T>,Ratio<T>> for Ratio<T> {
- #[inline]
- fn div(&self, rhs: &Ratio<T>) -> Ratio<T> {
- Ratio::new(self.numer * rhs.denom, self.denom * rhs.numer)
- }
-}
-
-// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
-macro_rules! arith_impl {
- (impl $imp:ident, $method:ident) => {
- impl<T: Clone + Integer + Ord>
- $imp<Ratio<T>,Ratio<T>> for Ratio<T> {
- #[inline]
- fn $method(&self, rhs: &Ratio<T>) -> Ratio<T> {
- Ratio::new((self.numer * rhs.denom).$method(&(self.denom * rhs.numer)),
- self.denom * rhs.denom)
- }
- }
- }
-}
-
-// a/b + c/d = (a*d + b*c)/(b*d
-arith_impl!(impl Add, add)
-
-// a/b - c/d = (a*d - b*c)/(b*d)
-arith_impl!(impl Sub, sub)
-
-// a/b % c/d = (a*d % b*c)/(b*d)
-arith_impl!(impl Rem, rem)
-
-impl<T: Clone + Integer + Ord>
- Neg<Ratio<T>> for Ratio<T> {
- #[inline]
- fn neg(&self) -> Ratio<T> {
- Ratio::new_raw(-self.numer, self.denom.clone())
- }
-}
-
-/* Constants */
-impl<T: Clone + Integer + Ord>
- Zero for Ratio<T> {
- #[inline]
- fn zero() -> Ratio<T> {
- Ratio::new_raw(Zero::zero(), One::one())
- }
-
- #[inline]
- fn is_zero(&self) -> bool {
- *self == Zero::zero()
- }
-}
-
-impl<T: Clone + Integer + Ord>
- One for Ratio<T> {
- #[inline]
- fn one() -> Ratio<T> {
- Ratio::new_raw(One::one(), One::one())
- }
-}
-
-impl<T: Clone + Integer + Ord>
- Num for Ratio<T> {}
-
-/* Utils */
-impl<T: Clone + Integer + Ord>
- Round for Ratio<T> {
-
- fn floor(&self) -> Ratio<T> {
- if *self < Zero::zero() {
- Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
- } else {
- Ratio::from_integer(self.numer / self.denom)
- }
- }
-
- fn ceil(&self) -> Ratio<T> {
- if *self < Zero::zero() {
- Ratio::from_integer(self.numer / self.denom)
- } else {
- Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
- }
- }
-
- #[inline]
- fn round(&self) -> Ratio<T> {
- if *self < Zero::zero() {
- Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
- } else {
- Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
- }
- }
-
- #[inline]
- fn trunc(&self) -> Ratio<T> {
- Ratio::from_integer(self.numer / self.denom)
- }
-
- fn fract(&self) -> Ratio<T> {
- Ratio::new_raw(self.numer % self.denom, self.denom.clone())
- }
-}
-
-/* String conversions */
-impl<T: ToStr> ToStr for Ratio<T> {
- /// Renders as `numer/denom`.
- fn to_str(&self) -> ~str {
- format!("{}/{}", self.numer.to_str(), self.denom.to_str())
- }
-}
-impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
- /// Renders as `numer/denom` where the numbers are in base `radix`.
- fn to_str_radix(&self, radix: uint) -> ~str {
- format!("{}/{}", self.numer.to_str_radix(radix), self.denom.to_str_radix(radix))
- }
-}
-
-impl<T: FromStr + Clone + Integer + Ord>
- FromStr for Ratio<T> {
- /// Parses `numer/denom`.
- fn from_str(s: &str) -> Option<Ratio<T>> {
- let split: ~[&str] = s.splitn('/', 1).collect();
- if split.len() < 2 {
- return None
- }
- let a_option: Option<T> = FromStr::from_str(split[0]);
- a_option.and_then(|a| {
- let b_option: Option<T> = FromStr::from_str(split[1]);
- b_option.and_then(|b| {
- Some(Ratio::new(a.clone(), b.clone()))
- })
- })
- }
-}
-impl<T: FromStrRadix + Clone + Integer + Ord>
- FromStrRadix for Ratio<T> {
- /// Parses `numer/denom` where the numbers are in base `radix`.
- fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
- let split: ~[&str] = s.splitn('/', 1).collect();
- if split.len() < 2 {
- None
- } else {
- let a_option: Option<T> = FromStrRadix::from_str_radix(split[0],
- radix);
- a_option.and_then(|a| {
- let b_option: Option<T> =
- FromStrRadix::from_str_radix(split[1], radix);
- b_option.and_then(|b| {
- Some(Ratio::new(a.clone(), b.clone()))
- })
- })
- }
- }
-}
-
-#[cfg(test)]
-mod test {
-
- use super::*;
- use std::num::{Zero,One,FromStrRadix,FromPrimitive};
- use std::from_str::FromStr;
-
- pub static _0 : Rational = Ratio { numer: 0, denom: 1};
- pub static _1 : Rational = Ratio { numer: 1, denom: 1};
- pub static _2: Rational = Ratio { numer: 2, denom: 1};
- pub static _1_2: Rational = Ratio { numer: 1, denom: 2};
- pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
- pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2};
-
- pub fn to_big(n: Rational) -> BigRational {
- Ratio::new(
- FromPrimitive::from_int(n.numer).unwrap(),
- FromPrimitive::from_int(n.denom).unwrap()
- )
- }
-
- #[test]
- fn test_test_constants() {
- // check our constants are what Ratio::new etc. would make.
- assert_eq!(_0, Zero::zero());
- assert_eq!(_1, One::one());
- assert_eq!(_2, Ratio::from_integer(2));
- assert_eq!(_1_2, Ratio::new(1,2));
- assert_eq!(_3_2, Ratio::new(3,2));
- assert_eq!(_neg1_2, Ratio::new(-1,2));
- }
-
- #[test]
- fn test_new_reduce() {
- let one22 = Ratio::new(2i,2);
-
- assert_eq!(one22, One::one());
- }
- #[test]
- #[should_fail]
- fn test_new_zero() {
- let _a = Ratio::new(1,0);
- }
-
-
- #[test]
- fn test_cmp() {
- assert!(_0 == _0 && _1 == _1);
- assert!(_0 != _1 && _1 != _0);
- assert!(_0 < _1 && !(_1 < _0));
- assert!(_1 > _0 && !(_0 > _1));
-
- assert!(_0 <= _0 && _1 <= _1);
- assert!(_0 <= _1 && !(_1 <= _0));
-
- assert!(_0 >= _0 && _1 >= _1);
- assert!(_1 >= _0 && !(_0 >= _1));
- }
-
-
- #[test]
- fn test_to_integer() {
- assert_eq!(_0.to_integer(), 0);
- assert_eq!(_1.to_integer(), 1);
- assert_eq!(_2.to_integer(), 2);
- assert_eq!(_1_2.to_integer(), 0);
- assert_eq!(_3_2.to_integer(), 1);
- assert_eq!(_neg1_2.to_integer(), 0);
- }
-
-
- #[test]
- fn test_numer() {
- assert_eq!(_0.numer(), &0);
- assert_eq!(_1.numer(), &1);
- assert_eq!(_2.numer(), &2);
- assert_eq!(_1_2.numer(), &1);
- assert_eq!(_3_2.numer(), &3);
- assert_eq!(_neg1_2.numer(), &(-1));
- }
- #[test]
- fn test_denom() {
- assert_eq!(_0.denom(), &1);
- assert_eq!(_1.denom(), &1);
- assert_eq!(_2.denom(), &1);
- assert_eq!(_1_2.denom(), &2);
- assert_eq!(_3_2.denom(), &2);
- assert_eq!(_neg1_2.denom(), &2);
- }
-
-
- #[test]
- fn test_is_integer() {
- assert!(_0.is_integer());
- assert!(_1.is_integer());
- assert!(_2.is_integer());
- assert!(!_1_2.is_integer());
- assert!(!_3_2.is_integer());
- assert!(!_neg1_2.is_integer());
- }
-
-
- mod arith {
- use super::*;
- use super::super::*;
-
-
- #[test]
- fn test_add() {
- fn test(a: Rational, b: Rational, c: Rational) {
- assert_eq!(a + b, c);
- assert_eq!(to_big(a) + to_big(b), to_big(c));
- }
-
- test(_1, _1_2, _3_2);
- test(_1, _1, _2);
- test(_1_2, _3_2, _2);
- test(_1_2, _neg1_2, _0);
- }
-
- #[test]
- fn test_sub() {
- fn test(a: Rational, b: Rational, c: Rational) {
- assert_eq!(a - b, c);
- assert_eq!(to_big(a) - to_big(b), to_big(c))
- }
-
- test(_1, _1_2, _1_2);
- test(_3_2, _1_2, _1);
- test(_1, _neg1_2, _3_2);
- }
-
- #[test]
- fn test_mul() {
- fn test(a: Rational, b: Rational, c: Rational) {
- assert_eq!(a * b, c);
- assert_eq!(to_big(a) * to_big(b), to_big(c))
- }
-
- test(_1, _1_2, _1_2);
- test(_1_2, _3_2, Ratio::new(3,4));
- test(_1_2, _neg1_2, Ratio::new(-1, 4));
- }
-
- #[test]
- fn test_div() {
- fn test(a: Rational, b: Rational, c: Rational) {
- assert_eq!(a / b, c);
- assert_eq!(to_big(a) / to_big(b), to_big(c))
- }
-
- test(_1, _1_2, _2);
- test(_3_2, _1_2, _1 + _2);
- test(_1, _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2);
- }
-
- #[test]
- fn test_rem() {
- fn test(a: Rational, b: Rational, c: Rational) {
- assert_eq!(a % b, c);
- assert_eq!(to_big(a) % to_big(b), to_big(c))
- }
-
- test(_3_2, _1, _1_2);
- test(_2, _neg1_2, _0);
- test(_1_2, _2, _1_2);
- }
-
- #[test]
- fn test_neg() {
- fn test(a: Rational, b: Rational) {
- assert_eq!(-a, b);
- assert_eq!(-to_big(a), to_big(b))
- }
-
- test(_0, _0);
- test(_1_2, _neg1_2);
- test(-_1, _1);
- }
- #[test]
- fn test_zero() {
- assert_eq!(_0 + _0, _0);
- assert_eq!(_0 * _0, _0);
- assert_eq!(_0 * _1, _0);
- assert_eq!(_0 / _neg1_2, _0);
- assert_eq!(_0 - _0, _0);
- }
- #[test]
- #[should_fail]
- fn test_div_0() {
- let _a = _1 / _0;
- }
- }
-
- #[test]
- fn test_round() {
- assert_eq!(_1_2.ceil(), _1);
- assert_eq!(_1_2.floor(), _0);
- assert_eq!(_1_2.round(), _1);
- assert_eq!(_1_2.trunc(), _0);
-
- assert_eq!(_neg1_2.ceil(), _0);
- assert_eq!(_neg1_2.floor(), -_1);
- assert_eq!(_neg1_2.round(), -_1);
- assert_eq!(_neg1_2.trunc(), _0);
-
- assert_eq!(_1.ceil(), _1);
- assert_eq!(_1.floor(), _1);
- assert_eq!(_1.round(), _1);
- assert_eq!(_1.trunc(), _1);
- }
-
- #[test]
- fn test_fract() {
- assert_eq!(_1.fract(), _0);
- assert_eq!(_neg1_2.fract(), _neg1_2);
- assert_eq!(_1_2.fract(), _1_2);
- assert_eq!(_3_2.fract(), _1_2);
- }
-
- #[test]
- fn test_recip() {
- assert_eq!(_1 * _1.recip(), _1);
- assert_eq!(_2 * _2.recip(), _1);
- assert_eq!(_1_2 * _1_2.recip(), _1);
- assert_eq!(_3_2 * _3_2.recip(), _1);
- assert_eq!(_neg1_2 * _neg1_2.recip(), _1);
- }
-
- #[test]
- fn test_to_from_str() {
- fn test(r: Rational, s: ~str) {
- assert_eq!(FromStr::from_str(s), Some(r));
- assert_eq!(r.to_str(), s);
- }
- test(_1, ~"1/1");
- test(_0, ~"0/1");
- test(_1_2, ~"1/2");
- test(_3_2, ~"3/2");
- test(_2, ~"2/1");
- test(_neg1_2, ~"-1/2");
- }
- #[test]
- fn test_from_str_fail() {
- fn test(s: &str) {
- let rational: Option<Rational> = FromStr::from_str(s);
- assert_eq!(rational, None);
- }
-
- let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1"];
- for &s in xs.iter() {
- test(s);
- }
- }
-
- #[test]
- fn test_to_from_str_radix() {
- fn test(r: Rational, s: ~str, n: uint) {
- assert_eq!(FromStrRadix::from_str_radix(s, n), Some(r));
- assert_eq!(r.to_str_radix(n), s);
- }
- fn test3(r: Rational, s: ~str) { test(r, s, 3) }
- fn test16(r: Rational, s: ~str) { test(r, s, 16) }
-
- test3(_1, ~"1/1");
- test3(_0, ~"0/1");
- test3(_1_2, ~"1/2");
- test3(_3_2, ~"10/2");
- test3(_2, ~"2/1");
- test3(_neg1_2, ~"-1/2");
- test3(_neg1_2 / _2, ~"-1/11");
-
- test16(_1, ~"1/1");
- test16(_0, ~"0/1");
- test16(_1_2, ~"1/2");
- test16(_3_2, ~"3/2");
- test16(_2, ~"2/1");
- test16(_neg1_2, ~"-1/2");
- test16(_neg1_2 / _2, ~"-1/4");
- test16(Ratio::new(13,15), ~"d/f");
- test16(_1_2*_1_2*_1_2*_1_2, ~"1/10");
- }
-
- #[test]
- fn test_from_str_radix_fail() {
- fn test(s: &str) {
- let radix: Option<Rational> = FromStrRadix::from_str_radix(s, 3);
- assert_eq!(radix, None);
- }
-
- let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1", "3/2"];
- for &s in xs.iter() {
- test(s);
- }
- }
-
- #[test]
- fn test_from_float() {
- fn test<T: Float>(given: T, (numer, denom): (&str, &str)) {
- let ratio: BigRational = Ratio::from_float(given).unwrap();
- assert_eq!(ratio, Ratio::new(
- FromStr::from_str(numer).unwrap(),
- FromStr::from_str(denom).unwrap()));
- }
-
- // f32
- test(3.14159265359f32, ("13176795", "4194304"));
- test(2f32.powf(&100.), ("1267650600228229401496703205376", "1"));
- test(-2f32.powf(&100.), ("-1267650600228229401496703205376", "1"));
- test(1.0 / 2f32.powf(&100.), ("1", "1267650600228229401496703205376"));
- test(684729.48391f32, ("1369459", "2"));
- test(-8573.5918555f32, ("-4389679", "512"));
-
- // f64
- test(3.14159265359f64, ("3537118876014453", "1125899906842624"));
- test(2f64.powf(&100.), ("1267650600228229401496703205376", "1"));
- test(-2f64.powf(&100.), ("-1267650600228229401496703205376", "1"));
- test(684729.48391f64, ("367611342500051", "536870912"));
- test(-8573.5918555, ("-4713381968463931", "549755813888"));
- test(1.0 / 2f64.powf(&100.), ("1", "1267650600228229401496703205376"));
- }
-
- #[test]
- fn test_from_float_fail() {
- use std::{f32, f64};
-
- assert_eq!(Ratio::from_float(f32::NAN), None);
- assert_eq!(Ratio::from_float(f32::INFINITY), None);
- assert_eq!(Ratio::from_float(f32::NEG_INFINITY), None);
- assert_eq!(Ratio::from_float(f64::NAN), None);
- assert_eq!(Ratio::from_float(f64::INFINITY), None);
- assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None);
- }
-}
--- /dev/null
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+A Big integer (signed version: `BigInt`, unsigned version: `BigUint`).
+
+A `BigUint` is represented as an array of `BigDigit`s.
+A `BigInt` is a combination of `BigUint` and `Sign`.
+*/
+
+use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
+use std::num;
+use std::num::{Zero, One, ToStrRadix, FromStrRadix, Orderable};
+use std::num::{Bitwise, ToPrimitive, FromPrimitive};
+use std::rand::Rng;
+use std::str;
+use std::uint;
+use std::{i64, u64};
+use std::vec;
+
+/**
+A `BigDigit` is a `BigUint`'s composing element.
+
+A `BigDigit` is half the size of machine word size.
+*/
+#[cfg(target_word_size = "32")]
+pub type BigDigit = u16;
+
+/**
+A `BigDigit` is a `BigUint`'s composing element.
+
+A `BigDigit` is half the size of machine word size.
+*/
+#[cfg(target_word_size = "64")]
+pub type BigDigit = u32;
+
+pub static ZERO_BIG_DIGIT: BigDigit = 0;
+
+pub mod BigDigit {
+ use super::BigDigit;
+
+ #[cfg(target_word_size = "32")]
+ pub static bits: uint = 16;
+
+ #[cfg(target_word_size = "64")]
+ pub static bits: uint = 32;
+
+ pub static base: uint = 1 << bits;
+ static lo_mask: uint = (-1 as uint) >> bits;
+
+ #[inline]
+ fn get_hi(n: uint) -> BigDigit { (n >> bits) as BigDigit }
+ #[inline]
+ fn get_lo(n: uint) -> BigDigit { (n & lo_mask) as BigDigit }
+
+ /// Split one machine sized unsigned integer into two `BigDigit`s.
+ #[inline]
+ pub fn from_uint(n: uint) -> (BigDigit, BigDigit) {
+ (get_hi(n), get_lo(n))
+ }
+
+ /// Join two `BigDigit`s into one machine sized unsigned integer
+ #[inline]
+ pub fn to_uint(hi: BigDigit, lo: BigDigit) -> uint {
+ (lo as uint) | ((hi as uint) << bits)
+ }
+}
+
+/**
+A big unsigned integer type.
+
+A `BigUint`-typed value `BigUint { data: ~[a, b, c] }` represents a number
+`(a + b * BigDigit::base + c * BigDigit::base^2)`.
+*/
+#[deriving(Clone)]
+pub struct BigUint {
+ priv data: ~[BigDigit]
+}
+
+impl Eq for BigUint {
+ #[inline]
+ fn eq(&self, other: &BigUint) -> bool { self.equals(other) }
+}
+
+impl TotalEq for BigUint {
+ #[inline]
+ fn equals(&self, other: &BigUint) -> bool {
+ match self.cmp(other) { Equal => true, _ => false }
+ }
+}
+
+impl Ord for BigUint {
+ #[inline]
+ fn lt(&self, other: &BigUint) -> bool {
+ match self.cmp(other) { Less => true, _ => false}
+ }
+}
+
+impl TotalOrd for BigUint {
+ #[inline]
+ fn cmp(&self, other: &BigUint) -> Ordering {
+ let (s_len, o_len) = (self.data.len(), other.data.len());
+ if s_len < o_len { return Less; }
+ if s_len > o_len { return Greater; }
+
+ for (&self_i, &other_i) in self.data.rev_iter().zip(other.data.rev_iter()) {
+ if self_i < other_i { return Less; }
+ if self_i > other_i { return Greater; }
+ }
+ return Equal;
+ }
+}
+
+impl ToStr for BigUint {
+ #[inline]
+ fn to_str(&self) -> ~str { self.to_str_radix(10) }
+}
+
+impl FromStr for BigUint {
+ #[inline]
+ fn from_str(s: &str) -> Option<BigUint> {
+ FromStrRadix::from_str_radix(s, 10)
+ }
+}
+
+impl Num for BigUint {}
+
+impl Orderable for BigUint {
+ #[inline]
+ fn min(&self, other: &BigUint) -> BigUint {
+ if self < other { self.clone() } else { other.clone() }
+ }
+
+ #[inline]
+ fn max(&self, other: &BigUint) -> BigUint {
+ if self > other { self.clone() } else { other.clone() }
+ }
+
+ #[inline]
+ fn clamp(&self, mn: &BigUint, mx: &BigUint) -> BigUint {
+ if self > mx { mx.clone() } else
+ if self < mn { mn.clone() } else { self.clone() }
+ }
+}
+
+impl BitAnd<BigUint, BigUint> for BigUint {
+ fn bitand(&self, other: &BigUint) -> BigUint {
+ let new_len = num::min(self.data.len(), other.data.len());
+ let anded = vec::from_fn(new_len, |i| {
+ // i will never be less than the size of either data vector
+ let ai = self.data[i];
+ let bi = other.data[i];
+ ai & bi
+ });
+ return BigUint::new(anded);
+ }
+}
+
+impl BitOr<BigUint, BigUint> for BigUint {
+ fn bitor(&self, other: &BigUint) -> BigUint {
+ let new_len = num::max(self.data.len(), other.data.len());
+ let ored = vec::from_fn(new_len, |i| {
+ let ai = if i < self.data.len() { self.data[i] } else { 0 };
+ let bi = if i < other.data.len() { other.data[i] } else { 0 };
+ ai | bi
+ });
+ return BigUint::new(ored);
+ }
+}
+
+impl BitXor<BigUint, BigUint> for BigUint {
+ fn bitxor(&self, other: &BigUint) -> BigUint {
+ let new_len = num::max(self.data.len(), other.data.len());
+ let xored = vec::from_fn(new_len, |i| {
+ let ai = if i < self.data.len() { self.data[i] } else { 0 };
+ let bi = if i < other.data.len() { other.data[i] } else { 0 };
+ ai ^ bi
+ });
+ return BigUint::new(xored);
+ }
+}
+
+impl Shl<uint, BigUint> for BigUint {
+ #[inline]
+ fn shl(&self, rhs: &uint) -> BigUint {
+ let n_unit = *rhs / BigDigit::bits;
+ let n_bits = *rhs % BigDigit::bits;
+ return self.shl_unit(n_unit).shl_bits(n_bits);
+ }
+}
+
+impl Shr<uint, BigUint> for BigUint {
+ #[inline]
+ fn shr(&self, rhs: &uint) -> BigUint {
+ let n_unit = *rhs / BigDigit::bits;
+ let n_bits = *rhs % BigDigit::bits;
+ return self.shr_unit(n_unit).shr_bits(n_bits);
+ }
+}
+
+impl Zero for BigUint {
+ #[inline]
+ fn zero() -> BigUint { BigUint::new(~[]) }
+
+ #[inline]
+ fn is_zero(&self) -> bool { self.data.is_empty() }
+}
+
+impl One for BigUint {
+ #[inline]
+ fn one() -> BigUint { BigUint::new(~[1]) }
+}
+
+impl Unsigned for BigUint {}
+
+impl Add<BigUint, BigUint> for BigUint {
+ fn add(&self, other: &BigUint) -> BigUint {
+ let new_len = num::max(self.data.len(), other.data.len());
+
+ let mut carry = 0;
+ let mut sum = vec::from_fn(new_len, |i| {
+ let ai = if i < self.data.len() { self.data[i] } else { 0 };
+ let bi = if i < other.data.len() { other.data[i] } else { 0 };
+ let (hi, lo) = BigDigit::from_uint(
+ (ai as uint) + (bi as uint) + (carry as uint)
+ );
+ carry = hi;
+ lo
+ });
+ if carry != 0 { sum.push(carry); }
+ return BigUint::new(sum);
+ }
+}
+
+impl Sub<BigUint, BigUint> for BigUint {
+ fn sub(&self, other: &BigUint) -> BigUint {
+ let new_len = num::max(self.data.len(), other.data.len());
+
+ let mut borrow = 0;
+ let diff = vec::from_fn(new_len, |i| {
+ let ai = if i < self.data.len() { self.data[i] } else { 0 };
+ let bi = if i < other.data.len() { other.data[i] } else { 0 };
+ let (hi, lo) = BigDigit::from_uint(
+ (BigDigit::base) +
+ (ai as uint) - (bi as uint) - (borrow as uint)
+ );
+ /*
+ hi * (base) + lo == 1*(base) + ai - bi - borrow
+ => ai - bi - borrow < 0 <=> hi == 0
+ */
+ borrow = if hi == 0 { 1 } else { 0 };
+ lo
+ });
+
+ assert_eq!(borrow, 0); // <=> assert!((self >= other));
+ return BigUint::new(diff);
+ }
+}
+
+impl Mul<BigUint, BigUint> for BigUint {
+ fn mul(&self, other: &BigUint) -> BigUint {
+ if self.is_zero() || other.is_zero() { return Zero::zero(); }
+
+ let (s_len, o_len) = (self.data.len(), other.data.len());
+ if s_len == 1 { return mul_digit(other, self.data[0]); }
+ if o_len == 1 { return mul_digit(self, other.data[0]); }
+
+ // Using Karatsuba multiplication
+ // (a1 * base + a0) * (b1 * base + b0)
+ // = a1*b1 * base^2 +
+ // (a1*b1 + a0*b0 - (a1-b0)*(b1-a0)) * base +
+ // a0*b0
+ let half_len = num::max(s_len, o_len) / 2;
+ let (sHi, sLo) = cut_at(self, half_len);
+ let (oHi, oLo) = cut_at(other, half_len);
+
+ let ll = sLo * oLo;
+ let hh = sHi * oHi;
+ let mm = {
+ let (s1, n1) = sub_sign(sHi, sLo);
+ let (s2, n2) = sub_sign(oHi, oLo);
+ match (s1, s2) {
+ (Equal, _) | (_, Equal) => hh + ll,
+ (Less, Greater) | (Greater, Less) => hh + ll + (n1 * n2),
+ (Less, Less) | (Greater, Greater) => hh + ll - (n1 * n2)
+ }
+ };
+
+ return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2);
+
+
+ fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
+ if n == 0 { return Zero::zero(); }
+ if n == 1 { return (*a).clone(); }
+
+ let mut carry = 0;
+ let mut prod = a.data.iter().map(|ai| {
+ let (hi, lo) = BigDigit::from_uint(
+ (*ai as uint) * (n as uint) + (carry as uint)
+ );
+ carry = hi;
+ lo
+ }).collect::<~[BigDigit]>();
+ if carry != 0 { prod.push(carry); }
+ return BigUint::new(prod);
+ }
+
+ #[inline]
+ fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
+ let mid = num::min(a.data.len(), n);
+ return (BigUint::from_slice(a.data.slice(mid, a.data.len())),
+ BigUint::from_slice(a.data.slice(0, mid)));
+ }
+
+ #[inline]
+ fn sub_sign(a: BigUint, b: BigUint) -> (Ordering, BigUint) {
+ match a.cmp(&b) {
+ Less => (Less, b - a),
+ Greater => (Greater, a - b),
+ _ => (Equal, Zero::zero())
+ }
+ }
+ }
+}
+
+impl Div<BigUint, BigUint> for BigUint {
+ #[inline]
+ fn div(&self, other: &BigUint) -> BigUint {
+ let (q, _) = self.div_rem(other);
+ return q;
+ }
+}
+
+impl Rem<BigUint, BigUint> for BigUint {
+ #[inline]
+ fn rem(&self, other: &BigUint) -> BigUint {
+ let (_, r) = self.div_rem(other);
+ return r;
+ }
+}
+
+impl Neg<BigUint> for BigUint {
+ #[inline]
+ fn neg(&self) -> BigUint { fail!() }
+}
+
+impl Integer for BigUint {
+ #[inline]
+ fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
+ self.div_mod_floor(other)
+ }
+
+ #[inline]
+ fn div_floor(&self, other: &BigUint) -> BigUint {
+ let (d, _) = self.div_mod_floor(other);
+ return d;
+ }
+
+ #[inline]
+ fn mod_floor(&self, other: &BigUint) -> BigUint {
+ let (_, m) = self.div_mod_floor(other);
+ return m;
+ }
+
+ fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) {
+ if other.is_zero() { fail!() }
+ if self.is_zero() { return (Zero::zero(), Zero::zero()); }
+ if *other == One::one() { return ((*self).clone(), Zero::zero()); }
+
+ match self.cmp(other) {
+ Less => return (Zero::zero(), (*self).clone()),
+ Equal => return (One::one(), Zero::zero()),
+ Greater => {} // Do nothing
+ }
+
+ let mut shift = 0;
+ let mut n = *other.data.last().unwrap();
+ while n < (1 << BigDigit::bits - 2) {
+ n <<= 1;
+ shift += 1;
+ }
+ assert!(shift < BigDigit::bits);
+ let (d, m) = div_mod_floor_inner(self << shift, other << shift);
+ return (d, m >> shift);
+
+
+ fn div_mod_floor_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
+ let mut m = a;
+ let mut d: BigUint = Zero::zero();
+ let mut n = 1;
+ while m >= b {
+ let (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
+ let mut d0 = d0;
+ let mut prod = b * d0;
+ while prod > m {
+ // FIXME(#6050): overloaded operators force moves with generic types
+ // d0 -= d_unit
+ d0 = d0 - d_unit;
+ // FIXME(#6050): overloaded operators force moves with generic types
+ // prod = prod - b_unit;
+ prod = prod - b_unit
+ }
+ if d0.is_zero() {
+ n = 2;
+ continue;
+ }
+ n = 1;
+ // FIXME(#6102): Assignment operator for BigInt causes ICE
+ // d += d0;
+ d = d + d0;
+ // FIXME(#6102): Assignment operator for BigInt causes ICE
+ // m -= prod;
+ m = m - prod;
+ }
+ return (d, m);
+ }
+
+
+ fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
+ -> (BigUint, BigUint, BigUint) {
+ if a.data.len() < n {
+ return (Zero::zero(), Zero::zero(), (*a).clone());
+ }
+
+ let an = a.data.slice(a.data.len() - n, a.data.len());
+ let bn = *b.data.last().unwrap();
+ let mut d = ~[];
+ let mut carry = 0;
+ for elt in an.rev_iter() {
+ let ai = BigDigit::to_uint(carry, *elt);
+ let di = ai / (bn as uint);
+ assert!(di < BigDigit::base);
+ carry = (ai % (bn as uint)) as BigDigit;
+ d = ~[di as BigDigit] + d;
+ }
+
+ let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
+ if shift == 0 {
+ return (BigUint::new(d), One::one(), (*b).clone());
+ }
+ let one: BigUint = One::one();
+ return (BigUint::from_slice(d).shl_unit(shift),
+ one.shl_unit(shift),
+ b.shl_unit(shift));
+ }
+ }
+
+ /**
+ * Calculates the Greatest Common Divisor (GCD) of the number and `other`
+ *
+ * The result is always positive
+ */
+ #[inline]
+ fn gcd(&self, other: &BigUint) -> BigUint {
+ // Use Euclid's algorithm
+ let mut m = (*self).clone();
+ let mut n = (*other).clone();
+ while !m.is_zero() {
+ let temp = m;
+ m = n % temp;
+ n = temp;
+ }
+ return n;
+ }
+
+ /**
+ * Calculates the Lowest Common Multiple (LCM) of the number and `other`
+ */
+ #[inline]
+ fn lcm(&self, other: &BigUint) -> BigUint { ((*self * *other) / self.gcd(other)) }
+
+ /// Returns `true` if the number can be divided by `other` without leaving a remainder
+ #[inline]
+ fn is_multiple_of(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline]
+ fn is_even(&self) -> bool {
+ // Considering only the last digit.
+ if self.data.is_empty() {
+ true
+ } else {
+ self.data[0].is_even()
+ }
+ }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline]
+ fn is_odd(&self) -> bool { !self.is_even() }
+}
+
+impl ToPrimitive for BigUint {
+ #[inline]
+ fn to_i64(&self) -> Option<i64> {
+ self.to_u64().and_then(|n| {
+ // If top bit of u64 is set, it's too large to convert to i64.
+ if n >> 63 == 0 {
+ Some(n as i64)
+ } else {
+ None
+ }
+ })
+ }
+
+ #[cfg(target_word_size = "32")]
+ #[inline]
+ fn to_u64(&self) -> Option<u64> {
+ match self.data {
+ [] => {
+ Some(0)
+ }
+ [n0] => {
+ Some(n0 as u64)
+ }
+ [n0, n1] => {
+ Some(BigDigit::to_uint(n1, n0) as u64)
+ }
+ [n0, n1, n2] => {
+ let n_lo = BigDigit::to_uint(n1, n0) as u64;
+ let n_hi = n2 as u64;
+ Some((n_hi << 32) + n_lo)
+ }
+ [n0, n1, n2, n3] => {
+ let n_lo = BigDigit::to_uint(n1, n0) as u64;
+ let n_hi = BigDigit::to_uint(n3, n2) as u64;
+ Some((n_hi << 32) + n_lo)
+ }
+ _ => None
+ }
+ }
+
+ #[cfg(target_word_size = "64")]
+ #[inline]
+ fn to_u64(&self) -> Option<u64> {
+ match self.data {
+ [] => {
+ Some(0)
+ }
+ [n0] => {
+ Some(n0 as u64)
+ }
+ [n0, n1] => {
+ Some(BigDigit::to_uint(n1, n0) as u64)
+ }
+ _ => None
+ }
+ }
+}
+
+impl FromPrimitive for BigUint {
+ #[inline]
+ fn from_i64(n: i64) -> Option<BigUint> {
+ if n > 0 {
+ FromPrimitive::from_u64(n as u64)
+ } else if n == 0 {
+ Some(Zero::zero())
+ } else {
+ None
+ }
+ }
+
+ #[cfg(target_word_size = "32")]
+ #[inline]
+ fn from_u64(n: u64) -> Option<BigUint> {
+ let n_lo = (n & 0x0000_0000_FFFF_FFFF) as uint;
+ let n_hi = (n >> 32) as uint;
+
+ let n = match (BigDigit::from_uint(n_hi), BigDigit::from_uint(n_lo)) {
+ ((0, 0), (0, 0)) => Zero::zero(),
+ ((0, 0), (0, n0)) => BigUint::new(~[n0]),
+ ((0, 0), (n1, n0)) => BigUint::new(~[n0, n1]),
+ ((0, n2), (n1, n0)) => BigUint::new(~[n0, n1, n2]),
+ ((n3, n2), (n1, n0)) => BigUint::new(~[n0, n1, n2, n3]),
+ };
+ Some(n)
+ }
+
+ #[cfg(target_word_size = "64")]
+ #[inline]
+ fn from_u64(n: u64) -> Option<BigUint> {
+ let n = match BigDigit::from_uint(n as uint) {
+ (0, 0) => Zero::zero(),
+ (0, n0) => BigUint::new(~[n0]),
+ (n1, n0) => BigUint::new(~[n0, n1])
+ };
+ Some(n)
+ }
+}
+
+/// A generic trait for converting a value to a `BigUint`.
+pub trait ToBigUint {
+ /// Converts the value of `self` to a `BigUint`.
+ fn to_biguint(&self) -> Option<BigUint>;
+}
+
+impl ToBigUint for BigInt {
+ #[inline]
+ fn to_biguint(&self) -> Option<BigUint> {
+ if self.sign == Plus {
+ Some(self.data.clone())
+ } else if self.sign == Zero {
+ Some(Zero::zero())
+ } else {
+ None
+ }
+ }
+}
+
+impl ToBigUint for BigUint {
+ #[inline]
+ fn to_biguint(&self) -> Option<BigUint> {
+ Some(self.clone())
+ }
+}
+
+macro_rules! impl_to_biguint(
+ ($T:ty, $from_ty:path) => {
+ impl ToBigUint for $T {
+ #[inline]
+ fn to_biguint(&self) -> Option<BigUint> {
+ $from_ty(*self)
+ }
+ }
+ }
+)
+
+impl_to_biguint!(int, FromPrimitive::from_int)
+impl_to_biguint!(i8, FromPrimitive::from_i8)
+impl_to_biguint!(i16, FromPrimitive::from_i16)
+impl_to_biguint!(i32, FromPrimitive::from_i32)
+impl_to_biguint!(i64, FromPrimitive::from_i64)
+impl_to_biguint!(uint, FromPrimitive::from_uint)
+impl_to_biguint!(u8, FromPrimitive::from_u8)
+impl_to_biguint!(u16, FromPrimitive::from_u16)
+impl_to_biguint!(u32, FromPrimitive::from_u32)
+impl_to_biguint!(u64, FromPrimitive::from_u64)
+
+impl ToStrRadix for BigUint {
+ fn to_str_radix(&self, radix: uint) -> ~str {
+ assert!(1 < radix && radix <= 16);
+ let (base, max_len) = get_radix_base(radix);
+ if base == BigDigit::base {
+ return fill_concat(self.data, radix, max_len)
+ }
+ return fill_concat(convert_base((*self).clone(), base), radix, max_len);
+
+ fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
+ let divider = FromPrimitive::from_uint(base).unwrap();
+ let mut result = ~[];
+ let mut m = n;
+ while m >= divider {
+ let (d, m0) = m.div_mod_floor(÷r);
+ result.push(m0.to_uint().unwrap() as BigDigit);
+ m = d;
+ }
+ if !m.is_zero() {
+ result.push(m.to_uint().unwrap() as BigDigit);
+ }
+ return result;
+ }
+
+ fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
+ if v.is_empty() { return ~"0" }
+ let mut s = str::with_capacity(v.len() * l);
+ for n in v.rev_iter() {
+ let ss = (*n as uint).to_str_radix(radix);
+ s.push_str("0".repeat(l - ss.len()));
+ s.push_str(ss);
+ }
+ s.trim_left_chars(&'0').to_owned()
+ }
+ }
+}
+
+impl FromStrRadix for BigUint {
+ /// Creates and initializes a `BigUint`.
+ #[inline]
+ fn from_str_radix(s: &str, radix: uint)
+ -> Option<BigUint> {
+ BigUint::parse_bytes(s.as_bytes(), radix)
+ }
+}
+
+impl BigUint {
+ /// Creates and initializes a `BigUint`.
+ #[inline]
+ pub fn new(v: ~[BigDigit]) -> BigUint {
+ // omit trailing zeros
+ let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
+
+ if new_len == v.len() { return BigUint { data: v }; }
+ let mut v = v;
+ v.truncate(new_len);
+ return BigUint { data: v };
+ }
+
+ /// Creates and initializes a `BigUint`.
+ #[inline]
+ pub fn from_slice(slice: &[BigDigit]) -> BigUint {
+ return BigUint::new(slice.to_owned());
+ }
+
+ /// Creates and initializes a `BigUint`.
+ pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigUint> {
+ let (base, unit_len) = get_radix_base(radix);
+ let base_num = match FromPrimitive::from_uint(base) {
+ Some(base_num) => base_num,
+ None => { return None; }
+ };
+
+ let mut end = buf.len();
+ let mut n: BigUint = Zero::zero();
+ let mut power: BigUint = One::one();
+ loop {
+ let start = num::max(end, unit_len) - unit_len;
+ match uint::parse_bytes(buf.slice(start, end), radix) {
+ Some(d) => {
+ let d: Option<BigUint> = FromPrimitive::from_uint(d);
+ match d {
+ Some(d) => {
+ // FIXME(#6102): Assignment operator for BigInt
+ // causes ICE:
+ // n += d * power;
+ n = n + d * power;
+ }
+ None => { return None; }
+ }
+ }
+ None => { return None; }
+ }
+ if end <= unit_len {
+ return Some(n);
+ }
+ end -= unit_len;
+ // FIXME(#6050): overloaded operators force moves with generic types
+ // power *= base_num;
+ power = power * base_num;
+ }
+ }
+
+ #[inline]
+ fn shl_unit(&self, n_unit: uint) -> BigUint {
+ if n_unit == 0 || self.is_zero() { return (*self).clone(); }
+
+ return BigUint::new(vec::from_elem(n_unit, ZERO_BIG_DIGIT)
+ + self.data);
+ }
+
+ #[inline]
+ fn shl_bits(&self, n_bits: uint) -> BigUint {
+ if n_bits == 0 || self.is_zero() { return (*self).clone(); }
+
+ let mut carry = 0;
+ let mut shifted = self.data.iter().map(|elem| {
+ let (hi, lo) = BigDigit::from_uint(
+ (*elem as uint) << n_bits | (carry as uint)
+ );
+ carry = hi;
+ lo
+ }).collect::<~[BigDigit]>();
+ if carry != 0 { shifted.push(carry); }
+ return BigUint::new(shifted);
+ }
+
+ #[inline]
+ fn shr_unit(&self, n_unit: uint) -> BigUint {
+ if n_unit == 0 { return (*self).clone(); }
+ if self.data.len() < n_unit { return Zero::zero(); }
+ return BigUint::from_slice(
+ self.data.slice(n_unit, self.data.len())
+ );
+ }
+
+ #[inline]
+ fn shr_bits(&self, n_bits: uint) -> BigUint {
+ if n_bits == 0 || self.data.is_empty() { return (*self).clone(); }
+
+ let mut borrow = 0;
+ let mut shifted = ~[];
+ for elem in self.data.rev_iter() {
+ shifted = ~[(*elem >> n_bits) | borrow] + shifted;
+ borrow = *elem << (BigDigit::bits - n_bits);
+ }
+ return BigUint::new(shifted);
+ }
+
+ /// Determines the fewest bits necessary to express the `BigUint`.
+ pub fn bits(&self) -> uint {
+ if self.is_zero() { return 0; }
+ let zeros = self.data.last().unwrap().leading_zeros();
+ return self.data.len()*BigDigit::bits - (zeros as uint);
+ }
+}
+
+#[cfg(target_word_size = "32")]
+#[inline]
+fn get_radix_base(radix: uint) -> (uint, uint) {
+ assert!(1 < radix && radix <= 16);
+ match radix {
+ 2 => (65536, 16),
+ 3 => (59049, 10),
+ 4 => (65536, 8),
+ 5 => (15625, 6),
+ 6 => (46656, 6),
+ 7 => (16807, 5),
+ 8 => (32768, 5),
+ 9 => (59049, 5),
+ 10 => (10000, 4),
+ 11 => (14641, 4),
+ 12 => (20736, 4),
+ 13 => (28561, 4),
+ 14 => (38416, 4),
+ 15 => (50625, 4),
+ 16 => (65536, 4),
+ _ => fail!()
+ }
+}
+
+#[cfg(target_word_size = "64")]
+#[inline]
+fn get_radix_base(radix: uint) -> (uint, uint) {
+ assert!(1 < radix && radix <= 16);
+ match radix {
+ 2 => (4294967296, 32),
+ 3 => (3486784401, 20),
+ 4 => (4294967296, 16),
+ 5 => (1220703125, 13),
+ 6 => (2176782336, 12),
+ 7 => (1977326743, 11),
+ 8 => (1073741824, 10),
+ 9 => (3486784401, 10),
+ 10 => (1000000000, 9),
+ 11 => (2357947691, 9),
+ 12 => (429981696, 8),
+ 13 => (815730721, 8),
+ 14 => (1475789056, 8),
+ 15 => (2562890625, 8),
+ 16 => (4294967296, 8),
+ _ => fail!()
+ }
+}
+
+/// A Sign is a `BigInt`'s composing element.
+#[deriving(Eq, Clone)]
+pub enum Sign { Minus, Zero, Plus }
+
+impl Ord for Sign {
+ #[inline]
+ fn lt(&self, other: &Sign) -> bool {
+ match self.cmp(other) { Less => true, _ => false}
+ }
+}
+
+impl TotalEq for Sign {
+ #[inline]
+ fn equals(&self, other: &Sign) -> bool { *self == *other }
+}
+impl TotalOrd for Sign {
+ #[inline]
+ fn cmp(&self, other: &Sign) -> Ordering {
+ match (*self, *other) {
+ (Minus, Minus) | (Zero, Zero) | (Plus, Plus) => Equal,
+ (Minus, Zero) | (Minus, Plus) | (Zero, Plus) => Less,
+ _ => Greater
+ }
+ }
+}
+
+impl Neg<Sign> for Sign {
+ /// Negate Sign value.
+ #[inline]
+ fn neg(&self) -> Sign {
+ match *self {
+ Minus => Plus,
+ Zero => Zero,
+ Plus => Minus
+ }
+ }
+}
+
+/// A big signed integer type.
+#[deriving(Clone)]
+pub struct BigInt {
+ priv sign: Sign,
+ priv data: BigUint
+}
+
+impl Eq for BigInt {
+ #[inline]
+ fn eq(&self, other: &BigInt) -> bool { self.equals(other) }
+}
+
+impl TotalEq for BigInt {
+ #[inline]
+ fn equals(&self, other: &BigInt) -> bool {
+ match self.cmp(other) { Equal => true, _ => false }
+ }
+}
+
+impl Ord for BigInt {
+ #[inline]
+ fn lt(&self, other: &BigInt) -> bool {
+ match self.cmp(other) { Less => true, _ => false}
+ }
+}
+
+impl TotalOrd for BigInt {
+ #[inline]
+ fn cmp(&self, other: &BigInt) -> Ordering {
+ let scmp = self.sign.cmp(&other.sign);
+ if scmp != Equal { return scmp; }
+
+ match self.sign {
+ Zero => Equal,
+ Plus => self.data.cmp(&other.data),
+ Minus => other.data.cmp(&self.data),
+ }
+ }
+}
+
+impl ToStr for BigInt {
+ #[inline]
+ fn to_str(&self) -> ~str { self.to_str_radix(10) }
+}
+
+impl FromStr for BigInt {
+ #[inline]
+ fn from_str(s: &str) -> Option<BigInt> {
+ FromStrRadix::from_str_radix(s, 10)
+ }
+}
+
+impl Num for BigInt {}
+
+impl Orderable for BigInt {
+ #[inline]
+ fn min(&self, other: &BigInt) -> BigInt {
+ if self < other { self.clone() } else { other.clone() }
+ }
+
+ #[inline]
+ fn max(&self, other: &BigInt) -> BigInt {
+ if self > other { self.clone() } else { other.clone() }
+ }
+
+ #[inline]
+ fn clamp(&self, mn: &BigInt, mx: &BigInt) -> BigInt {
+ if self > mx { mx.clone() } else
+ if self < mn { mn.clone() } else { self.clone() }
+ }
+}
+
+impl Shl<uint, BigInt> for BigInt {
+ #[inline]
+ fn shl(&self, rhs: &uint) -> BigInt {
+ BigInt::from_biguint(self.sign, self.data << *rhs)
+ }
+}
+
+impl Shr<uint, BigInt> for BigInt {
+ #[inline]
+ fn shr(&self, rhs: &uint) -> BigInt {
+ BigInt::from_biguint(self.sign, self.data >> *rhs)
+ }
+}
+
+impl Zero for BigInt {
+ #[inline]
+ fn zero() -> BigInt {
+ BigInt::from_biguint(Zero, Zero::zero())
+ }
+
+ #[inline]
+ fn is_zero(&self) -> bool { self.sign == Zero }
+}
+
+impl One for BigInt {
+ #[inline]
+ fn one() -> BigInt {
+ BigInt::from_biguint(Plus, One::one())
+ }
+}
+
+impl Signed for BigInt {
+ #[inline]
+ fn abs(&self) -> BigInt {
+ match self.sign {
+ Plus | Zero => self.clone(),
+ Minus => BigInt::from_biguint(Plus, self.data.clone())
+ }
+ }
+
+ #[inline]
+ fn abs_sub(&self, other: &BigInt) -> BigInt {
+ if *self <= *other { Zero::zero() } else { *self - *other }
+ }
+
+ #[inline]
+ fn signum(&self) -> BigInt {
+ match self.sign {
+ Plus => BigInt::from_biguint(Plus, One::one()),
+ Minus => BigInt::from_biguint(Minus, One::one()),
+ Zero => Zero::zero(),
+ }
+ }
+
+ #[inline]
+ fn is_positive(&self) -> bool { self.sign == Plus }
+
+ #[inline]
+ fn is_negative(&self) -> bool { self.sign == Minus }
+}
+
+impl Add<BigInt, BigInt> for BigInt {
+ #[inline]
+ fn add(&self, other: &BigInt) -> BigInt {
+ match (self.sign, other.sign) {
+ (Zero, _) => other.clone(),
+ (_, Zero) => self.clone(),
+ (Plus, Plus) => BigInt::from_biguint(Plus,
+ self.data + other.data),
+ (Plus, Minus) => self - (-*other),
+ (Minus, Plus) => other - (-*self),
+ (Minus, Minus) => -((-self) + (-*other))
+ }
+ }
+}
+
+impl Sub<BigInt, BigInt> for BigInt {
+ #[inline]
+ fn sub(&self, other: &BigInt) -> BigInt {
+ match (self.sign, other.sign) {
+ (Zero, _) => -other,
+ (_, Zero) => self.clone(),
+ (Plus, Plus) => match self.data.cmp(&other.data) {
+ Less => BigInt::from_biguint(Minus, other.data - self.data),
+ Greater => BigInt::from_biguint(Plus, self.data - other.data),
+ Equal => Zero::zero()
+ },
+ (Plus, Minus) => self + (-*other),
+ (Minus, Plus) => -((-self) + *other),
+ (Minus, Minus) => (-other) - (-*self)
+ }
+ }
+}
+
+impl Mul<BigInt, BigInt> for BigInt {
+ #[inline]
+ fn mul(&self, other: &BigInt) -> BigInt {
+ match (self.sign, other.sign) {
+ (Zero, _) | (_, Zero) => Zero::zero(),
+ (Plus, Plus) | (Minus, Minus) => {
+ BigInt::from_biguint(Plus, self.data * other.data)
+ },
+ (Plus, Minus) | (Minus, Plus) => {
+ BigInt::from_biguint(Minus, self.data * other.data)
+ }
+ }
+ }
+}
+
+impl Div<BigInt, BigInt> for BigInt {
+ #[inline]
+ fn div(&self, other: &BigInt) -> BigInt {
+ let (q, _) = self.div_rem(other);
+ return q;
+ }
+}
+
+impl Rem<BigInt, BigInt> for BigInt {
+ #[inline]
+ fn rem(&self, other: &BigInt) -> BigInt {
+ let (_, r) = self.div_rem(other);
+ return r;
+ }
+}
+
+impl Neg<BigInt> for BigInt {
+ #[inline]
+ fn neg(&self) -> BigInt {
+ BigInt::from_biguint(self.sign.neg(), self.data.clone())
+ }
+}
+
+impl Integer for BigInt {
+ #[inline]
+ fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
+ // r.sign == self.sign
+ let (d_ui, r_ui) = self.data.div_mod_floor(&other.data);
+ let d = BigInt::from_biguint(Plus, d_ui);
+ let r = BigInt::from_biguint(Plus, r_ui);
+ match (self.sign, other.sign) {
+ (_, Zero) => fail!(),
+ (Plus, Plus) | (Zero, Plus) => ( d, r),
+ (Plus, Minus) | (Zero, Minus) => (-d, r),
+ (Minus, Plus) => (-d, -r),
+ (Minus, Minus) => ( d, -r)
+ }
+ }
+
+ #[inline]
+ fn div_floor(&self, other: &BigInt) -> BigInt {
+ let (d, _) = self.div_mod_floor(other);
+ return d;
+ }
+
+ #[inline]
+ fn mod_floor(&self, other: &BigInt) -> BigInt {
+ let (_, m) = self.div_mod_floor(other);
+ return m;
+ }
+
+ fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
+ // m.sign == other.sign
+ let (d_ui, m_ui) = self.data.div_rem(&other.data);
+ let d = BigInt::from_biguint(Plus, d_ui);
+ let m = BigInt::from_biguint(Plus, m_ui);
+ match (self.sign, other.sign) {
+ (_, Zero) => fail!(),
+ (Plus, Plus) | (Zero, Plus) => (d, m),
+ (Plus, Minus) | (Zero, Minus) => if m.is_zero() {
+ (-d, Zero::zero())
+ } else {
+ (-d - One::one(), m + *other)
+ },
+ (Minus, Plus) => if m.is_zero() {
+ (-d, Zero::zero())
+ } else {
+ (-d - One::one(), other - m)
+ },
+ (Minus, Minus) => (d, -m)
+ }
+ }
+
+ /**
+ * Calculates the Greatest Common Divisor (GCD) of the number and `other`
+ *
+ * The result is always positive
+ */
+ #[inline]
+ fn gcd(&self, other: &BigInt) -> BigInt {
+ BigInt::from_biguint(Plus, self.data.gcd(&other.data))
+ }
+
+ /**
+ * Calculates the Lowest Common Multiple (LCM) of the number and `other`
+ */
+ #[inline]
+ fn lcm(&self, other: &BigInt) -> BigInt {
+ BigInt::from_biguint(Plus, self.data.lcm(&other.data))
+ }
+
+ /// Returns `true` if the number can be divided by `other` without leaving a remainder
+ #[inline]
+ fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline]
+ fn is_even(&self) -> bool { self.data.is_even() }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline]
+ fn is_odd(&self) -> bool { self.data.is_odd() }
+}
+
+impl ToPrimitive for BigInt {
+ #[inline]
+ fn to_i64(&self) -> Option<i64> {
+ match self.sign {
+ Plus => self.data.to_i64(),
+ Zero => Some(0),
+ Minus => {
+ self.data.to_u64().and_then(|n| {
+ let m: u64 = 1 << 63;
+ if n < m {
+ Some(-(n as i64))
+ } else if n == m {
+ Some(i64::MIN)
+ } else {
+ None
+ }
+ })
+ }
+ }
+ }
+
+ #[inline]
+ fn to_u64(&self) -> Option<u64> {
+ match self.sign {
+ Plus => self.data.to_u64(),
+ Zero => Some(0),
+ Minus => None
+ }
+ }
+}
+
+impl FromPrimitive for BigInt {
+ #[inline]
+ fn from_i64(n: i64) -> Option<BigInt> {
+ if n > 0 {
+ FromPrimitive::from_u64(n as u64).and_then(|n| {
+ Some(BigInt::from_biguint(Plus, n))
+ })
+ } else if n < 0 {
+ FromPrimitive::from_u64(u64::MAX - (n as u64) + 1).and_then(
+ |n| {
+ Some(BigInt::from_biguint(Minus, n))
+ })
+ } else {
+ Some(Zero::zero())
+ }
+ }
+
+ #[inline]
+ fn from_u64(n: u64) -> Option<BigInt> {
+ if n == 0 {
+ Some(Zero::zero())
+ } else {
+ FromPrimitive::from_u64(n).and_then(|n| {
+ Some(BigInt::from_biguint(Plus, n))
+ })
+ }
+ }
+}
+
+/// A generic trait for converting a value to a `BigInt`.
+pub trait ToBigInt {
+ /// Converts the value of `self` to a `BigInt`.
+ fn to_bigint(&self) -> Option<BigInt>;
+}
+
+impl ToBigInt for BigInt {
+ #[inline]
+ fn to_bigint(&self) -> Option<BigInt> {
+ Some(self.clone())
+ }
+}
+
+impl ToBigInt for BigUint {
+ #[inline]
+ fn to_bigint(&self) -> Option<BigInt> {
+ if self.is_zero() {
+ Some(Zero::zero())
+ } else {
+ Some(BigInt { sign: Plus, data: self.clone() })
+ }
+ }
+}
+
+macro_rules! impl_to_bigint(
+ ($T:ty, $from_ty:path) => {
+ impl ToBigInt for $T {
+ #[inline]
+ fn to_bigint(&self) -> Option<BigInt> {
+ $from_ty(*self)
+ }
+ }
+ }
+)
+
+impl_to_bigint!(int, FromPrimitive::from_int)
+impl_to_bigint!(i8, FromPrimitive::from_i8)
+impl_to_bigint!(i16, FromPrimitive::from_i16)
+impl_to_bigint!(i32, FromPrimitive::from_i32)
+impl_to_bigint!(i64, FromPrimitive::from_i64)
+impl_to_bigint!(uint, FromPrimitive::from_uint)
+impl_to_bigint!(u8, FromPrimitive::from_u8)
+impl_to_bigint!(u16, FromPrimitive::from_u16)
+impl_to_bigint!(u32, FromPrimitive::from_u32)
+impl_to_bigint!(u64, FromPrimitive::from_u64)
+
+impl ToStrRadix for BigInt {
+ #[inline]
+ fn to_str_radix(&self, radix: uint) -> ~str {
+ match self.sign {
+ Plus => self.data.to_str_radix(radix),
+ Zero => ~"0",
+ Minus => ~"-" + self.data.to_str_radix(radix)
+ }
+ }
+}
+
+impl FromStrRadix for BigInt {
+ /// Creates and initializes a BigInt.
+ #[inline]
+ fn from_str_radix(s: &str, radix: uint) -> Option<BigInt> {
+ BigInt::parse_bytes(s.as_bytes(), radix)
+ }
+}
+
+trait RandBigInt {
+ /// Generate a random `BigUint` of the given bit size.
+ fn gen_biguint(&mut self, bit_size: uint) -> BigUint;
+
+ /// Generate a random BigInt of the given bit size.
+ fn gen_bigint(&mut self, bit_size: uint) -> BigInt;
+
+ /// Generate a random `BigUint` less than the given bound. Fails
+ /// when the bound is zero.
+ fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint;
+
+ /// Generate a random `BigUint` within the given range. The lower
+ /// bound is inclusive; the upper bound is exclusive. Fails when
+ /// the upper bound is not greater than the lower bound.
+ fn gen_biguint_range(&mut self, lbound: &BigUint, ubound: &BigUint) -> BigUint;
+
+ /// Generate a random `BigInt` within the given range. The lower
+ /// bound is inclusive; the upper bound is exclusive. Fails when
+ /// the upper bound is not greater than the lower bound.
+ fn gen_bigint_range(&mut self, lbound: &BigInt, ubound: &BigInt) -> BigInt;
+}
+
+impl<R: Rng> RandBigInt for R {
+ fn gen_biguint(&mut self, bit_size: uint) -> BigUint {
+ let (digits, rem) = bit_size.div_rem(&BigDigit::bits);
+ let mut data = vec::with_capacity(digits+1);
+ for _ in range(0, digits) {
+ data.push(self.gen());
+ }
+ if rem > 0 {
+ let final_digit: BigDigit = self.gen();
+ data.push(final_digit >> (BigDigit::bits - rem));
+ }
+ return BigUint::new(data);
+ }
+
+ fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
+ // Generate a random BigUint...
+ let biguint = self.gen_biguint(bit_size);
+ // ...and then randomly assign it a Sign...
+ let sign = if biguint.is_zero() {
+ // ...except that if the BigUint is zero, we need to try
+ // again with probability 0.5. This is because otherwise,
+ // the probability of generating a zero BigInt would be
+ // double that of any other number.
+ if self.gen() {
+ return self.gen_bigint(bit_size);
+ } else {
+ Zero
+ }
+ } else if self.gen() {
+ Plus
+ } else {
+ Minus
+ };
+ return BigInt::from_biguint(sign, biguint);
+ }
+
+ fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
+ assert!(!bound.is_zero());
+ let bits = bound.bits();
+ loop {
+ let n = self.gen_biguint(bits);
+ if n < *bound { return n; }
+ }
+ }
+
+ fn gen_biguint_range(&mut self,
+ lbound: &BigUint,
+ ubound: &BigUint)
+ -> BigUint {
+ assert!(*lbound < *ubound);
+ return *lbound + self.gen_biguint_below(&(*ubound - *lbound));
+ }
+
+ fn gen_bigint_range(&mut self,
+ lbound: &BigInt,
+ ubound: &BigInt)
+ -> BigInt {
+ assert!(*lbound < *ubound);
+ let delta = (*ubound - *lbound).to_biguint().unwrap();
+ return *lbound + self.gen_biguint_below(&delta).to_bigint().unwrap();
+ }
+}
+
+impl BigInt {
+ /// Creates and initializes a BigInt.
+ #[inline]
+ pub fn new(sign: Sign, v: ~[BigDigit]) -> BigInt {
+ BigInt::from_biguint(sign, BigUint::new(v))
+ }
+
+ /// Creates and initializes a `BigInt`.
+ #[inline]
+ pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
+ if sign == Zero || data.is_zero() {
+ return BigInt { sign: Zero, data: Zero::zero() };
+ }
+ return BigInt { sign: sign, data: data };
+ }
+
+ /// Creates and initializes a `BigInt`.
+ #[inline]
+ pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
+ BigInt::from_biguint(sign, BigUint::from_slice(slice))
+ }
+
+ /// Creates and initializes a `BigInt`.
+ pub fn parse_bytes(buf: &[u8], radix: uint)
+ -> Option<BigInt> {
+ if buf.is_empty() { return None; }
+ let mut sign = Plus;
+ let mut start = 0;
+ if buf[0] == ('-' as u8) {
+ sign = Minus;
+ start = 1;
+ }
+ return BigUint::parse_bytes(buf.slice(start, buf.len()), radix)
+ .map(|bu| BigInt::from_biguint(sign, bu));
+ }
+
+ /// Converts this `BigInt` into a `BigUint`, if it's not negative.
+ #[inline]
+ pub fn to_biguint(&self) -> Option<BigUint> {
+ match self.sign {
+ Plus => Some(self.data.clone()),
+ Zero => Some(Zero::zero()),
+ Minus => None
+ }
+ }
+}
+
+#[cfg(test)]
+mod biguint_tests {
+ use super::{BigDigit, BigUint, ToBigUint};
+ use super::{Plus, BigInt, RandBigInt, ToBigInt};
+
+ use std::cmp::{Less, Equal, Greater};
+ use std::i64;
+ use std::num::{Zero, One, FromStrRadix};
+ use std::num::{ToPrimitive, FromPrimitive};
+ use std::rand::{task_rng};
+ use std::str;
+ use std::u64;
+ use std::vec;
+
+ #[test]
+ fn test_from_slice() {
+ fn check(slice: &[BigDigit], data: &[BigDigit]) {
+ assert!(data == BigUint::from_slice(slice).data);
+ }
+ check([1], [1]);
+ check([0, 0, 0], []);
+ check([1, 2, 0, 0], [1, 2]);
+ check([0, 0, 1, 2], [0, 0, 1, 2]);
+ check([0, 0, 1, 2, 0, 0], [0, 0, 1, 2]);
+ check([-1], [-1]);
+ }
+
+ #[test]
+ fn test_cmp() {
+ let data: ~[BigUint] = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1] ]
+ .map(|v| BigUint::from_slice(*v));
+ for (i, ni) in data.iter().enumerate() {
+ for (j0, nj) in data.slice(i, data.len()).iter().enumerate() {
+ let j = j0 + i;
+ if i == j {
+ assert_eq!(ni.cmp(nj), Equal);
+ assert_eq!(nj.cmp(ni), Equal);
+ assert_eq!(ni, nj);
+ assert!(!(ni != nj));
+ assert!(ni <= nj);
+ assert!(ni >= nj);
+ assert!(!(ni < nj));
+ assert!(!(ni > nj));
+ } else {
+ assert_eq!(ni.cmp(nj), Less);
+ assert_eq!(nj.cmp(ni), Greater);
+
+ assert!(!(ni == nj));
+ assert!(ni != nj);
+
+ assert!(ni <= nj);
+ assert!(!(ni >= nj));
+ assert!(ni < nj);
+ assert!(!(ni > nj));
+
+ assert!(!(nj <= ni));
+ assert!(nj >= ni);
+ assert!(!(nj < ni));
+ assert!(nj > ni);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_bitand() {
+ fn check(left: ~[BigDigit],
+ right: ~[BigDigit],
+ expected: ~[BigDigit]) {
+ assert_eq!(BigUint::new(left) & BigUint::new(right),
+ BigUint::new(expected));
+ }
+ check(~[], ~[], ~[]);
+ check(~[268, 482, 17],
+ ~[964, 54],
+ ~[260, 34]);
+ }
+
+ #[test]
+ fn test_bitor() {
+ fn check(left: ~[BigDigit],
+ right: ~[BigDigit],
+ expected: ~[BigDigit]) {
+ assert_eq!(BigUint::new(left) | BigUint::new(right),
+ BigUint::new(expected));
+ }
+ check(~[], ~[], ~[]);
+ check(~[268, 482, 17],
+ ~[964, 54],
+ ~[972, 502, 17]);
+ }
+
+ #[test]
+ fn test_bitxor() {
+ fn check(left: ~[BigDigit],
+ right: ~[BigDigit],
+ expected: ~[BigDigit]) {
+ assert_eq!(BigUint::new(left) ^ BigUint::new(right),
+ BigUint::new(expected));
+ }
+ check(~[], ~[], ~[]);
+ check(~[268, 482, 17],
+ ~[964, 54],
+ ~[712, 468, 17]);
+ }
+
+ #[test]
+ fn test_shl() {
+ fn check(s: &str, shift: uint, ans: &str) {
+ let opt_biguint: Option<BigUint> = FromStrRadix::from_str_radix(s, 16);
+ let bu = (opt_biguint.unwrap() << shift).to_str_radix(16);
+ assert_eq!(bu.as_slice(), ans);
+ }
+
+ check("0", 3, "0");
+ check("1", 3, "8");
+
+ check("1" + "0000" + "0000" + "0000" + "0001" + "0000" + "0000" + "0000" + "0001", 3,
+ "8" + "0000" + "0000" + "0000" + "0008" + "0000" + "0000" + "0000" + "0008");
+ check("1" + "0000" + "0001" + "0000" + "0001", 2,
+ "4" + "0000" + "0004" + "0000" + "0004");
+ check("1" + "0001" + "0001", 1,
+ "2" + "0002" + "0002");
+
+ check("" + "4000" + "0000" + "0000" + "0000", 3,
+ "2" + "0000" + "0000" + "0000" + "0000");
+ check("" + "4000" + "0000", 2,
+ "1" + "0000" + "0000");
+ check("" + "4000", 2,
+ "1" + "0000");
+
+ check("" + "4000" + "0000" + "0000" + "0000", 67,
+ "2" + "0000" + "0000" + "0000" + "0000" + "0000" + "0000" + "0000" + "0000");
+ check("" + "4000" + "0000", 35,
+ "2" + "0000" + "0000" + "0000" + "0000");
+ check("" + "4000", 19,
+ "2" + "0000" + "0000");
+
+ check("" + "fedc" + "ba98" + "7654" + "3210" + "fedc" + "ba98" + "7654" + "3210", 4,
+ "f" + "edcb" + "a987" + "6543" + "210f" + "edcb" + "a987" + "6543" + "2100");
+ check("88887777666655554444333322221111", 16,
+ "888877776666555544443333222211110000");
+ }
+
+ #[test]
+ fn test_shr() {
+ fn check(s: &str, shift: uint, ans: &str) {
+ let opt_biguint: Option<BigUint> =
+ FromStrRadix::from_str_radix(s, 16);
+ let bu = (opt_biguint.unwrap() >> shift).to_str_radix(16);
+ assert_eq!(bu.as_slice(), ans);
+ }
+
+ check("0", 3, "0");
+ check("f", 3, "1");
+
+ check("1" + "0000" + "0000" + "0000" + "0001" + "0000" + "0000" + "0000" + "0001", 3,
+ "" + "2000" + "0000" + "0000" + "0000" + "2000" + "0000" + "0000" + "0000");
+ check("1" + "0000" + "0001" + "0000" + "0001", 2,
+ "" + "4000" + "0000" + "4000" + "0000");
+ check("1" + "0001" + "0001", 1,
+ "" + "8000" + "8000");
+
+ check("2" + "0000" + "0000" + "0000" + "0001" + "0000" + "0000" + "0000" + "0001", 67,
+ "" + "4000" + "0000" + "0000" + "0000");
+ check("2" + "0000" + "0001" + "0000" + "0001", 35,
+ "" + "4000" + "0000");
+ check("2" + "0001" + "0001", 19,
+ "" + "4000");
+
+ check("1" + "0000" + "0000" + "0000" + "0000", 1,
+ "" + "8000" + "0000" + "0000" + "0000");
+ check("1" + "0000" + "0000", 1,
+ "" + "8000" + "0000");
+ check("1" + "0000", 1,
+ "" + "8000");
+ check("f" + "edcb" + "a987" + "6543" + "210f" + "edcb" + "a987" + "6543" + "2100", 4,
+ "" + "fedc" + "ba98" + "7654" + "3210" + "fedc" + "ba98" + "7654" + "3210");
+
+ check("888877776666555544443333222211110000", 16,
+ "88887777666655554444333322221111");
+ }
+
+ #[cfg(target_word_size = "32")]
+ #[test]
+ fn test_convert_i64() {
+ fn check(b1: BigUint, i: i64) {
+ let b2: BigUint = FromPrimitive::from_i64(i).unwrap();
+ assert!(b1 == b2);
+ assert!(b1.to_i64().unwrap() == i);
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+ check(i64::MAX.to_biguint().unwrap(), i64::MAX);
+
+ check(BigUint::new(~[ ]), 0);
+ check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1 ]), (1 << (2*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 0, 1 ]), (1 << (2*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1, -1 ]), (1 << (3*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 0, 0, 1 ]), (1 << (3*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1, -1, -1 >> 1]), i64::MAX);
+
+ assert_eq!(i64::MIN.to_biguint(), None);
+ assert_eq!(BigUint::new(~[-1, -1, -1, -1 ]).to_i64(), None);
+ assert_eq!(BigUint::new(~[ 0, 0, 0, 0, 1]).to_i64(), None);
+ assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_i64(), None);
+ }
+
+ #[cfg(target_word_size = "64")]
+ #[test]
+ fn test_convert_i64() {
+ fn check(b1: BigUint, i: i64) {
+ let b2: BigUint = FromPrimitive::from_i64(i).unwrap();
+ assert!(b1 == b2);
+ assert!(b1.to_i64().unwrap() == i);
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+ check(i64::MAX.to_biguint().unwrap(), i64::MAX);
+
+ check(BigUint::new(~[ ]), 0);
+ check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1 >> 1]), i64::MAX);
+
+ assert_eq!(i64::MIN.to_biguint(), None);
+ assert_eq!(BigUint::new(~[-1, -1 ]).to_i64(), None);
+ assert_eq!(BigUint::new(~[ 0, 0, 1]).to_i64(), None);
+ assert_eq!(BigUint::new(~[-1, -1, -1]).to_i64(), None);
+ }
+
+ #[cfg(target_word_size = "32")]
+ #[test]
+ fn test_convert_u64() {
+ fn check(b1: BigUint, u: u64) {
+ let b2: BigUint = FromPrimitive::from_u64(u).unwrap();
+ assert!(b1 == b2);
+ assert!(b1.to_u64().unwrap() == u);
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+ check(u64::MIN.to_biguint().unwrap(), u64::MIN);
+ check(u64::MAX.to_biguint().unwrap(), u64::MAX);
+
+ check(BigUint::new(~[ ]), 0);
+ check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1 ]), (1 << (2*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 0, 1 ]), (1 << (2*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1, -1 ]), (1 << (3*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 0, 0, 1]), (1 << (3*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1, -1, -1]), u64::MAX);
+
+ assert_eq!(BigUint::new(~[ 0, 0, 0, 0, 1]).to_u64(), None);
+ assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_u64(), None);
+ }
+
+ #[cfg(target_word_size = "64")]
+ #[test]
+ fn test_convert_u64() {
+ fn check(b1: BigUint, u: u64) {
+ let b2: BigUint = FromPrimitive::from_u64(u).unwrap();
+ assert!(b1 == b2);
+ assert!(b1.to_u64().unwrap() == u);
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+ check(u64::MIN.to_biguint().unwrap(), u64::MIN);
+ check(u64::MAX.to_biguint().unwrap(), u64::MAX);
+
+ check(BigUint::new(~[ ]), 0);
+ check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(~[ 0, 1]), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(~[-1, -1]), u64::MAX);
+
+ assert_eq!(BigUint::new(~[ 0, 0, 1]).to_u64(), None);
+ assert_eq!(BigUint::new(~[-1, -1, -1]).to_u64(), None);
+ }
+
+ #[test]
+ fn test_convert_to_bigint() {
+ fn check(n: BigUint, ans: BigInt) {
+ assert_eq!(n.to_bigint().unwrap(), ans);
+ assert_eq!(n.to_bigint().unwrap().to_biguint().unwrap(), n);
+ }
+ check(Zero::zero(), Zero::zero());
+ check(BigUint::new(~[1,2,3]),
+ BigInt::from_biguint(Plus, BigUint::new(~[1,2,3])));
+ }
+
+ static sum_triples: &'static [(&'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[ 1]),
+ (&[ 1], &[ 1], &[ 2]),
+ (&[ 1], &[ 1, 1], &[ 2, 1]),
+ (&[ 1], &[-1], &[ 0, 1]),
+ (&[ 1], &[-1, -1], &[ 0, 0, 1]),
+ (&[-1, -1], &[-1, -1], &[-2, -1, 1]),
+ (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
+ (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
+ ];
+
+ #[test]
+ fn test_add() {
+ for elm in sum_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ assert!(a + b == c);
+ assert!(b + a == c);
+ }
+ }
+
+ #[test]
+ fn test_sub() {
+ for elm in sum_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ assert!(c - a == b);
+ assert!(c - b == a);
+ }
+ }
+
+ static mul_triples: &'static [(&'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[]),
+ (&[ 2], &[], &[]),
+ (&[ 1], &[ 1], &[1]),
+ (&[ 2], &[ 3], &[ 6]),
+ (&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
+ (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
+ (&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
+ (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
+ (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
+ (&[-1], &[-1], &[ 1, -2]),
+ (&[-1, -1], &[-1], &[ 1, -1, -2]),
+ (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
+ (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
+ (&[-1/2 + 1], &[ 2], &[ 0, 1]),
+ (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]),
+ (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
+ (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
+ (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
+ (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
+ (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
+ ];
+
+ static div_rem_quadruples: &'static [(&'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit])]
+ = &[
+ (&[ 1], &[ 2], &[], &[1]),
+ (&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
+ (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
+ (&[ 0, 1], &[-1], &[1], &[1]),
+ (&[-1, -1], &[-2], &[2, 1], &[3])
+ ];
+
+ #[test]
+ fn test_mul() {
+ for elm in mul_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ assert!(a * b == c);
+ assert!(b * a == c);
+ }
+
+ for elm in div_rem_quadruples.iter() {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+ let d = BigUint::from_slice(dVec);
+
+ assert!(a == b * c + d);
+ assert!(a == c * b + d);
+ }
+ }
+
+ #[test]
+ fn test_div_rem() {
+ for elm in mul_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ if !a.is_zero() {
+ assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero()));
+ }
+ if !b.is_zero() {
+ assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero()));
+ }
+ }
+
+ for elm in div_rem_quadruples.iter() {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+ let d = BigUint::from_slice(dVec);
+
+ if !b.is_zero() { assert!(a.div_rem(&b) == (c, d)); }
+ }
+ }
+
+ #[test]
+ fn test_gcd() {
+ fn check(a: uint, b: uint, c: uint) {
+ let big_a: BigUint = FromPrimitive::from_uint(a).unwrap();
+ let big_b: BigUint = FromPrimitive::from_uint(b).unwrap();
+ let big_c: BigUint = FromPrimitive::from_uint(c).unwrap();
+
+ assert_eq!(big_a.gcd(&big_b), big_c);
+ }
+
+ check(10, 2, 2);
+ check(10, 3, 1);
+ check(0, 3, 3);
+ check(3, 3, 3);
+ check(56, 42, 14);
+ }
+
+ #[test]
+ fn test_lcm() {
+ fn check(a: uint, b: uint, c: uint) {
+ let big_a: BigUint = FromPrimitive::from_uint(a).unwrap();
+ let big_b: BigUint = FromPrimitive::from_uint(b).unwrap();
+ let big_c: BigUint = FromPrimitive::from_uint(c).unwrap();
+
+ assert_eq!(big_a.lcm(&big_b), big_c);
+ }
+
+ check(1, 0, 0);
+ check(0, 1, 0);
+ check(1, 1, 1);
+ check(8, 9, 72);
+ check(11, 5, 55);
+ check(99, 17, 1683);
+ }
+
+ #[test]
+ fn test_is_even() {
+ let one: BigUint = FromStr::from_str("1").unwrap();
+ let two: BigUint = FromStr::from_str("2").unwrap();
+ let thousand: BigUint = FromStr::from_str("1000").unwrap();
+ let big: BigUint = FromStr::from_str("1000000000000000000000").unwrap();
+ let bigger: BigUint = FromStr::from_str("1000000000000000000001").unwrap();
+ assert!(one.is_odd());
+ assert!(two.is_even());
+ assert!(thousand.is_even());
+ assert!(big.is_even());
+ assert!(bigger.is_odd());
+ assert!((one << 64).is_even());
+ assert!(((one << 64) + one).is_odd());
+ }
+
+ fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
+ let bits = BigDigit::bits;
+ ~[( Zero::zero(), ~[
+ (2, ~"0"), (3, ~"0")
+ ]), ( BigUint::from_slice([ 0xff ]), ~[
+ (2, ~"11111111"),
+ (3, ~"100110"),
+ (4, ~"3333"),
+ (5, ~"2010"),
+ (6, ~"1103"),
+ (7, ~"513"),
+ (8, ~"377"),
+ (9, ~"313"),
+ (10, ~"255"),
+ (11, ~"212"),
+ (12, ~"193"),
+ (13, ~"168"),
+ (14, ~"143"),
+ (15, ~"120"),
+ (16, ~"ff")
+ ]), ( BigUint::from_slice([ 0xfff ]), ~[
+ (2, ~"111111111111"),
+ (4, ~"333333"),
+ (16, ~"fff")
+ ]), ( BigUint::from_slice([ 1, 2 ]), ~[
+ (2,
+ ~"10" +
+ str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
+ (4,
+ ~"2" +
+ str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
+ (10, match bits {
+ 32 => ~"8589934593", 16 => ~"131073", _ => fail!()
+ }),
+ (16,
+ ~"2" +
+ str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
+ ]), ( BigUint::from_slice([ 1, 2, 3 ]), ~[
+ (2,
+ ~"11" +
+ str::from_chars(vec::from_elem(bits - 2, '0')) + "10" +
+ str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
+ (4,
+ ~"3" +
+ str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "2" +
+ str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
+ (10, match bits {
+ 32 => ~"55340232229718589441",
+ 16 => ~"12885032961",
+ _ => fail!()
+ }),
+ (16, ~"3" +
+ str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "2" +
+ str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
+ ]) ]
+ }
+
+ #[test]
+ fn test_to_str_radix() {
+ let r = to_str_pairs();
+ for num_pair in r.iter() {
+ let &(ref n, ref rs) = num_pair;
+ for str_pair in rs.iter() {
+ let &(ref radix, ref str) = str_pair;
+ assert_eq!(&n.to_str_radix(*radix), str);
+ }
+ }
+ }
+
+ #[test]
+ fn test_from_str_radix() {
+ let r = to_str_pairs();
+ for num_pair in r.iter() {
+ let &(ref n, ref rs) = num_pair;
+ for str_pair in rs.iter() {
+ let &(ref radix, ref str) = str_pair;
+ assert_eq!(n, &FromStrRadix::from_str_radix(*str, *radix).unwrap());
+ }
+ }
+
+ let zed: Option<BigUint> = FromStrRadix::from_str_radix("Z", 10);
+ assert_eq!(zed, None);
+ let blank: Option<BigUint> = FromStrRadix::from_str_radix("_", 2);
+ assert_eq!(blank, None);
+ let minus_one: Option<BigUint> = FromStrRadix::from_str_radix("-1",
+ 10);
+ assert_eq!(minus_one, None);
+ }
+
+ #[test]
+ fn test_factor() {
+ fn factor(n: uint) -> BigUint {
+ let mut f: BigUint = One::one();
+ for i in range(2, n + 1) {
+ // FIXME(#6102): Assignment operator for BigInt causes ICE
+ // f *= FromPrimitive::from_uint(i);
+ f = f * FromPrimitive::from_uint(i).unwrap();
+ }
+ return f;
+ }
+
+ fn check(n: uint, s: &str) {
+ let n = factor(n);
+ let ans = match FromStrRadix::from_str_radix(s, 10) {
+ Some(x) => x, None => fail!()
+ };
+ assert_eq!(n, ans);
+ }
+
+ check(3, "6");
+ check(10, "3628800");
+ check(20, "2432902008176640000");
+ check(30, "265252859812191058636308480000000");
+ }
+
+ #[test]
+ fn test_bits() {
+ assert_eq!(BigUint::new(~[0,0,0,0]).bits(), 0);
+ let n: BigUint = FromPrimitive::from_uint(0).unwrap();
+ assert_eq!(n.bits(), 0);
+ let n: BigUint = FromPrimitive::from_uint(1).unwrap();
+ assert_eq!(n.bits(), 1);
+ let n: BigUint = FromPrimitive::from_uint(3).unwrap();
+ assert_eq!(n.bits(), 2);
+ let n: BigUint = FromStrRadix::from_str_radix("4000000000", 16).unwrap();
+ assert_eq!(n.bits(), 39);
+ let one: BigUint = One::one();
+ assert_eq!((one << 426).bits(), 427);
+ }
+
+ #[test]
+ fn test_rand() {
+ let mut rng = task_rng();
+ let _n: BigUint = rng.gen_biguint(137);
+ assert!(rng.gen_biguint(0).is_zero());
+ }
+
+ #[test]
+ fn test_rand_range() {
+ let mut rng = task_rng();
+
+ for _ in range(0, 10) {
+ assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_uint(236).unwrap(),
+ &FromPrimitive::from_uint(237).unwrap()),
+ FromPrimitive::from_uint(236).unwrap());
+ }
+
+ let l = FromPrimitive::from_uint(403469000 + 2352).unwrap();
+ let u = FromPrimitive::from_uint(403469000 + 3513).unwrap();
+ for _ in range(0, 1000) {
+ let n: BigUint = rng.gen_biguint_below(&u);
+ assert!(n < u);
+
+ let n: BigUint = rng.gen_biguint_range(&l, &u);
+ assert!(n >= l);
+ assert!(n < u);
+ }
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_zero_rand_range() {
+ task_rng().gen_biguint_range(&FromPrimitive::from_uint(54).unwrap(),
+ &FromPrimitive::from_uint(54).unwrap());
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_negative_rand_range() {
+ let mut rng = task_rng();
+ let l = FromPrimitive::from_uint(2352).unwrap();
+ let u = FromPrimitive::from_uint(3513).unwrap();
+ // Switching u and l should fail:
+ let _n: BigUint = rng.gen_biguint_range(&u, &l);
+ }
+}
+
+#[cfg(test)]
+mod bigint_tests {
+ use super::{BigDigit, BigUint, ToBigUint};
+ use super::{Sign, Minus, Zero, Plus, BigInt, RandBigInt, ToBigInt};
+
+ use std::cmp::{Less, Equal, Greater};
+ use std::i64;
+ use std::num::{Zero, One, FromStrRadix};
+ use std::num::{ToPrimitive, FromPrimitive};
+ use std::rand::{task_rng};
+ use std::u64;
+
+ #[test]
+ fn test_from_biguint() {
+ fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) {
+ let inp = BigInt::from_biguint(inp_s, FromPrimitive::from_uint(inp_n).unwrap());
+ let ans = BigInt { sign: ans_s, data: FromPrimitive::from_uint(ans_n).unwrap()};
+ assert_eq!(inp, ans);
+ }
+ check(Plus, 1, Plus, 1);
+ check(Plus, 0, Zero, 0);
+ check(Minus, 1, Minus, 1);
+ check(Zero, 1, Zero, 0);
+ }
+
+ #[test]
+ fn test_cmp() {
+ let vs = [ &[2 as BigDigit], &[1, 1], &[2, 1], &[1, 1, 1] ];
+ let mut nums = ~[];
+ for s in vs.rev_iter() {
+ nums.push(BigInt::from_slice(Minus, *s));
+ }
+ nums.push(Zero::zero());
+ nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
+
+ for (i, ni) in nums.iter().enumerate() {
+ for (j0, nj) in nums.slice(i, nums.len()).iter().enumerate() {
+ let j = i + j0;
+ if i == j {
+ assert_eq!(ni.cmp(nj), Equal);
+ assert_eq!(nj.cmp(ni), Equal);
+ assert_eq!(ni, nj);
+ assert!(!(ni != nj));
+ assert!(ni <= nj);
+ assert!(ni >= nj);
+ assert!(!(ni < nj));
+ assert!(!(ni > nj));
+ } else {
+ assert_eq!(ni.cmp(nj), Less);
+ assert_eq!(nj.cmp(ni), Greater);
+
+ assert!(!(ni == nj));
+ assert!(ni != nj);
+
+ assert!(ni <= nj);
+ assert!(!(ni >= nj));
+ assert!(ni < nj);
+ assert!(!(ni > nj));
+
+ assert!(!(nj <= ni));
+ assert!(nj >= ni);
+ assert!(!(nj < ni));
+ assert!(nj > ni);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_convert_i64() {
+ fn check(b1: BigInt, i: i64) {
+ let b2: BigInt = FromPrimitive::from_i64(i).unwrap();
+ assert!(b1 == b2);
+ assert!(b1.to_i64().unwrap() == i);
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+ check(i64::MIN.to_bigint().unwrap(), i64::MIN);
+ check(i64::MAX.to_bigint().unwrap(), i64::MAX);
+
+ assert_eq!(
+ (i64::MAX as u64 + 1).to_bigint().unwrap().to_i64(),
+ None);
+
+ assert_eq!(
+ BigInt::from_biguint(Plus, BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
+ None);
+
+ assert_eq!(
+ BigInt::from_biguint(Minus, BigUint::new(~[1, 0, 0, 1<<(BigDigit::bits-1)])).to_i64(),
+ None);
+
+ assert_eq!(
+ BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
+ None);
+ }
+
+ #[test]
+ fn test_convert_u64() {
+ fn check(b1: BigInt, u: u64) {
+ let b2: BigInt = FromPrimitive::from_u64(u).unwrap();
+ assert!(b1 == b2);
+ assert!(b1.to_u64().unwrap() == u);
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+ check(u64::MIN.to_bigint().unwrap(), u64::MIN);
+ check(u64::MAX.to_bigint().unwrap(), u64::MAX);
+
+ assert_eq!(
+ BigInt::from_biguint(Plus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(),
+ None);
+
+ let max_value: BigUint = FromPrimitive::from_u64(u64::MAX).unwrap();
+ assert_eq!(BigInt::from_biguint(Minus, max_value).to_u64(), None);
+ assert_eq!(BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(), None);
+ }
+
+ #[test]
+ fn test_convert_to_biguint() {
+ fn check(n: BigInt, ans_1: BigUint) {
+ assert_eq!(n.to_biguint().unwrap(), ans_1);
+ assert_eq!(n.to_biguint().unwrap().to_bigint().unwrap(), n);
+ }
+ let zero: BigInt = Zero::zero();
+ let unsigned_zero: BigUint = Zero::zero();
+ let positive = BigInt::from_biguint(
+ Plus, BigUint::new(~[1,2,3]));
+ let negative = -positive;
+
+ check(zero, unsigned_zero);
+ check(positive, BigUint::new(~[1,2,3]));
+
+ assert_eq!(negative.to_biguint(), None);
+ }
+
+ static sum_triples: &'static [(&'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[ 1]),
+ (&[ 1], &[ 1], &[ 2]),
+ (&[ 1], &[ 1, 1], &[ 2, 1]),
+ (&[ 1], &[-1], &[ 0, 1]),
+ (&[ 1], &[-1, -1], &[ 0, 0, 1]),
+ (&[-1, -1], &[-1, -1], &[-2, -1, 1]),
+ (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
+ (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
+ ];
+
+ #[test]
+ fn test_add() {
+ for elm in sum_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ assert!(a + b == c);
+ assert!(b + a == c);
+ assert!(c + (-a) == b);
+ assert!(c + (-b) == a);
+ assert!(a + (-c) == (-b));
+ assert!(b + (-c) == (-a));
+ assert!((-a) + (-b) == (-c))
+ assert!(a + (-a) == Zero::zero());
+ }
+ }
+
+ #[test]
+ fn test_sub() {
+ for elm in sum_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ assert!(c - a == b);
+ assert!(c - b == a);
+ assert!((-b) - a == (-c))
+ assert!((-a) - b == (-c))
+ assert!(b - (-a) == c);
+ assert!(a - (-b) == c);
+ assert!((-c) - (-a) == (-b));
+ assert!(a - a == Zero::zero());
+ }
+ }
+
+ static mul_triples: &'static [(&'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[]),
+ (&[ 2], &[], &[]),
+ (&[ 1], &[ 1], &[1]),
+ (&[ 2], &[ 3], &[ 6]),
+ (&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
+ (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
+ (&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
+ (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
+ (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
+ (&[-1], &[-1], &[ 1, -2]),
+ (&[-1, -1], &[-1], &[ 1, -1, -2]),
+ (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
+ (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
+ (&[-1/2 + 1], &[ 2], &[ 0, 1]),
+ (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]),
+ (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
+ (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
+ (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
+ (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
+ (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
+ ];
+
+ static div_rem_quadruples: &'static [(&'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit],
+ &'static [BigDigit])]
+ = &[
+ (&[ 1], &[ 2], &[], &[1]),
+ (&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
+ (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
+ (&[ 0, 1], &[-1], &[1], &[1]),
+ (&[-1, -1], &[-2], &[2, 1], &[3])
+ ];
+
+ #[test]
+ fn test_mul() {
+ for elm in mul_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ assert!(a * b == c);
+ assert!(b * a == c);
+
+ assert!((-a) * b == -c);
+ assert!((-b) * a == -c);
+ }
+
+ for elm in div_rem_quadruples.iter() {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+ let d = BigInt::from_slice(Plus, dVec);
+
+ assert!(a == b * c + d);
+ assert!(a == c * b + d);
+ }
+ }
+
+ #[test]
+ fn test_div_mod_floor() {
+ fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
+ let (d, m) = a.div_mod_floor(b);
+ if !m.is_zero() {
+ assert_eq!(m.sign, b.sign);
+ }
+ assert!(m.abs() <= b.abs());
+ assert!(*a == b * d + m);
+ assert!(d == *ans_d);
+ assert!(m == *ans_m);
+ }
+
+ fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) {
+ if m.is_zero() {
+ check_sub(a, b, d, m);
+ check_sub(a, &b.neg(), &d.neg(), m);
+ check_sub(&a.neg(), b, &d.neg(), m);
+ check_sub(&a.neg(), &b.neg(), d, m);
+ } else {
+ check_sub(a, b, d, m);
+ check_sub(a, &b.neg(), &(d.neg() - One::one()), &(m - *b));
+ check_sub(&a.neg(), b, &(d.neg() - One::one()), &(b - *m));
+ check_sub(&a.neg(), &b.neg(), d, &m.neg());
+ }
+ }
+
+ for elm in mul_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
+ if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
+ }
+
+ for elm in div_rem_quadruples.iter() {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+ let d = BigInt::from_slice(Plus, dVec);
+
+ if !b.is_zero() {
+ check(&a, &b, &c, &d);
+ }
+ }
+ }
+
+
+ #[test]
+ fn test_div_rem() {
+ fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
+ let (q, r) = a.div_rem(b);
+ if !r.is_zero() {
+ assert_eq!(r.sign, a.sign);
+ }
+ assert!(r.abs() <= b.abs());
+ assert!(*a == b * q + r);
+ assert!(q == *ans_q);
+ assert!(r == *ans_r);
+ }
+
+ fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) {
+ check_sub(a, b, q, r);
+ check_sub(a, &b.neg(), &q.neg(), r);
+ check_sub(&a.neg(), b, &q.neg(), &r.neg());
+ check_sub(&a.neg(), &b.neg(), q, &r.neg());
+ }
+ for elm in mul_triples.iter() {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
+ if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
+ }
+
+ for elm in div_rem_quadruples.iter() {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+ let d = BigInt::from_slice(Plus, dVec);
+
+ if !b.is_zero() {
+ check(&a, &b, &c, &d);
+ }
+ }
+ }
+
+ #[test]
+ fn test_gcd() {
+ fn check(a: int, b: int, c: int) {
+ let big_a: BigInt = FromPrimitive::from_int(a).unwrap();
+ let big_b: BigInt = FromPrimitive::from_int(b).unwrap();
+ let big_c: BigInt = FromPrimitive::from_int(c).unwrap();
+
+ assert_eq!(big_a.gcd(&big_b), big_c);
+ }
+
+ check(10, 2, 2);
+ check(10, 3, 1);
+ check(0, 3, 3);
+ check(3, 3, 3);
+ check(56, 42, 14);
+ check(3, -3, 3);
+ check(-6, 3, 3);
+ check(-4, -2, 2);
+ }
+
+ #[test]
+ fn test_lcm() {
+ fn check(a: int, b: int, c: int) {
+ let big_a: BigInt = FromPrimitive::from_int(a).unwrap();
+ let big_b: BigInt = FromPrimitive::from_int(b).unwrap();
+ let big_c: BigInt = FromPrimitive::from_int(c).unwrap();
+
+ assert_eq!(big_a.lcm(&big_b), big_c);
+ }
+
+ check(1, 0, 0);
+ check(0, 1, 0);
+ check(1, 1, 1);
+ check(-1, 1, 1);
+ check(1, -1, 1);
+ check(-1, -1, 1);
+ check(8, 9, 72);
+ check(11, 5, 55);
+ }
+
+ #[test]
+ fn test_abs_sub() {
+ let zero: BigInt = Zero::zero();
+ let one: BigInt = One::one();
+ assert_eq!((-one).abs_sub(&one), zero);
+ let one: BigInt = One::one();
+ let zero: BigInt = Zero::zero();
+ assert_eq!(one.abs_sub(&one), zero);
+ let one: BigInt = One::one();
+ let zero: BigInt = Zero::zero();
+ assert_eq!(one.abs_sub(&zero), one);
+ let one: BigInt = One::one();
+ let two: BigInt = FromPrimitive::from_int(2).unwrap();
+ assert_eq!(one.abs_sub(&-one), two);
+ }
+
+ #[test]
+ fn test_to_str_radix() {
+ fn check(n: int, ans: &str) {
+ let n: BigInt = FromPrimitive::from_int(n).unwrap();
+ assert!(ans == n.to_str_radix(10));
+ }
+ check(10, "10");
+ check(1, "1");
+ check(0, "0");
+ check(-1, "-1");
+ check(-10, "-10");
+ }
+
+
+ #[test]
+ fn test_from_str_radix() {
+ fn check(s: &str, ans: Option<int>) {
+ let ans = ans.map(|n| {
+ let x: BigInt = FromPrimitive::from_int(n).unwrap();
+ x
+ });
+ assert_eq!(FromStrRadix::from_str_radix(s, 10), ans);
+ }
+ check("10", Some(10));
+ check("1", Some(1));
+ check("0", Some(0));
+ check("-1", Some(-1));
+ check("-10", Some(-10));
+ check("Z", None);
+ check("_", None);
+
+ // issue 10522, this hit an edge case that caused it to
+ // attempt to allocate a vector of size (-1u) == huge.
+ let x: BigInt = from_str("1" + "0".repeat(36)).unwrap();
+ let _y = x.to_str();
+ }
+
+ #[test]
+ fn test_neg() {
+ assert!(-BigInt::new(Plus, ~[1, 1, 1]) ==
+ BigInt::new(Minus, ~[1, 1, 1]));
+ assert!(-BigInt::new(Minus, ~[1, 1, 1]) ==
+ BigInt::new(Plus, ~[1, 1, 1]));
+ let zero: BigInt = Zero::zero();
+ assert_eq!(-zero, zero);
+ }
+
+ #[test]
+ fn test_rand() {
+ let mut rng = task_rng();
+ let _n: BigInt = rng.gen_bigint(137);
+ assert!(rng.gen_bigint(0).is_zero());
+ }
+
+ #[test]
+ fn test_rand_range() {
+ let mut rng = task_rng();
+
+ for _ in range(0, 10) {
+ assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_uint(236).unwrap(),
+ &FromPrimitive::from_uint(237).unwrap()),
+ FromPrimitive::from_uint(236).unwrap());
+ }
+
+ fn check(l: BigInt, u: BigInt) {
+ let mut rng = task_rng();
+ for _ in range(0, 1000) {
+ let n: BigInt = rng.gen_bigint_range(&l, &u);
+ assert!(n >= l);
+ assert!(n < u);
+ }
+ }
+ let l: BigInt = FromPrimitive::from_uint(403469000 + 2352).unwrap();
+ let u: BigInt = FromPrimitive::from_uint(403469000 + 3513).unwrap();
+ check( l.clone(), u.clone());
+ check(-l.clone(), u.clone());
+ check(-u.clone(), -l.clone());
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_zero_rand_range() {
+ task_rng().gen_bigint_range(&FromPrimitive::from_int(54).unwrap(),
+ &FromPrimitive::from_int(54).unwrap());
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_negative_rand_range() {
+ let mut rng = task_rng();
+ let l = FromPrimitive::from_uint(2352).unwrap();
+ let u = FromPrimitive::from_uint(3513).unwrap();
+ // Switching u and l should fail:
+ let _n: BigInt = rng.gen_bigint_range(&u, &l);
+ }
+}
+
+#[cfg(test)]
+mod bench {
+ use super::{BigInt, BigUint};
+ use std::iter;
+ use std::mem::replace;
+ use std::num::{FromPrimitive, Zero, One};
+ use extra::test::BenchHarness;
+
+ fn factorial(n: uint) -> BigUint {
+ let mut f: BigUint = One::one();
+ for i in iter::range_inclusive(1, n) {
+ f = f * FromPrimitive::from_uint(i).unwrap();
+ }
+ f
+ }
+
+ fn fib(n: uint) -> BigUint {
+ let mut f0: BigUint = Zero::zero();
+ let mut f1: BigUint = One::one();
+ for _ in range(0, n) {
+ let f2 = f0 + f1;
+ f0 = replace(&mut f1, f2);
+ }
+ f0
+ }
+
+ #[bench]
+ fn factorial_100(bh: &mut BenchHarness) {
+ bh.iter(|| {
+ factorial(100);
+ });
+ }
+
+ #[bench]
+ fn fib_100(bh: &mut BenchHarness) {
+ bh.iter(|| {
+ fib(100);
+ });
+ }
+
+ #[bench]
+ fn to_str(bh: &mut BenchHarness) {
+ let fac = factorial(100);
+ let fib = fib(100);
+ bh.iter(|| {
+ fac.to_str();
+ });
+ bh.iter(|| {
+ fib.to_str();
+ });
+ }
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+//! Complex numbers.
+
+use std::num::{Zero,One,ToStrRadix};
+
+// FIXME #1284: handle complex NaN & infinity etc. This
+// probably doesn't map to C's _Complex correctly.
+
+// FIXME #5734:: Need generic sin/cos for .to/from_polar().
+// FIXME #5735: Need generic sqrt to implement .norm().
+
+
+/// A complex number in Cartesian form.
+#[deriving(Eq,Clone)]
+pub struct Cmplx<T> {
+ /// Real portion of the complex number
+ re: T,
+ /// Imaginary portion of the complex number
+ im: T
+}
+
+pub type Complex32 = Cmplx<f32>;
+pub type Complex64 = Cmplx<f64>;
+
+impl<T: Clone + Num> Cmplx<T> {
+ /// Create a new Cmplx
+ #[inline]
+ pub fn new(re: T, im: T) -> Cmplx<T> {
+ Cmplx { re: re, im: im }
+ }
+
+ /**
+ Returns the square of the norm (since `T` doesn't necessarily
+ have a sqrt function), i.e. `re^2 + im^2`.
+ */
+ #[inline]
+ pub fn norm_sqr(&self) -> T {
+ self.re * self.re + self.im * self.im
+ }
+
+
+ /// Returns the complex conjugate. i.e. `re - i im`
+ #[inline]
+ pub fn conj(&self) -> Cmplx<T> {
+ Cmplx::new(self.re.clone(), -self.im)
+ }
+
+
+ /// Multiplies `self` by the scalar `t`.
+ #[inline]
+ pub fn scale(&self, t: T) -> Cmplx<T> {
+ Cmplx::new(self.re * t, self.im * t)
+ }
+
+ /// Divides `self` by the scalar `t`.
+ #[inline]
+ pub fn unscale(&self, t: T) -> Cmplx<T> {
+ Cmplx::new(self.re / t, self.im / t)
+ }
+
+ /// Returns `1/self`
+ #[inline]
+ pub fn inv(&self) -> Cmplx<T> {
+ let norm_sqr = self.norm_sqr();
+ Cmplx::new(self.re / norm_sqr,
+ -self.im / norm_sqr)
+ }
+}
+
+impl<T: Clone + Real> Cmplx<T> {
+ /// Calculate |self|
+ #[inline]
+ pub fn norm(&self) -> T {
+ self.re.hypot(&self.im)
+ }
+}
+
+impl<T: Clone + Real> Cmplx<T> {
+ /// Calculate the principal Arg of self.
+ #[inline]
+ pub fn arg(&self) -> T {
+ self.im.atan2(&self.re)
+ }
+ /// Convert to polar form (r, theta), such that `self = r * exp(i
+ /// * theta)`
+ #[inline]
+ pub fn to_polar(&self) -> (T, T) {
+ (self.norm(), self.arg())
+ }
+ /// Convert a polar representation into a complex number.
+ #[inline]
+ pub fn from_polar(r: &T, theta: &T) -> Cmplx<T> {
+ Cmplx::new(r * theta.cos(), r * theta.sin())
+ }
+}
+
+/* arithmetic */
+// (a + i b) + (c + i d) == (a + c) + i (b + d)
+impl<T: Clone + Num> Add<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
+ #[inline]
+ fn add(&self, other: &Cmplx<T>) -> Cmplx<T> {
+ Cmplx::new(self.re + other.re, self.im + other.im)
+ }
+}
+// (a + i b) - (c + i d) == (a - c) + i (b - d)
+impl<T: Clone + Num> Sub<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
+ #[inline]
+ fn sub(&self, other: &Cmplx<T>) -> Cmplx<T> {
+ Cmplx::new(self.re - other.re, self.im - other.im)
+ }
+}
+// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
+impl<T: Clone + Num> Mul<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
+ #[inline]
+ fn mul(&self, other: &Cmplx<T>) -> Cmplx<T> {
+ Cmplx::new(self.re*other.re - self.im*other.im,
+ self.re*other.im + self.im*other.re)
+ }
+}
+
+// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
+// == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
+impl<T: Clone + Num> Div<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
+ #[inline]
+ fn div(&self, other: &Cmplx<T>) -> Cmplx<T> {
+ let norm_sqr = other.norm_sqr();
+ Cmplx::new((self.re*other.re + self.im*other.im) / norm_sqr,
+ (self.im*other.re - self.re*other.im) / norm_sqr)
+ }
+}
+
+impl<T: Clone + Num> Neg<Cmplx<T>> for Cmplx<T> {
+ #[inline]
+ fn neg(&self) -> Cmplx<T> {
+ Cmplx::new(-self.re, -self.im)
+ }
+}
+
+/* constants */
+impl<T: Clone + Num> Zero for Cmplx<T> {
+ #[inline]
+ fn zero() -> Cmplx<T> {
+ Cmplx::new(Zero::zero(), Zero::zero())
+ }
+
+ #[inline]
+ fn is_zero(&self) -> bool {
+ self.re.is_zero() && self.im.is_zero()
+ }
+}
+
+impl<T: Clone + Num> One for Cmplx<T> {
+ #[inline]
+ fn one() -> Cmplx<T> {
+ Cmplx::new(One::one(), Zero::zero())
+ }
+}
+
+/* string conversions */
+impl<T: ToStr + Num + Ord> ToStr for Cmplx<T> {
+ fn to_str(&self) -> ~str {
+ if self.im < Zero::zero() {
+ format!("{}-{}i", self.re.to_str(), (-self.im).to_str())
+ } else {
+ format!("{}+{}i", self.re.to_str(), self.im.to_str())
+ }
+ }
+}
+
+impl<T: ToStrRadix + Num + Ord> ToStrRadix for Cmplx<T> {
+ fn to_str_radix(&self, radix: uint) -> ~str {
+ if self.im < Zero::zero() {
+ format!("{}-{}i", self.re.to_str_radix(radix), (-self.im).to_str_radix(radix))
+ } else {
+ format!("{}+{}i", self.re.to_str_radix(radix), self.im.to_str_radix(radix))
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ #[allow(non_uppercase_statics)];
+
+ use super::{Complex64, Cmplx};
+ use std::num::{Zero,One,Real};
+
+ pub static _0_0i : Complex64 = Cmplx { re: 0.0, im: 0.0 };
+ pub static _1_0i : Complex64 = Cmplx { re: 1.0, im: 0.0 };
+ pub static _1_1i : Complex64 = Cmplx { re: 1.0, im: 1.0 };
+ pub static _0_1i : Complex64 = Cmplx { re: 0.0, im: 1.0 };
+ pub static _neg1_1i : Complex64 = Cmplx { re: -1.0, im: 1.0 };
+ pub static _05_05i : Complex64 = Cmplx { re: 0.5, im: 0.5 };
+ pub static all_consts : [Complex64, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];
+
+ #[test]
+ fn test_consts() {
+ // check our constants are what Cmplx::new creates
+ fn test(c : Complex64, r : f64, i: f64) {
+ assert_eq!(c, Cmplx::new(r,i));
+ }
+ test(_0_0i, 0.0, 0.0);
+ test(_1_0i, 1.0, 0.0);
+ test(_1_1i, 1.0, 1.0);
+ test(_neg1_1i, -1.0, 1.0);
+ test(_05_05i, 0.5, 0.5);
+
+ assert_eq!(_0_0i, Zero::zero());
+ assert_eq!(_1_0i, One::one());
+ }
+
+ #[test]
+ #[ignore(cfg(target_arch = "x86"))]
+ // FIXME #7158: (maybe?) currently failing on x86.
+ fn test_norm() {
+ fn test(c: Complex64, ns: f64) {
+ assert_eq!(c.norm_sqr(), ns);
+ assert_eq!(c.norm(), ns.sqrt())
+ }
+ test(_0_0i, 0.0);
+ test(_1_0i, 1.0);
+ test(_1_1i, 2.0);
+ test(_neg1_1i, 2.0);
+ test(_05_05i, 0.5);
+ }
+
+ #[test]
+ fn test_scale_unscale() {
+ assert_eq!(_05_05i.scale(2.0), _1_1i);
+ assert_eq!(_1_1i.unscale(2.0), _05_05i);
+ for &c in all_consts.iter() {
+ assert_eq!(c.scale(2.0).unscale(2.0), c);
+ }
+ }
+
+ #[test]
+ fn test_conj() {
+ for &c in all_consts.iter() {
+ assert_eq!(c.conj(), Cmplx::new(c.re, -c.im));
+ assert_eq!(c.conj().conj(), c);
+ }
+ }
+
+ #[test]
+ fn test_inv() {
+ assert_eq!(_1_1i.inv(), _05_05i.conj());
+ assert_eq!(_1_0i.inv(), _1_0i.inv());
+ }
+
+ #[test]
+ #[should_fail]
+ #[ignore]
+ fn test_inv_zero() {
+ // FIXME #5736: should this really fail, or just NaN?
+ _0_0i.inv();
+ }
+
+ #[test]
+ fn test_arg() {
+ fn test(c: Complex64, arg: f64) {
+ assert!((c.arg() - arg).abs() < 1.0e-6)
+ }
+ test(_1_0i, 0.0);
+ test(_1_1i, 0.25 * Real::pi());
+ test(_neg1_1i, 0.75 * Real::pi());
+ test(_05_05i, 0.25 * Real::pi());
+ }
+
+ #[test]
+ fn test_polar_conv() {
+ fn test(c: Complex64) {
+ let (r, theta) = c.to_polar();
+ assert!((c - Cmplx::from_polar(&r, &theta)).norm() < 1e-6);
+ }
+ for &c in all_consts.iter() { test(c); }
+ }
+
+ mod arith {
+ use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, all_consts};
+ use std::num::Zero;
+
+ #[test]
+ fn test_add() {
+ assert_eq!(_05_05i + _05_05i, _1_1i);
+ assert_eq!(_0_1i + _1_0i, _1_1i);
+ assert_eq!(_1_0i + _neg1_1i, _0_1i);
+
+ for &c in all_consts.iter() {
+ assert_eq!(_0_0i + c, c);
+ assert_eq!(c + _0_0i, c);
+ }
+ }
+
+ #[test]
+ fn test_sub() {
+ assert_eq!(_05_05i - _05_05i, _0_0i);
+ assert_eq!(_0_1i - _1_0i, _neg1_1i);
+ assert_eq!(_0_1i - _neg1_1i, _1_0i);
+
+ for &c in all_consts.iter() {
+ assert_eq!(c - _0_0i, c);
+ assert_eq!(c - c, _0_0i);
+ }
+ }
+
+ #[test]
+ fn test_mul() {
+ assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2.0));
+ assert_eq!(_1_1i * _0_1i, _neg1_1i);
+
+ // i^2 & i^4
+ assert_eq!(_0_1i * _0_1i, -_1_0i);
+ assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);
+
+ for &c in all_consts.iter() {
+ assert_eq!(c * _1_0i, c);
+ assert_eq!(_1_0i * c, c);
+ }
+ }
+ #[test]
+ fn test_div() {
+ assert_eq!(_neg1_1i / _0_1i, _1_1i);
+ for &c in all_consts.iter() {
+ if c != Zero::zero() {
+ assert_eq!(c / c, _1_0i);
+ }
+ }
+ }
+ #[test]
+ fn test_neg() {
+ assert_eq!(-_1_0i + _0_1i, _neg1_1i);
+ assert_eq!((-_0_1i) * _0_1i, _1_0i);
+ for &c in all_consts.iter() {
+ assert_eq!(-(-c), c);
+ }
+ }
+ }
+
+ #[test]
+ fn test_to_str() {
+ fn test(c : Complex64, s: ~str) {
+ assert_eq!(c.to_str(), s);
+ }
+ test(_0_0i, ~"0+0i");
+ test(_1_0i, ~"1+0i");
+ test(_0_1i, ~"0+1i");
+ test(_1_1i, ~"1+1i");
+ test(_neg1_1i, ~"-1+1i");
+ test(-_neg1_1i, ~"1-1i");
+ test(_05_05i, ~"0.5+0.5i");
+ }
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[feature(macro_rules)];
+
+#[crate_id = "num#0.10-pre"];
+#[crate_type = "rlib"];
+#[crate_type = "dylib"];
+#[license = "MIT/ASL2"];
+
+extern mod extra;
+
+pub mod bigint;
+pub mod rational;
+pub mod complex;
--- /dev/null
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Rational numbers
+
+use std::cmp;
+use std::from_str::FromStr;
+use std::num::{Zero,One,ToStrRadix,FromStrRadix,Round};
+use bigint::{BigInt, BigUint, Sign, Plus, Minus};
+
+/// Represents the ratio between 2 numbers.
+#[deriving(Clone)]
+#[allow(missing_doc)]
+pub struct Ratio<T> {
+ priv numer: T,
+ priv denom: T
+}
+
+/// Alias for a `Ratio` of machine-sized integers.
+pub type Rational = Ratio<int>;
+pub type Rational32 = Ratio<i32>;
+pub type Rational64 = Ratio<i64>;
+
+/// Alias for arbitrary precision rationals.
+pub type BigRational = Ratio<BigInt>;
+
+impl<T: Clone + Integer + Ord>
+ Ratio<T> {
+ /// Create a ratio representing the integer `t`.
+ #[inline]
+ pub fn from_integer(t: T) -> Ratio<T> {
+ Ratio::new_raw(t, One::one())
+ }
+
+ /// Create a ratio without checking for `denom == 0` or reducing.
+ #[inline]
+ pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
+ Ratio { numer: numer, denom: denom }
+ }
+
+ /// Create a new Ratio. Fails if `denom == 0`.
+ #[inline]
+ pub fn new(numer: T, denom: T) -> Ratio<T> {
+ if denom == Zero::zero() {
+ fail!("denominator == 0");
+ }
+ let mut ret = Ratio::new_raw(numer, denom);
+ ret.reduce();
+ ret
+ }
+
+ /// Convert to an integer.
+ #[inline]
+ pub fn to_integer(&self) -> T {
+ self.trunc().numer
+ }
+
+ /// Gets an immutable reference to the numerator.
+ #[inline]
+ pub fn numer<'a>(&'a self) -> &'a T {
+ &self.numer
+ }
+
+ /// Gets an immutable reference to the denominator.
+ #[inline]
+ pub fn denom<'a>(&'a self) -> &'a T {
+ &self.denom
+ }
+
+ /// Return true if the rational number is an integer (denominator is 1).
+ #[inline]
+ pub fn is_integer(&self) -> bool {
+ self.denom == One::one()
+ }
+
+ /// Put self into lowest terms, with denom > 0.
+ fn reduce(&mut self) {
+ let g : T = self.numer.gcd(&self.denom);
+
+ // FIXME(#6050): overloaded operators force moves with generic types
+ // self.numer /= g;
+ self.numer = self.numer / g;
+ // FIXME(#6050): overloaded operators force moves with generic types
+ // self.denom /= g;
+ self.denom = self.denom / g;
+
+ // keep denom positive!
+ if self.denom < Zero::zero() {
+ self.numer = -self.numer;
+ self.denom = -self.denom;
+ }
+ }
+
+ /// Return a `reduce`d copy of self.
+ pub fn reduced(&self) -> Ratio<T> {
+ let mut ret = self.clone();
+ ret.reduce();
+ ret
+ }
+
+ /// Return the reciprocal
+ #[inline]
+ pub fn recip(&self) -> Ratio<T> {
+ Ratio::new_raw(self.denom.clone(), self.numer.clone())
+ }
+}
+
+impl Ratio<BigInt> {
+ /// Converts a float into a rational number
+ pub fn from_float<T: Float>(f: T) -> Option<BigRational> {
+ if !f.is_finite() {
+ return None;
+ }
+ let (mantissa, exponent, sign) = f.integer_decode();
+ let bigint_sign: Sign = if sign == 1 { Plus } else { Minus };
+ if exponent < 0 {
+ let one: BigInt = One::one();
+ let denom: BigInt = one << ((-exponent) as uint);
+ let numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
+ Some(Ratio::new(BigInt::from_biguint(bigint_sign, numer), denom))
+ } else {
+ let mut numer: BigUint = FromPrimitive::from_u64(mantissa).unwrap();
+ numer = numer << (exponent as uint);
+ Some(Ratio::from_integer(BigInt::from_biguint(bigint_sign, numer)))
+ }
+ }
+}
+
+/* Comparisons */
+
+// comparing a/b and c/d is the same as comparing a*d and b*c, so we
+// abstract that pattern. The following macro takes a trait and either
+// a comma-separated list of "method name -> return value" or just
+// "method name" (return value is bool in that case)
+macro_rules! cmp_impl {
+ (impl $imp:ident, $($method:ident),+) => {
+ cmp_impl!(impl $imp, $($method -> bool),+)
+ };
+ // return something other than a Ratio<T>
+ (impl $imp:ident, $($method:ident -> $res:ty),+) => {
+ impl<T: Mul<T,T> + $imp> $imp for Ratio<T> {
+ $(
+ #[inline]
+ fn $method(&self, other: &Ratio<T>) -> $res {
+ (self.numer * other.denom). $method (&(self.denom*other.numer))
+ }
+ )+
+ }
+ };
+}
+cmp_impl!(impl Eq, eq, ne)
+cmp_impl!(impl TotalEq, equals)
+cmp_impl!(impl Ord, lt, gt, le, ge)
+cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering)
+
+impl<T: Clone + Integer + Ord> Orderable for Ratio<T> {
+ #[inline]
+ fn min(&self, other: &Ratio<T>) -> Ratio<T> {
+ if *self < *other { self.clone() } else { other.clone() }
+ }
+
+ #[inline]
+ fn max(&self, other: &Ratio<T>) -> Ratio<T> {
+ if *self > *other { self.clone() } else { other.clone() }
+ }
+
+ #[inline]
+ fn clamp(&self, mn: &Ratio<T>, mx: &Ratio<T>) -> Ratio<T> {
+ if *self > *mx { mx.clone()} else
+ if *self < *mn { mn.clone() } else { self.clone() }
+ }
+}
+
+
+/* Arithmetic */
+// a/b * c/d = (a*c)/(b*d)
+impl<T: Clone + Integer + Ord>
+ Mul<Ratio<T>,Ratio<T>> for Ratio<T> {
+ #[inline]
+ fn mul(&self, rhs: &Ratio<T>) -> Ratio<T> {
+ Ratio::new(self.numer * rhs.numer, self.denom * rhs.denom)
+ }
+}
+
+// (a/b) / (c/d) = (a*d)/(b*c)
+impl<T: Clone + Integer + Ord>
+ Div<Ratio<T>,Ratio<T>> for Ratio<T> {
+ #[inline]
+ fn div(&self, rhs: &Ratio<T>) -> Ratio<T> {
+ Ratio::new(self.numer * rhs.denom, self.denom * rhs.numer)
+ }
+}
+
+// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
+macro_rules! arith_impl {
+ (impl $imp:ident, $method:ident) => {
+ impl<T: Clone + Integer + Ord>
+ $imp<Ratio<T>,Ratio<T>> for Ratio<T> {
+ #[inline]
+ fn $method(&self, rhs: &Ratio<T>) -> Ratio<T> {
+ Ratio::new((self.numer * rhs.denom).$method(&(self.denom * rhs.numer)),
+ self.denom * rhs.denom)
+ }
+ }
+ }
+}
+
+// a/b + c/d = (a*d + b*c)/(b*d
+arith_impl!(impl Add, add)
+
+// a/b - c/d = (a*d - b*c)/(b*d)
+arith_impl!(impl Sub, sub)
+
+// a/b % c/d = (a*d % b*c)/(b*d)
+arith_impl!(impl Rem, rem)
+
+impl<T: Clone + Integer + Ord>
+ Neg<Ratio<T>> for Ratio<T> {
+ #[inline]
+ fn neg(&self) -> Ratio<T> {
+ Ratio::new_raw(-self.numer, self.denom.clone())
+ }
+}
+
+/* Constants */
+impl<T: Clone + Integer + Ord>
+ Zero for Ratio<T> {
+ #[inline]
+ fn zero() -> Ratio<T> {
+ Ratio::new_raw(Zero::zero(), One::one())
+ }
+
+ #[inline]
+ fn is_zero(&self) -> bool {
+ *self == Zero::zero()
+ }
+}
+
+impl<T: Clone + Integer + Ord>
+ One for Ratio<T> {
+ #[inline]
+ fn one() -> Ratio<T> {
+ Ratio::new_raw(One::one(), One::one())
+ }
+}
+
+impl<T: Clone + Integer + Ord>
+ Num for Ratio<T> {}
+
+/* Utils */
+impl<T: Clone + Integer + Ord>
+ Round for Ratio<T> {
+
+ fn floor(&self) -> Ratio<T> {
+ if *self < Zero::zero() {
+ Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
+ } else {
+ Ratio::from_integer(self.numer / self.denom)
+ }
+ }
+
+ fn ceil(&self) -> Ratio<T> {
+ if *self < Zero::zero() {
+ Ratio::from_integer(self.numer / self.denom)
+ } else {
+ Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
+ }
+ }
+
+ #[inline]
+ fn round(&self) -> Ratio<T> {
+ if *self < Zero::zero() {
+ Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
+ } else {
+ Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
+ }
+ }
+
+ #[inline]
+ fn trunc(&self) -> Ratio<T> {
+ Ratio::from_integer(self.numer / self.denom)
+ }
+
+ fn fract(&self) -> Ratio<T> {
+ Ratio::new_raw(self.numer % self.denom, self.denom.clone())
+ }
+}
+
+/* String conversions */
+impl<T: ToStr> ToStr for Ratio<T> {
+ /// Renders as `numer/denom`.
+ fn to_str(&self) -> ~str {
+ format!("{}/{}", self.numer.to_str(), self.denom.to_str())
+ }
+}
+impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
+ /// Renders as `numer/denom` where the numbers are in base `radix`.
+ fn to_str_radix(&self, radix: uint) -> ~str {
+ format!("{}/{}", self.numer.to_str_radix(radix), self.denom.to_str_radix(radix))
+ }
+}
+
+impl<T: FromStr + Clone + Integer + Ord>
+ FromStr for Ratio<T> {
+ /// Parses `numer/denom`.
+ fn from_str(s: &str) -> Option<Ratio<T>> {
+ let split: ~[&str] = s.splitn('/', 1).collect();
+ if split.len() < 2 {
+ return None
+ }
+ let a_option: Option<T> = FromStr::from_str(split[0]);
+ a_option.and_then(|a| {
+ let b_option: Option<T> = FromStr::from_str(split[1]);
+ b_option.and_then(|b| {
+ Some(Ratio::new(a.clone(), b.clone()))
+ })
+ })
+ }
+}
+impl<T: FromStrRadix + Clone + Integer + Ord>
+ FromStrRadix for Ratio<T> {
+ /// Parses `numer/denom` where the numbers are in base `radix`.
+ fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
+ let split: ~[&str] = s.splitn('/', 1).collect();
+ if split.len() < 2 {
+ None
+ } else {
+ let a_option: Option<T> = FromStrRadix::from_str_radix(split[0],
+ radix);
+ a_option.and_then(|a| {
+ let b_option: Option<T> =
+ FromStrRadix::from_str_radix(split[1], radix);
+ b_option.and_then(|b| {
+ Some(Ratio::new(a.clone(), b.clone()))
+ })
+ })
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+
+ use super::{Ratio, Rational, BigRational};
+ use std::num::{Zero,One,FromStrRadix,FromPrimitive};
+ use std::from_str::FromStr;
+
+ pub static _0 : Rational = Ratio { numer: 0, denom: 1};
+ pub static _1 : Rational = Ratio { numer: 1, denom: 1};
+ pub static _2: Rational = Ratio { numer: 2, denom: 1};
+ pub static _1_2: Rational = Ratio { numer: 1, denom: 2};
+ pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
+ pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2};
+
+ pub fn to_big(n: Rational) -> BigRational {
+ Ratio::new(
+ FromPrimitive::from_int(n.numer).unwrap(),
+ FromPrimitive::from_int(n.denom).unwrap()
+ )
+ }
+
+ #[test]
+ fn test_test_constants() {
+ // check our constants are what Ratio::new etc. would make.
+ assert_eq!(_0, Zero::zero());
+ assert_eq!(_1, One::one());
+ assert_eq!(_2, Ratio::from_integer(2));
+ assert_eq!(_1_2, Ratio::new(1,2));
+ assert_eq!(_3_2, Ratio::new(3,2));
+ assert_eq!(_neg1_2, Ratio::new(-1,2));
+ }
+
+ #[test]
+ fn test_new_reduce() {
+ let one22 = Ratio::new(2i,2);
+
+ assert_eq!(one22, One::one());
+ }
+ #[test]
+ #[should_fail]
+ fn test_new_zero() {
+ let _a = Ratio::new(1,0);
+ }
+
+
+ #[test]
+ fn test_cmp() {
+ assert!(_0 == _0 && _1 == _1);
+ assert!(_0 != _1 && _1 != _0);
+ assert!(_0 < _1 && !(_1 < _0));
+ assert!(_1 > _0 && !(_0 > _1));
+
+ assert!(_0 <= _0 && _1 <= _1);
+ assert!(_0 <= _1 && !(_1 <= _0));
+
+ assert!(_0 >= _0 && _1 >= _1);
+ assert!(_1 >= _0 && !(_0 >= _1));
+ }
+
+
+ #[test]
+ fn test_to_integer() {
+ assert_eq!(_0.to_integer(), 0);
+ assert_eq!(_1.to_integer(), 1);
+ assert_eq!(_2.to_integer(), 2);
+ assert_eq!(_1_2.to_integer(), 0);
+ assert_eq!(_3_2.to_integer(), 1);
+ assert_eq!(_neg1_2.to_integer(), 0);
+ }
+
+
+ #[test]
+ fn test_numer() {
+ assert_eq!(_0.numer(), &0);
+ assert_eq!(_1.numer(), &1);
+ assert_eq!(_2.numer(), &2);
+ assert_eq!(_1_2.numer(), &1);
+ assert_eq!(_3_2.numer(), &3);
+ assert_eq!(_neg1_2.numer(), &(-1));
+ }
+ #[test]
+ fn test_denom() {
+ assert_eq!(_0.denom(), &1);
+ assert_eq!(_1.denom(), &1);
+ assert_eq!(_2.denom(), &1);
+ assert_eq!(_1_2.denom(), &2);
+ assert_eq!(_3_2.denom(), &2);
+ assert_eq!(_neg1_2.denom(), &2);
+ }
+
+
+ #[test]
+ fn test_is_integer() {
+ assert!(_0.is_integer());
+ assert!(_1.is_integer());
+ assert!(_2.is_integer());
+ assert!(!_1_2.is_integer());
+ assert!(!_3_2.is_integer());
+ assert!(!_neg1_2.is_integer());
+ }
+
+
+ mod arith {
+ use super::{_0, _1, _2, _1_2, _3_2, _neg1_2, to_big};
+ use super::super::{Ratio, Rational, BigRational};
+
+
+ #[test]
+ fn test_add() {
+ fn test(a: Rational, b: Rational, c: Rational) {
+ assert_eq!(a + b, c);
+ assert_eq!(to_big(a) + to_big(b), to_big(c));
+ }
+
+ test(_1, _1_2, _3_2);
+ test(_1, _1, _2);
+ test(_1_2, _3_2, _2);
+ test(_1_2, _neg1_2, _0);
+ }
+
+ #[test]
+ fn test_sub() {
+ fn test(a: Rational, b: Rational, c: Rational) {
+ assert_eq!(a - b, c);
+ assert_eq!(to_big(a) - to_big(b), to_big(c))
+ }
+
+ test(_1, _1_2, _1_2);
+ test(_3_2, _1_2, _1);
+ test(_1, _neg1_2, _3_2);
+ }
+
+ #[test]
+ fn test_mul() {
+ fn test(a: Rational, b: Rational, c: Rational) {
+ assert_eq!(a * b, c);
+ assert_eq!(to_big(a) * to_big(b), to_big(c))
+ }
+
+ test(_1, _1_2, _1_2);
+ test(_1_2, _3_2, Ratio::new(3,4));
+ test(_1_2, _neg1_2, Ratio::new(-1, 4));
+ }
+
+ #[test]
+ fn test_div() {
+ fn test(a: Rational, b: Rational, c: Rational) {
+ assert_eq!(a / b, c);
+ assert_eq!(to_big(a) / to_big(b), to_big(c))
+ }
+
+ test(_1, _1_2, _2);
+ test(_3_2, _1_2, _1 + _2);
+ test(_1, _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2);
+ }
+
+ #[test]
+ fn test_rem() {
+ fn test(a: Rational, b: Rational, c: Rational) {
+ assert_eq!(a % b, c);
+ assert_eq!(to_big(a) % to_big(b), to_big(c))
+ }
+
+ test(_3_2, _1, _1_2);
+ test(_2, _neg1_2, _0);
+ test(_1_2, _2, _1_2);
+ }
+
+ #[test]
+ fn test_neg() {
+ fn test(a: Rational, b: Rational) {
+ assert_eq!(-a, b);
+ assert_eq!(-to_big(a), to_big(b))
+ }
+
+ test(_0, _0);
+ test(_1_2, _neg1_2);
+ test(-_1, _1);
+ }
+ #[test]
+ fn test_zero() {
+ assert_eq!(_0 + _0, _0);
+ assert_eq!(_0 * _0, _0);
+ assert_eq!(_0 * _1, _0);
+ assert_eq!(_0 / _neg1_2, _0);
+ assert_eq!(_0 - _0, _0);
+ }
+ #[test]
+ #[should_fail]
+ fn test_div_0() {
+ let _a = _1 / _0;
+ }
+ }
+
+ #[test]
+ fn test_round() {
+ assert_eq!(_1_2.ceil(), _1);
+ assert_eq!(_1_2.floor(), _0);
+ assert_eq!(_1_2.round(), _1);
+ assert_eq!(_1_2.trunc(), _0);
+
+ assert_eq!(_neg1_2.ceil(), _0);
+ assert_eq!(_neg1_2.floor(), -_1);
+ assert_eq!(_neg1_2.round(), -_1);
+ assert_eq!(_neg1_2.trunc(), _0);
+
+ assert_eq!(_1.ceil(), _1);
+ assert_eq!(_1.floor(), _1);
+ assert_eq!(_1.round(), _1);
+ assert_eq!(_1.trunc(), _1);
+ }
+
+ #[test]
+ fn test_fract() {
+ assert_eq!(_1.fract(), _0);
+ assert_eq!(_neg1_2.fract(), _neg1_2);
+ assert_eq!(_1_2.fract(), _1_2);
+ assert_eq!(_3_2.fract(), _1_2);
+ }
+
+ #[test]
+ fn test_recip() {
+ assert_eq!(_1 * _1.recip(), _1);
+ assert_eq!(_2 * _2.recip(), _1);
+ assert_eq!(_1_2 * _1_2.recip(), _1);
+ assert_eq!(_3_2 * _3_2.recip(), _1);
+ assert_eq!(_neg1_2 * _neg1_2.recip(), _1);
+ }
+
+ #[test]
+ fn test_to_from_str() {
+ fn test(r: Rational, s: ~str) {
+ assert_eq!(FromStr::from_str(s), Some(r));
+ assert_eq!(r.to_str(), s);
+ }
+ test(_1, ~"1/1");
+ test(_0, ~"0/1");
+ test(_1_2, ~"1/2");
+ test(_3_2, ~"3/2");
+ test(_2, ~"2/1");
+ test(_neg1_2, ~"-1/2");
+ }
+ #[test]
+ fn test_from_str_fail() {
+ fn test(s: &str) {
+ let rational: Option<Rational> = FromStr::from_str(s);
+ assert_eq!(rational, None);
+ }
+
+ let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1"];
+ for &s in xs.iter() {
+ test(s);
+ }
+ }
+
+ #[test]
+ fn test_to_from_str_radix() {
+ fn test(r: Rational, s: ~str, n: uint) {
+ assert_eq!(FromStrRadix::from_str_radix(s, n), Some(r));
+ assert_eq!(r.to_str_radix(n), s);
+ }
+ fn test3(r: Rational, s: ~str) { test(r, s, 3) }
+ fn test16(r: Rational, s: ~str) { test(r, s, 16) }
+
+ test3(_1, ~"1/1");
+ test3(_0, ~"0/1");
+ test3(_1_2, ~"1/2");
+ test3(_3_2, ~"10/2");
+ test3(_2, ~"2/1");
+ test3(_neg1_2, ~"-1/2");
+ test3(_neg1_2 / _2, ~"-1/11");
+
+ test16(_1, ~"1/1");
+ test16(_0, ~"0/1");
+ test16(_1_2, ~"1/2");
+ test16(_3_2, ~"3/2");
+ test16(_2, ~"2/1");
+ test16(_neg1_2, ~"-1/2");
+ test16(_neg1_2 / _2, ~"-1/4");
+ test16(Ratio::new(13,15), ~"d/f");
+ test16(_1_2*_1_2*_1_2*_1_2, ~"1/10");
+ }
+
+ #[test]
+ fn test_from_str_radix_fail() {
+ fn test(s: &str) {
+ let radix: Option<Rational> = FromStrRadix::from_str_radix(s, 3);
+ assert_eq!(radix, None);
+ }
+
+ let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1", "3/2"];
+ for &s in xs.iter() {
+ test(s);
+ }
+ }
+
+ #[test]
+ fn test_from_float() {
+ fn test<T: Float>(given: T, (numer, denom): (&str, &str)) {
+ let ratio: BigRational = Ratio::from_float(given).unwrap();
+ assert_eq!(ratio, Ratio::new(
+ FromStr::from_str(numer).unwrap(),
+ FromStr::from_str(denom).unwrap()));
+ }
+
+ // f32
+ test(3.14159265359f32, ("13176795", "4194304"));
+ test(2f32.powf(&100.), ("1267650600228229401496703205376", "1"));
+ test(-2f32.powf(&100.), ("-1267650600228229401496703205376", "1"));
+ test(1.0 / 2f32.powf(&100.), ("1", "1267650600228229401496703205376"));
+ test(684729.48391f32, ("1369459", "2"));
+ test(-8573.5918555f32, ("-4389679", "512"));
+
+ // f64
+ test(3.14159265359f64, ("3537118876014453", "1125899906842624"));
+ test(2f64.powf(&100.), ("1267650600228229401496703205376", "1"));
+ test(-2f64.powf(&100.), ("-1267650600228229401496703205376", "1"));
+ test(684729.48391f64, ("367611342500051", "536870912"));
+ test(-8573.5918555, ("-4713381968463931", "549755813888"));
+ test(1.0 / 2f64.powf(&100.), ("1", "1267650600228229401496703205376"));
+ }
+
+ #[test]
+ fn test_from_float_fail() {
+ use std::{f32, f64};
+
+ assert_eq!(Ratio::from_float(f32::NAN), None);
+ assert_eq!(Ratio::from_float(f32::INFINITY), None);
+ assert_eq!(Ratio::from_float(f32::NEG_INFINITY), None);
+ assert_eq!(Ratio::from_float(f64::NAN), None);
+ assert_eq!(Ratio::from_float(f64::INFINITY), None);
+ assert_eq!(Ratio::from_float(f64::NEG_INFINITY), None);
+ }
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern mod extra;
+extern mod num;
use std::from_str::FromStr;
use std::num::One;
use std::num::Zero;
use std::num::FromPrimitive;
-use extra::bigint::BigInt;
+use num::bigint::BigInt;
struct Context {
numer: BigInt,