From 42a610d323f0aab71ad30df2f087a427d03fa7c6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 18 Dec 2017 17:35:41 -0800 Subject: [PATCH] Move num-traits to its own repo All the prior `num` history is kept, so old `num-traits` tags are still valid, but future development here will be just for `num-traits`. --- .travis.yml | 16 +- Cargo.toml | 75 +- README.md | 21 +- benches/bigint.rs | 294 --- benches/shootout-pidigits.rs | 131 - bigint/Cargo.toml | 39 - bigint/LICENSE-APACHE | 201 -- bigint/LICENSE-MIT | 25 - bigint/src/algorithms.rs | 658 ----- bigint/src/bigint.rs | 1767 ------------- bigint/src/biguint.rs | 2242 ----------------- bigint/src/lib.rs | 154 -- bigint/src/macros.rs | 316 --- bigint/src/monty.rs | 127 - bigint/src/tests/bigint.rs | 1194 --------- bigint/src/tests/biguint.rs | 1760 ------------- ci/.gitignore | 1 - ci/deploy.enc | Bin 1680 -> 0 bytes ci/deploy.sh | 12 - ci/rustup.sh | 10 +- ci/test_full.sh | 49 +- complex/Cargo.toml | 30 - complex/LICENSE-APACHE | 201 -- complex/LICENSE-MIT | 25 - complex/src/lib.rs | 1899 -------------- derive/Cargo.toml | 27 - derive/LICENSE-APACHE | 201 -- derive/LICENSE-MIT | 25 - derive/src/lib.rs | 118 - .../from-primitive/derive_on_struct.rs | 22 - .../enum_with_associated_data.rs | 21 - .../to-primitive/derive_on_struct.rs | 22 - .../to-primitive/enum_with_associated_data.rs | 21 - derive/tests/compiletest.rs | 25 - derive/tests/empty_enum.rs | 23 - derive/tests/trivial.rs | 52 - derive/tests/with_custom_values.rs | 31 - doc/favicon.ico | Bin 23229 -> 0 bytes doc/index.html | 1 - doc/rust-logo-128x128-blk-v2.png | Bin 5758 -> 0 bytes integer/Cargo.toml | 15 - integer/LICENSE-APACHE | 201 -- integer/LICENSE-MIT | 25 - integer/src/lib.rs | 988 -------- iter/Cargo.toml | 23 - iter/LICENSE-APACHE | 201 -- iter/LICENSE-MIT | 25 - iter/src/lib.rs | 378 --- rational/Cargo.toml | 38 - rational/LICENSE-APACHE | 201 -- rational/LICENSE-MIT | 25 - rational/src/lib.rs | 1413 ----------- {traits/src => src}/bounds.rs | 0 {traits/src => src}/cast.rs | 0 {traits/src => src}/float.rs | 0 {traits/src => src}/identities.rs | 0 {traits/src => src}/int.rs | 0 src/lib.rs | 500 +++- {traits/src => src}/ops/checked.rs | 0 {traits/src => src}/ops/mod.rs | 0 {traits/src => src}/ops/saturating.rs | 0 {traits/src => src}/ops/wrapping.rs | 0 {traits/src => src}/pow.rs | 0 {traits/src => src}/sign.rs | 0 traits/Cargo.toml | 13 - traits/LICENSE-APACHE | 201 -- traits/LICENSE-MIT | 25 - traits/src/lib.rs | 437 ---- 68 files changed, 437 insertions(+), 16108 deletions(-) delete mode 100644 benches/bigint.rs delete mode 100644 benches/shootout-pidigits.rs delete mode 100644 bigint/Cargo.toml delete mode 100644 bigint/LICENSE-APACHE delete mode 100644 bigint/LICENSE-MIT delete mode 100644 bigint/src/algorithms.rs delete mode 100644 bigint/src/bigint.rs delete mode 100644 bigint/src/biguint.rs delete mode 100644 bigint/src/lib.rs delete mode 100644 bigint/src/macros.rs delete mode 100644 bigint/src/monty.rs delete mode 100644 bigint/src/tests/bigint.rs delete mode 100644 bigint/src/tests/biguint.rs delete mode 100644 ci/.gitignore delete mode 100644 ci/deploy.enc delete mode 100755 ci/deploy.sh delete mode 100644 complex/Cargo.toml delete mode 100644 complex/LICENSE-APACHE delete mode 100644 complex/LICENSE-MIT delete mode 100644 complex/src/lib.rs delete mode 100644 derive/Cargo.toml delete mode 100644 derive/LICENSE-APACHE delete mode 100644 derive/LICENSE-MIT delete mode 100644 derive/src/lib.rs delete mode 100644 derive/tests/compile-fail/from-primitive/derive_on_struct.rs delete mode 100644 derive/tests/compile-fail/from-primitive/enum_with_associated_data.rs delete mode 100644 derive/tests/compile-fail/to-primitive/derive_on_struct.rs delete mode 100644 derive/tests/compile-fail/to-primitive/enum_with_associated_data.rs delete mode 100644 derive/tests/compiletest.rs delete mode 100644 derive/tests/empty_enum.rs delete mode 100644 derive/tests/trivial.rs delete mode 100644 derive/tests/with_custom_values.rs delete mode 100644 doc/favicon.ico delete mode 100644 doc/index.html delete mode 100644 doc/rust-logo-128x128-blk-v2.png delete mode 100644 integer/Cargo.toml delete mode 100644 integer/LICENSE-APACHE delete mode 100644 integer/LICENSE-MIT delete mode 100644 integer/src/lib.rs delete mode 100644 iter/Cargo.toml delete mode 100644 iter/LICENSE-APACHE delete mode 100644 iter/LICENSE-MIT delete mode 100644 iter/src/lib.rs delete mode 100644 rational/Cargo.toml delete mode 100644 rational/LICENSE-APACHE delete mode 100644 rational/LICENSE-MIT delete mode 100644 rational/src/lib.rs rename {traits/src => src}/bounds.rs (100%) rename {traits/src => src}/cast.rs (100%) rename {traits/src => src}/float.rs (100%) rename {traits/src => src}/identities.rs (100%) rename {traits/src => src}/int.rs (100%) rename {traits/src => src}/ops/checked.rs (100%) rename {traits/src => src}/ops/mod.rs (100%) rename {traits/src => src}/ops/saturating.rs (100%) rename {traits/src => src}/ops/wrapping.rs (100%) rename {traits/src => src}/pow.rs (100%) rename {traits/src => src}/sign.rs (100%) delete mode 100644 traits/Cargo.toml delete mode 100644 traits/LICENSE-APACHE delete mode 100644 traits/LICENSE-MIT delete mode 100644 traits/src/lib.rs diff --git a/.travis.yml b/.travis.yml index c8195a7..c8cda1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,13 @@ language: rust rust: - - 1.15.0 + - 1.8.0 + - stable - beta - nightly -matrix: - include: - - rust: 1.8.0 - before_script: - # libc 0.2.34 started using #[deprecated] - - cargo generate-lockfile - - cargo update --package libc --precise 0.2.33 sudo: false script: - cargo build --verbose - ./ci/test_full.sh - - cargo doc -after_success: | - [ $TRAVIS_BRANCH = master ] && - [ $TRAVIS_PULL_REQUEST = false ] && - [ $TRAVIS_RUST_VERSION = nightly ] && - ssh-agent ./ci/deploy.sh notifications: email: on_success: never diff --git a/Cargo.toml b/Cargo.toml index 2f16403..c388e9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,73 +1,14 @@ [package] authors = ["The Rust Project Developers"] -description = "A collection of numeric types and traits for Rust, including bigint,\ncomplex, rational, range iterators, generic integers, and more!\n" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics", "bignum"] -categories = [ "algorithms", "data-structures", "science" ] +description = "Numeric traits for generic mathematics" +documentation = "https://docs.rs/num-traits" +homepage = "https://github.com/rust-num/num-traits" +keywords = ["mathematics", "numerics"] +categories = [ "algorithms", "science" ] license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num" -name = "num" +repository = "https://github.com/rust-num/num-traits" +name = "num-traits" version = "0.1.41" - -[badges] -travis-ci = { repository = "rust-num/num" } - -[[bench]] -name = "bigint" - -[[bench]] -harness = false -name = "shootout-pidigits" +readme = "README.md" [dependencies] - -[dependencies.num-bigint] -optional = true -path = "bigint" -version = "0.1.41" - -[dependencies.num-complex] -optional = true -path = "complex" -version = "0.1.41" - -[dependencies.num-integer] -path = "./integer" -version = "0.1.35" - -[dependencies.num-iter] -optional = false -path = "iter" -version = "0.1.34" - -[dependencies.num-rational] -optional = true -path = "rational" -version = "0.1.40" - -[dependencies.num-traits] -path = "./traits" -version = "0.1.41" - -[dev-dependencies] - -[dev-dependencies.rand] -version = "0.3.8" - -[features] -bigint = ["num-bigint"] -complex = ["num-complex"] -rational = ["num-rational"] -default = ["bigint", "complex", "rational", "rustc-serialize"] - -serde = [ - "num-bigint/serde", - "num-complex/serde", - "num-rational/serde" -] -rustc-serialize = [ - "num-bigint/rustc-serialize", - "num-complex/rustc-serialize", - "num-rational/rustc-serialize" -] diff --git a/README.md b/README.md index 4e739b1..a4af231 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,10 @@ -# num +# num-traits -[![](https://travis-ci.org/rust-num/num.svg)](https://travis-ci.org/rust-num/num) +[![crate](https://img.shields.io/crates/v/num-traits.svg)](https://crates.io/crates/num-traits) +[![documentation](https://docs.rs/num-traits/badge.svg)](https://docs.rs/num-traits) +[![Travis status](https://travis-ci.org/rust-num/num-traits.svg?branch=master)](https://travis-ci.org/rust-num/num-traits) -A collection of numeric types and traits for Rust. - -This includes new types for big integers, rationals, and complex numbers, -new traits for generic programming on numeric properties like `Integer`, -and generic range iterators. - -[Documentation](http://rust-num.github.io/num) +Numeric traits for generic mathematics in Rust. ## Usage @@ -16,16 +12,15 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -num = "0.1" +num-traits = "0.1" ``` and this to your crate root: ```rust -extern crate num; +extern crate num_traits; ``` ## Compatibility -Most of the `num` crates are tested for rustc 1.8 and greater. -The exception is `num-derive` which requires at least rustc 1.15. +The `num-traits` crate is tested for rustc 1.8 and greater. diff --git a/benches/bigint.rs b/benches/bigint.rs deleted file mode 100644 index 23932e6..0000000 --- a/benches/bigint.rs +++ /dev/null @@ -1,294 +0,0 @@ -#![feature(test)] - -extern crate test; -extern crate num; -extern crate rand; - -use std::mem::replace; -use test::Bencher; -use num::{BigInt, BigUint, Zero, One, FromPrimitive, Num}; -use num::bigint::RandBigInt; -use rand::{SeedableRng, StdRng}; - -fn get_rng() -> StdRng { - let seed: &[_] = &[1, 2, 3, 4]; - SeedableRng::from_seed(seed) -} - -fn multiply_bench(b: &mut Bencher, xbits: usize, ybits: usize) { - let mut rng = get_rng(); - let x = rng.gen_bigint(xbits); - let y = rng.gen_bigint(ybits); - - b.iter(|| &x * &y); -} - -fn divide_bench(b: &mut Bencher, xbits: usize, ybits: usize) { - let mut rng = get_rng(); - let x = rng.gen_bigint(xbits); - let y = rng.gen_bigint(ybits); - - b.iter(|| &x / &y); -} - -fn factorial(n: usize) -> BigUint { - let mut f: BigUint = One::one(); - for i in 1..(n+1) { - let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); - f = f * bu; - } - f -} - -/// Compute Fibonacci numbers -fn fib(n: usize) -> BigUint { - let mut f0: BigUint = Zero::zero(); - let mut f1: BigUint = One::one(); - for _ in 0..n { - let f2 = f0 + &f1; - f0 = replace(&mut f1, f2); - } - f0 -} - -/// Compute Fibonacci numbers with two ops per iteration -/// (add and subtract, like issue #200) -fn fib2(n: usize) -> BigUint { - let mut f0: BigUint = Zero::zero(); - let mut f1: BigUint = One::one(); - for _ in 0..n { - f1 = f1 + &f0; - f0 = &f1 - f0; - } - f0 -} - -#[bench] -fn multiply_0(b: &mut Bencher) { - multiply_bench(b, 1 << 8, 1 << 8); -} - -#[bench] -fn multiply_1(b: &mut Bencher) { - multiply_bench(b, 1 << 8, 1 << 16); -} - -#[bench] -fn multiply_2(b: &mut Bencher) { - multiply_bench(b, 1 << 16, 1 << 16); -} - -#[bench] -fn multiply_3(b: &mut Bencher) { - multiply_bench(b, 1 << 16, 1 << 17); -} - -#[bench] -fn divide_0(b: &mut Bencher) { - divide_bench(b, 1 << 8, 1 << 6); -} - -#[bench] -fn divide_1(b: &mut Bencher) { - divide_bench(b, 1 << 12, 1 << 8); -} - -#[bench] -fn divide_2(b: &mut Bencher) { - divide_bench(b, 1 << 16, 1 << 12); -} - -#[bench] -fn factorial_100(b: &mut Bencher) { - b.iter(|| factorial(100)); -} - -#[bench] -fn fib_100(b: &mut Bencher) { - b.iter(|| fib(100)); -} - -#[bench] -fn fib_1000(b: &mut Bencher) { - b.iter(|| fib(1000)); -} - -#[bench] -fn fib_10000(b: &mut Bencher) { - b.iter(|| fib(10000)); -} - -#[bench] -fn fib2_100(b: &mut Bencher) { - b.iter(|| fib2(100)); -} - -#[bench] -fn fib2_1000(b: &mut Bencher) { - b.iter(|| fib2(1000)); -} - -#[bench] -fn fib2_10000(b: &mut Bencher) { - b.iter(|| fib2(10000)); -} - -#[bench] -fn fac_to_string(b: &mut Bencher) { - let fac = factorial(100); - b.iter(|| fac.to_string()); -} - -#[bench] -fn fib_to_string(b: &mut Bencher) { - let fib = fib(100); - b.iter(|| fib.to_string()); -} - -fn to_str_radix_bench(b: &mut Bencher, radix: u32) { - let mut rng = get_rng(); - let x = rng.gen_bigint(1009); - b.iter(|| x.to_str_radix(radix)); -} - -#[bench] -fn to_str_radix_02(b: &mut Bencher) { - to_str_radix_bench(b, 2); -} - -#[bench] -fn to_str_radix_08(b: &mut Bencher) { - to_str_radix_bench(b, 8); -} - -#[bench] -fn to_str_radix_10(b: &mut Bencher) { - to_str_radix_bench(b, 10); -} - -#[bench] -fn to_str_radix_16(b: &mut Bencher) { - to_str_radix_bench(b, 16); -} - -#[bench] -fn to_str_radix_36(b: &mut Bencher) { - to_str_radix_bench(b, 36); -} - -fn from_str_radix_bench(b: &mut Bencher, radix: u32) { - use num::Num; - let mut rng = get_rng(); - let x = rng.gen_bigint(1009); - let s = x.to_str_radix(radix); - assert_eq!(x, BigInt::from_str_radix(&s, radix).unwrap()); - b.iter(|| BigInt::from_str_radix(&s, radix)); -} - -#[bench] -fn from_str_radix_02(b: &mut Bencher) { - from_str_radix_bench(b, 2); -} - -#[bench] -fn from_str_radix_08(b: &mut Bencher) { - from_str_radix_bench(b, 8); -} - -#[bench] -fn from_str_radix_10(b: &mut Bencher) { - from_str_radix_bench(b, 10); -} - -#[bench] -fn from_str_radix_16(b: &mut Bencher) { - from_str_radix_bench(b, 16); -} - -#[bench] -fn from_str_radix_36(b: &mut Bencher) { - from_str_radix_bench(b, 36); -} - -#[bench] -fn shl(b: &mut Bencher) { - let n = BigUint::one() << 1000; - b.iter(|| { - let mut m = n.clone(); - for i in 0..50 { - m = m << i; - } - }) -} - -#[bench] -fn shr(b: &mut Bencher) { - let n = BigUint::one() << 2000; - b.iter(|| { - let mut m = n.clone(); - for i in 0..50 { - m = m >> i; - } - }) -} - -#[bench] -fn hash(b: &mut Bencher) { - use std::collections::HashSet; - let mut rng = get_rng(); - let v: Vec = (1000..2000).map(|bits| rng.gen_bigint(bits)).collect(); - b.iter(|| { - let h: HashSet<&BigInt> = v.iter().collect(); - assert_eq!(h.len(), v.len()); - }); -} - -#[bench] -fn pow_bench(b: &mut Bencher) { - b.iter(|| { - let upper = 100_usize; - for i in 2..upper + 1 { - for j in 2..upper + 1 { - let i_big = BigUint::from_usize(i).unwrap(); - num::pow(i_big, j); - } - } - }); -} - - -/// This modulus is the prime from the 2048-bit MODP DH group: -/// https://tools.ietf.org/html/rfc3526#section-3 -const RFC3526_2048BIT_MODP_GROUP: &'static str = "\ - FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ - 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ - EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ - E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ - EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ - C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ - 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ - 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ - E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ - DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ - 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF"; - -#[bench] -fn modpow(b: &mut Bencher) { - let mut rng = get_rng(); - let base = rng.gen_biguint(2048); - let e = rng.gen_biguint(2048); - let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap(); - - b.iter(|| base.modpow(&e, &m)); -} - -#[bench] -fn modpow_even(b: &mut Bencher) { - let mut rng = get_rng(); - let base = rng.gen_biguint(2048); - let e = rng.gen_biguint(2048); - // Make the modulus even, so monty (base-2^32) doesn't apply. - let m = BigUint::from_str_radix(RFC3526_2048BIT_MODP_GROUP, 16).unwrap() - 1u32; - - b.iter(|| base.modpow(&e, &m)); -} diff --git a/benches/shootout-pidigits.rs b/benches/shootout-pidigits.rs deleted file mode 100644 index 2cdcbda..0000000 --- a/benches/shootout-pidigits.rs +++ /dev/null @@ -1,131 +0,0 @@ -// The Computer Language Benchmarks Game -// http://benchmarksgame.alioth.debian.org/ -// -// contributed by the Rust Project Developers - -// Copyright (c) 2013-2014 The Rust Project Developers -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// - Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// -// - Neither the name of "The Computer Language Benchmarks Game" nor -// the name of "The Computer Language Shootout Benchmarks" nor the -// names of its contributors may be used to endorse or promote -// products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -extern crate num; - -use std::str::FromStr; -use std::io; - -use num::traits::{FromPrimitive, ToPrimitive}; -use num::{BigInt, Integer, One, Zero}; - -struct Context { - numer: BigInt, - accum: BigInt, - denom: BigInt, -} - -impl Context { - fn new() -> Context { - Context { - numer: One::one(), - accum: Zero::zero(), - denom: One::one(), - } - } - - fn from_i32(i: i32) -> BigInt { - FromPrimitive::from_i32(i).unwrap() - } - - fn extract_digit(&self) -> i32 { - if self.numer > self.accum {return -1;} - let (q, r) = - (&self.numer * Context::from_i32(3) + &self.accum) - .div_rem(&self.denom); - if r + &self.numer >= self.denom {return -1;} - q.to_i32().unwrap() - } - - fn next_term(&mut self, k: i32) { - let y2 = Context::from_i32(k * 2 + 1); - self.accum = (&self.accum + (&self.numer << 1)) * &y2; - self.numer = &self.numer * Context::from_i32(k); - self.denom = &self.denom * y2; - } - - fn eliminate_digit(&mut self, d: i32) { - let d = Context::from_i32(d); - let ten = Context::from_i32(10); - self.accum = (&self.accum - &self.denom * d) * &ten; - self.numer = &self.numer * ten; - } -} - -fn pidigits(n: isize, out: &mut io::Write) -> io::Result<()> { - let mut k = 0; - let mut context = Context::new(); - - for i in 1..(n+1) { - let mut d; - loop { - k += 1; - context.next_term(k); - d = context.extract_digit(); - if d != -1 {break;} - } - - try!(write!(out, "{}", d)); - if i % 10 == 0 { try!(write!(out, "\t:{}\n", i)); } - - context.eliminate_digit(d); - } - - let m = n % 10; - if m != 0 { - for _ in m..10 { try!(write!(out, " ")); } - try!(write!(out, "\t:{}\n", n)); - } - Ok(()) -} - -const DEFAULT_DIGITS: isize = 512; - -fn main() { - let args = std::env::args().collect::>(); - let n = if args.len() < 2 { - DEFAULT_DIGITS - } else if args[1] == "--bench" { - return pidigits(DEFAULT_DIGITS, &mut std::io::sink()).unwrap() - } else { - FromStr::from_str(&args[1]).unwrap() - }; - pidigits(n, &mut std::io::stdout()).unwrap(); -} diff --git a/bigint/Cargo.toml b/bigint/Cargo.toml deleted file mode 100644 index e07e38f..0000000 --- a/bigint/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -description = "Big integer implementation for Rust" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics", "bignum"] -categories = [ "algorithms", "data-structures", "science" ] -license = "MIT/Apache-2.0" -name = "num-bigint" -repository = "https://github.com/rust-num/num" -version = "0.1.41" - -[dependencies] - -[dependencies.num-integer] -path = "../integer" -version = "0.1.32" - -[dependencies.num-traits] -path = "../traits" -version = "0.1.32" - -[dependencies.rand] -optional = true -version = "0.3.14" - -[dependencies.rustc-serialize] -optional = true -version = "0.3.19" - -[dependencies.serde] -optional = true -version = ">= 0.7.0, < 0.9.0" - -[dev-dependencies.rand] -version = "0.3.14" - -[features] -default = ["rand", "rustc-serialize"] diff --git a/bigint/LICENSE-APACHE b/bigint/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/bigint/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/bigint/LICENSE-MIT b/bigint/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/bigint/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/bigint/src/algorithms.rs b/bigint/src/algorithms.rs deleted file mode 100644 index 5b74539..0000000 --- a/bigint/src/algorithms.rs +++ /dev/null @@ -1,658 +0,0 @@ -use std::borrow::Cow; -use std::cmp; -use std::cmp::Ordering::{self, Less, Greater, Equal}; -use std::iter::repeat; -use std::mem; -use traits; -use traits::{Zero, One}; - -use biguint::BigUint; - -use bigint::BigInt; -use bigint::Sign; -use bigint::Sign::{Minus, NoSign, Plus}; - -#[allow(non_snake_case)] -pub mod big_digit { - /// A `BigDigit` is a `BigUint`'s composing element. - pub type BigDigit = u32; - - /// A `DoubleBigDigit` is the internal type used to do the computations. Its - /// size is the double of the size of `BigDigit`. - pub type DoubleBigDigit = u64; - - pub const ZERO_BIG_DIGIT: BigDigit = 0; - - // `DoubleBigDigit` size dependent - pub const BITS: usize = 32; - - pub const BASE: DoubleBigDigit = 1 << BITS; - const LO_MASK: DoubleBigDigit = (-1i32 as DoubleBigDigit) >> BITS; - - #[inline] - fn get_hi(n: DoubleBigDigit) -> BigDigit { - (n >> BITS) as BigDigit - } - #[inline] - fn get_lo(n: DoubleBigDigit) -> BigDigit { - (n & LO_MASK) as BigDigit - } - - /// Split one `DoubleBigDigit` into two `BigDigit`s. - #[inline] - pub fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) { - (get_hi(n), get_lo(n)) - } - - /// Join two `BigDigit`s into one `DoubleBigDigit` - #[inline] - pub fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit { - (lo as DoubleBigDigit) | ((hi as DoubleBigDigit) << BITS) - } -} - -use big_digit::{BigDigit, DoubleBigDigit}; - -// Generic functions for add/subtract/multiply with carry/borrow: - -// Add with carry: -#[inline] -fn adc(a: BigDigit, b: BigDigit, carry: &mut BigDigit) -> BigDigit { - let (hi, lo) = big_digit::from_doublebigdigit((a as DoubleBigDigit) + (b as DoubleBigDigit) + - (*carry as DoubleBigDigit)); - - *carry = hi; - lo -} - -// Subtract with borrow: -#[inline] -fn sbb(a: BigDigit, b: BigDigit, borrow: &mut BigDigit) -> BigDigit { - let (hi, lo) = big_digit::from_doublebigdigit(big_digit::BASE + (a as DoubleBigDigit) - - (b as DoubleBigDigit) - - (*borrow as DoubleBigDigit)); - // hi * (base) + lo == 1*(base) + ai - bi - borrow - // => ai - bi - borrow < 0 <=> hi == 0 - *borrow = (hi == 0) as BigDigit; - lo -} - -#[inline] -pub fn mac_with_carry(a: BigDigit, b: BigDigit, c: BigDigit, carry: &mut BigDigit) -> BigDigit { - let (hi, lo) = big_digit::from_doublebigdigit((a as DoubleBigDigit) + - (b as DoubleBigDigit) * (c as DoubleBigDigit) + - (*carry as DoubleBigDigit)); - *carry = hi; - lo -} - -#[inline] -pub fn mul_with_carry(a: BigDigit, b: BigDigit, carry: &mut BigDigit) -> BigDigit { - let (hi, lo) = big_digit::from_doublebigdigit((a as DoubleBigDigit) * (b as DoubleBigDigit) + - (*carry as DoubleBigDigit)); - - *carry = hi; - lo -} - -/// Divide a two digit numerator by a one digit divisor, returns quotient and remainder: -/// -/// Note: the caller must ensure that both the quotient and remainder will fit into a single digit. -/// This is _not_ true for an arbitrary numerator/denominator. -/// -/// (This function also matches what the x86 divide instruction does). -#[inline] -fn div_wide(hi: BigDigit, lo: BigDigit, divisor: BigDigit) -> (BigDigit, BigDigit) { - debug_assert!(hi < divisor); - - let lhs = big_digit::to_doublebigdigit(hi, lo); - let rhs = divisor as DoubleBigDigit; - ((lhs / rhs) as BigDigit, (lhs % rhs) as BigDigit) -} - -pub fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) { - let mut rem = 0; - - for d in a.data.iter_mut().rev() { - let (q, r) = div_wide(rem, *d, b); - *d = q; - rem = r; - } - - (a.normalized(), rem) -} - -// Only for the Add impl: -#[inline] -pub fn __add2(a: &mut [BigDigit], b: &[BigDigit]) -> BigDigit { - debug_assert!(a.len() >= b.len()); - - let mut carry = 0; - let (a_lo, a_hi) = a.split_at_mut(b.len()); - - for (a, b) in a_lo.iter_mut().zip(b) { - *a = adc(*a, *b, &mut carry); - } - - if carry != 0 { - for a in a_hi { - *a = adc(*a, 0, &mut carry); - if carry == 0 { break } - } - } - - carry -} - -/// /Two argument addition of raw slices: -/// a += b -/// -/// The caller _must_ ensure that a is big enough to store the result - typically this means -/// resizing a to max(a.len(), b.len()) + 1, to fit a possible carry. -pub fn add2(a: &mut [BigDigit], b: &[BigDigit]) { - let carry = __add2(a, b); - - debug_assert!(carry == 0); -} - -pub fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { - let mut borrow = 0; - - let len = cmp::min(a.len(), b.len()); - let (a_lo, a_hi) = a.split_at_mut(len); - let (b_lo, b_hi) = b.split_at(len); - - for (a, b) in a_lo.iter_mut().zip(b_lo) { - *a = sbb(*a, *b, &mut borrow); - } - - if borrow != 0 { - for a in a_hi { - *a = sbb(*a, 0, &mut borrow); - if borrow == 0 { break } - } - } - - // note: we're _required_ to fail on underflow - assert!(borrow == 0 && b_hi.iter().all(|x| *x == 0), - "Cannot subtract b from a because b is larger than a."); -} - -pub fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { - debug_assert!(b.len() >= a.len()); - - let mut borrow = 0; - - let len = cmp::min(a.len(), b.len()); - let (a_lo, a_hi) = a.split_at(len); - let (b_lo, b_hi) = b.split_at_mut(len); - - for (a, b) in a_lo.iter().zip(b_lo) { - *b = sbb(*a, *b, &mut borrow); - } - - assert!(a_hi.is_empty()); - - // note: we're _required_ to fail on underflow - assert!(borrow == 0 && b_hi.iter().all(|x| *x == 0), - "Cannot subtract b from a because b is larger than a."); -} - -pub fn sub_sign(a: &[BigDigit], b: &[BigDigit]) -> (Sign, BigUint) { - // Normalize: - let a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; - let b = &b[..b.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; - - match cmp_slice(a, b) { - Greater => { - let mut a = a.to_vec(); - sub2(&mut a, b); - (Plus, BigUint::new(a)) - } - Less => { - let mut b = b.to_vec(); - sub2(&mut b, a); - (Minus, BigUint::new(b)) - } - _ => (NoSign, Zero::zero()), - } -} - -/// Three argument multiply accumulate: -/// acc += b * c -pub fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { - if c == 0 { - return; - } - - let mut carry = 0; - let (a_lo, a_hi) = acc.split_at_mut(b.len()); - - for (a, &b) in a_lo.iter_mut().zip(b) { - *a = mac_with_carry(*a, b, c, &mut carry); - } - - let mut a = a_hi.iter_mut(); - while carry != 0 { - let a = a.next().expect("carry overflow during multiplication!"); - *a = adc(*a, 0, &mut carry); - } -} - -/// Three argument multiply accumulate: -/// acc += b * c -fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) { - let (x, y) = if b.len() < c.len() { - (b, c) - } else { - (c, b) - }; - - // We use three algorithms for different input sizes. - // - // - For small inputs, long multiplication is fastest. - // - Next we use Karatsuba multiplication (Toom-2), which we have optimized - // to avoid unnecessary allocations for intermediate values. - // - For the largest inputs we use Toom-3, which better optimizes the - // number of operations, but uses more temporary allocations. - // - // The thresholds are somewhat arbitrary, chosen by evaluating the results - // of `cargo bench --bench bigint multiply`. - - if x.len() <= 32 { - // Long multiplication: - for (i, xi) in x.iter().enumerate() { - mac_digit(&mut acc[i..], y, *xi); - } - } else if x.len() <= 256 { - /* - * Karatsuba multiplication: - * - * The idea is that we break x and y up into two smaller numbers that each have about half - * as many digits, like so (note that multiplying by b is just a shift): - * - * x = x0 + x1 * b - * y = y0 + y1 * b - * - * With some algebra, we can compute x * y with three smaller products, where the inputs to - * each of the smaller products have only about half as many digits as x and y: - * - * x * y = (x0 + x1 * b) * (y0 + y1 * b) - * - * x * y = x0 * y0 - * + x0 * y1 * b - * + x1 * y0 * b - * + x1 * y1 * b^2 - * - * Let p0 = x0 * y0 and p2 = x1 * y1: - * - * x * y = p0 - * + (x0 * y1 + x1 * y0) * b - * + p2 * b^2 - * - * The real trick is that middle term: - * - * x0 * y1 + x1 * y0 - * - * = x0 * y1 + x1 * y0 - p0 + p0 - p2 + p2 - * - * = x0 * y1 + x1 * y0 - x0 * y0 - x1 * y1 + p0 + p2 - * - * Now we complete the square: - * - * = -(x0 * y0 - x0 * y1 - x1 * y0 + x1 * y1) + p0 + p2 - * - * = -((x1 - x0) * (y1 - y0)) + p0 + p2 - * - * Let p1 = (x1 - x0) * (y1 - y0), and substitute back into our original formula: - * - * x * y = p0 - * + (p0 + p2 - p1) * b - * + p2 * b^2 - * - * Where the three intermediate products are: - * - * p0 = x0 * y0 - * p1 = (x1 - x0) * (y1 - y0) - * p2 = x1 * y1 - * - * In doing the computation, we take great care to avoid unnecessary temporary variables - * (since creating a BigUint requires a heap allocation): thus, we rearrange the formula a - * bit so we can use the same temporary variable for all the intermediate products: - * - * x * y = p2 * b^2 + p2 * b - * + p0 * b + p0 - * - p1 * b - * - * The other trick we use is instead of doing explicit shifts, we slice acc at the - * appropriate offset when doing the add. - */ - - /* - * When x is smaller than y, it's significantly faster to pick b such that x is split in - * half, not y: - */ - let b = x.len() / 2; - let (x0, x1) = x.split_at(b); - let (y0, y1) = y.split_at(b); - - /* - * We reuse the same BigUint for all the intermediate multiplies and have to size p - * appropriately here: x1.len() >= x0.len and y1.len() >= y0.len(): - */ - let len = x1.len() + y1.len() + 1; - let mut p = BigUint { data: vec![0; len] }; - - // p2 = x1 * y1 - mac3(&mut p.data[..], x1, y1); - - // Not required, but the adds go faster if we drop any unneeded 0s from the end: - p.normalize(); - - add2(&mut acc[b..], &p.data[..]); - add2(&mut acc[b * 2..], &p.data[..]); - - // Zero out p before the next multiply: - p.data.truncate(0); - p.data.extend(repeat(0).take(len)); - - // p0 = x0 * y0 - mac3(&mut p.data[..], x0, y0); - p.normalize(); - - add2(&mut acc[..], &p.data[..]); - add2(&mut acc[b..], &p.data[..]); - - // p1 = (x1 - x0) * (y1 - y0) - // We do this one last, since it may be negative and acc can't ever be negative: - let (j0_sign, j0) = sub_sign(x1, x0); - let (j1_sign, j1) = sub_sign(y1, y0); - - match j0_sign * j1_sign { - Plus => { - p.data.truncate(0); - p.data.extend(repeat(0).take(len)); - - mac3(&mut p.data[..], &j0.data[..], &j1.data[..]); - p.normalize(); - - sub2(&mut acc[b..], &p.data[..]); - }, - Minus => { - mac3(&mut acc[b..], &j0.data[..], &j1.data[..]); - }, - NoSign => (), - } - - } else { - // Toom-3 multiplication: - // - // Toom-3 is like Karatsuba above, but dividing the inputs into three parts. - // Both are instances of Toom-Cook, using `k=3` and `k=2` respectively. - // - // FIXME: It would be nice to have comments breaking down the operations below. - - let i = y.len()/3 + 1; - - let x0_len = cmp::min(x.len(), i); - let x1_len = cmp::min(x.len() - x0_len, i); - - let y0_len = i; - let y1_len = cmp::min(y.len() - y0_len, i); - - let x0 = BigInt::from_slice(Plus, &x[..x0_len]); - let x1 = BigInt::from_slice(Plus, &x[x0_len..x0_len + x1_len]); - let x2 = BigInt::from_slice(Plus, &x[x0_len + x1_len..]); - - let y0 = BigInt::from_slice(Plus, &y[..y0_len]); - let y1 = BigInt::from_slice(Plus, &y[y0_len..y0_len + y1_len]); - let y2 = BigInt::from_slice(Plus, &y[y0_len + y1_len..]); - - let p = &x0 + &x2; - let q = &y0 + &y2; - - let p2 = &p - &x1; - let q2 = &q - &y1; - - let r0 = &x0 * &y0; - let r4 = &x2 * &y2; - let r1 = (p + x1) * (q + y1); - let r2 = &p2 * &q2; - let r3 = ((p2 + x2)*2 - x0) * ((q2 + y2)*2 - y0); - - let mut comp3: BigInt = (r3 - &r1) / 3; - let mut comp1: BigInt = (r1 - &r2) / 2; - let mut comp2: BigInt = r2 - &r0; - comp3 = (&comp2 - comp3)/2 + &r4*2; - comp2 = comp2 + &comp1 - &r4; - comp1 = comp1 - &comp3; - - let result = r0 + (comp1 << 32*i) + (comp2 << 2*32*i) + (comp3 << 3*32*i) + (r4 << 4*32*i); - let result_pos = result.to_biguint().unwrap(); - add2(&mut acc[..], &result_pos.data); - } -} - -pub fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { - let len = x.len() + y.len() + 1; - let mut prod = BigUint { data: vec![0; len] }; - - mac3(&mut prod.data[..], x, y); - prod.normalized() -} - -pub fn scalar_mul(a: &mut [BigDigit], b: BigDigit) -> BigDigit { - let mut carry = 0; - for a in a.iter_mut() { - *a = mul_with_carry(*a, b, &mut carry); - } - carry -} - -pub fn div_rem(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { - if d.is_zero() { - panic!() - } - if u.is_zero() { - return (Zero::zero(), Zero::zero()); - } - if *d == One::one() { - return (u.clone(), Zero::zero()); - } - - // Required or the q_len calculation below can underflow: - match u.cmp(d) { - Less => return (Zero::zero(), u.clone()), - Equal => return (One::one(), Zero::zero()), - Greater => {} // Do nothing - } - - // This algorithm is from Knuth, TAOCP vol 2 section 4.3, algorithm D: - // - // First, normalize the arguments so the highest bit in the highest digit of the divisor is - // set: the main loop uses the highest digit of the divisor for generating guesses, so we - // want it to be the largest number we can efficiently divide by. - // - let shift = d.data.last().unwrap().leading_zeros() as usize; - let mut a = u << shift; - let b = d << shift; - - // The algorithm works by incrementally calculating "guesses", q0, for part of the - // remainder. Once we have any number q0 such that q0 * b <= a, we can set - // - // q += q0 - // a -= q0 * b - // - // and then iterate until a < b. Then, (q, a) will be our desired quotient and remainder. - // - // q0, our guess, is calculated by dividing the last few digits of a by the last digit of b - // - this should give us a guess that is "close" to the actual quotient, but is possibly - // greater than the actual quotient. If q0 * b > a, we simply use iterated subtraction - // until we have a guess such that q0 * b <= a. - // - - let bn = *b.data.last().unwrap(); - let q_len = a.data.len() - b.data.len() + 1; - let mut q = BigUint { data: vec![0; q_len] }; - - // We reuse the same temporary to avoid hitting the allocator in our inner loop - this is - // sized to hold a0 (in the common case; if a particular digit of the quotient is zero a0 - // can be bigger). - // - let mut tmp = BigUint { data: Vec::with_capacity(2) }; - - for j in (0..q_len).rev() { - /* - * When calculating our next guess q0, we don't need to consider the digits below j - * + b.data.len() - 1: we're guessing digit j of the quotient (i.e. q0 << j) from - * digit bn of the divisor (i.e. bn << (b.data.len() - 1) - so the product of those - * two numbers will be zero in all digits up to (j + b.data.len() - 1). - */ - let offset = j + b.data.len() - 1; - if offset >= a.data.len() { - continue; - } - - /* just avoiding a heap allocation: */ - let mut a0 = tmp; - a0.data.truncate(0); - a0.data.extend(a.data[offset..].iter().cloned()); - - /* - * q0 << j * big_digit::BITS is our actual quotient estimate - we do the shifts - * implicitly at the end, when adding and subtracting to a and q. Not only do we - * save the cost of the shifts, the rest of the arithmetic gets to work with - * smaller numbers. - */ - let (mut q0, _) = div_rem_digit(a0, bn); - let mut prod = &b * &q0; - - while cmp_slice(&prod.data[..], &a.data[j..]) == Greater { - let one: BigUint = One::one(); - q0 = q0 - one; - prod = prod - &b; - } - - add2(&mut q.data[j..], &q0.data[..]); - sub2(&mut a.data[j..], &prod.data[..]); - a.normalize(); - - tmp = q0; - } - - debug_assert!(a < b); - - (q.normalized(), a >> shift) -} - -/// Find last set bit -/// fls(0) == 0, fls(u32::MAX) == 32 -pub fn fls(v: T) -> usize { - mem::size_of::() * 8 - v.leading_zeros() as usize -} - -pub fn ilog2(v: T) -> usize { - fls(v) - 1 -} - -#[inline] -pub fn biguint_shl(n: Cow, bits: usize) -> BigUint { - let n_unit = bits / big_digit::BITS; - let mut data = match n_unit { - 0 => n.into_owned().data, - _ => { - let len = n_unit + n.data.len() + 1; - let mut data = Vec::with_capacity(len); - data.extend(repeat(0).take(n_unit)); - data.extend(n.data.iter().cloned()); - data - } - }; - - let n_bits = bits % big_digit::BITS; - if n_bits > 0 { - let mut carry = 0; - for elem in data[n_unit..].iter_mut() { - let new_carry = *elem >> (big_digit::BITS - n_bits); - *elem = (*elem << n_bits) | carry; - carry = new_carry; - } - if carry != 0 { - data.push(carry); - } - } - - BigUint::new(data) -} - -#[inline] -pub fn biguint_shr(n: Cow, bits: usize) -> BigUint { - let n_unit = bits / big_digit::BITS; - if n_unit >= n.data.len() { - return Zero::zero(); - } - let mut data = match n_unit { - 0 => n.into_owned().data, - _ => n.data[n_unit..].to_vec(), - }; - - let n_bits = bits % big_digit::BITS; - if n_bits > 0 { - let mut borrow = 0; - for elem in data.iter_mut().rev() { - let new_borrow = *elem << (big_digit::BITS - n_bits); - *elem = (*elem >> n_bits) | borrow; - borrow = new_borrow; - } - } - - BigUint::new(data) -} - -pub fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { - debug_assert!(a.last() != Some(&0)); - debug_assert!(b.last() != Some(&0)); - - let (a_len, b_len) = (a.len(), b.len()); - if a_len < b_len { - return Less; - } - if a_len > b_len { - return Greater; - } - - for (&ai, &bi) in a.iter().rev().zip(b.iter().rev()) { - if ai < bi { - return Less; - } - if ai > bi { - return Greater; - } - } - return Equal; -} - -#[cfg(test)] -mod algorithm_tests { - use {BigDigit, BigUint, BigInt}; - use Sign::Plus; - use traits::Num; - - #[test] - fn test_sub_sign() { - use super::sub_sign; - - fn sub_sign_i(a: &[BigDigit], b: &[BigDigit]) -> BigInt { - let (sign, val) = sub_sign(a, b); - BigInt::from_biguint(sign, val) - } - - let a = BigUint::from_str_radix("265252859812191058636308480000000", 10).unwrap(); - let b = BigUint::from_str_radix("26525285981219105863630848000000", 10).unwrap(); - let a_i = BigInt::from_biguint(Plus, a.clone()); - let b_i = BigInt::from_biguint(Plus, b.clone()); - - assert_eq!(sub_sign_i(&a.data[..], &b.data[..]), &a_i - &b_i); - assert_eq!(sub_sign_i(&b.data[..], &a.data[..]), &b_i - &a_i); - } -} diff --git a/bigint/src/bigint.rs b/bigint/src/bigint.rs deleted file mode 100644 index bf55b89..0000000 --- a/bigint/src/bigint.rs +++ /dev/null @@ -1,1767 +0,0 @@ -use std::default::Default; -use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Not}; -use std::str::{self, FromStr}; -use std::fmt; -use std::cmp::Ordering::{self, Less, Greater, Equal}; -use std::{i64, u64}; -use std::ascii::AsciiExt; - -#[cfg(feature = "serde")] -use serde; - -// Some of the tests of non-RNG-based functionality are randomized using the -// RNG-based functionality, so the RNG-based functionality needs to be enabled -// for tests. -#[cfg(any(feature = "rand", test))] -use rand::Rng; - -use integer::Integer; -use traits::{ToPrimitive, FromPrimitive, Num, CheckedAdd, CheckedSub, - CheckedMul, CheckedDiv, Signed, Zero, One}; - -use self::Sign::{Minus, NoSign, Plus}; - -use super::ParseBigIntError; -use super::big_digit; -use super::big_digit::{BigDigit, DoubleBigDigit}; -use biguint; -use biguint::to_str_radix_reversed; -use biguint::BigUint; - -use UsizePromotion; -use IsizePromotion; - -#[cfg(test)] -#[path = "tests/bigint.rs"] -mod bigint_tests; - -/// A Sign is a `BigInt`'s composing element. -#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)] -#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] -pub enum Sign { - Minus, - NoSign, - Plus, -} - -impl Neg for Sign { - type Output = Sign; - - /// Negate Sign value. - #[inline] - fn neg(self) -> Sign { - match self { - Minus => Plus, - NoSign => NoSign, - Plus => Minus, - } - } -} - -impl Mul for Sign { - type Output = Sign; - - #[inline] - fn mul(self, other: Sign) -> Sign { - match (self, other) { - (NoSign, _) | (_, NoSign) => NoSign, - (Plus, Plus) | (Minus, Minus) => Plus, - (Plus, Minus) | (Minus, Plus) => Minus, - } - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for Sign { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: serde::Serializer - { - match *self { - Sign::Minus => (-1i8).serialize(serializer), - Sign::NoSign => 0i8.serialize(serializer), - Sign::Plus => 1i8.serialize(serializer), - } - } -} - -#[cfg(feature = "serde")] -impl serde::Deserialize for Sign { - fn deserialize(deserializer: &mut D) -> Result - where D: serde::Deserializer - { - use serde::de::Error; - - let sign: i8 = try!(serde::Deserialize::deserialize(deserializer)); - match sign { - -1 => Ok(Sign::Minus), - 0 => Ok(Sign::NoSign), - 1 => Ok(Sign::Plus), - _ => Err(D::Error::invalid_value("sign must be -1, 0, or 1")), - } - } -} - -/// A big signed integer type. -#[derive(Clone, Debug, Hash)] -#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] -pub struct BigInt { - sign: Sign, - data: BigUint, -} - -impl PartialEq for BigInt { - #[inline] - fn eq(&self, other: &BigInt) -> bool { - self.cmp(other) == Equal - } -} - -impl Eq for BigInt {} - -impl PartialOrd for BigInt { - #[inline] - fn partial_cmp(&self, other: &BigInt) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for BigInt { - #[inline] - fn cmp(&self, other: &BigInt) -> Ordering { - let scmp = self.sign.cmp(&other.sign); - if scmp != Equal { - return scmp; - } - - match self.sign { - NoSign => Equal, - Plus => self.data.cmp(&other.data), - Minus => other.data.cmp(&self.data), - } - } -} - -impl Default for BigInt { - #[inline] - fn default() -> BigInt { - Zero::zero() - } -} - -impl fmt::Display for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "", &self.data.to_str_radix(10)) - } -} - -impl fmt::Binary for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "0b", &self.data.to_str_radix(2)) - } -} - -impl fmt::Octal for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "0o", &self.data.to_str_radix(8)) - } -} - -impl fmt::LowerHex for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), "0x", &self.data.to_str_radix(16)) - } -} - -impl fmt::UpperHex for BigInt { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(!self.is_negative(), - "0x", - &self.data.to_str_radix(16).to_ascii_uppercase()) - } -} - -impl FromStr for BigInt { - type Err = ParseBigIntError; - - #[inline] - fn from_str(s: &str) -> Result { - BigInt::from_str_radix(s, 10) - } -} - -impl Num for BigInt { - type FromStrRadixErr = ParseBigIntError; - - /// Creates and initializes a BigInt. - #[inline] - fn from_str_radix(mut s: &str, radix: u32) -> Result { - let sign = if s.starts_with('-') { - let tail = &s[1..]; - if !tail.starts_with('+') { - s = tail - } - Minus - } else { - Plus - }; - let bu = try!(BigUint::from_str_radix(s, radix)); - Ok(BigInt::from_biguint(sign, bu)) - } -} - -impl Shl for BigInt { - type Output = BigInt; - - #[inline] - fn shl(self, rhs: usize) -> BigInt { - (&self) << rhs - } -} - -impl<'a> Shl for &'a BigInt { - type Output = BigInt; - - #[inline] - fn shl(self, rhs: usize) -> BigInt { - BigInt::from_biguint(self.sign, &self.data << rhs) - } -} - -impl Shr for BigInt { - type Output = BigInt; - - #[inline] - fn shr(self, rhs: usize) -> BigInt { - BigInt::from_biguint(self.sign, self.data >> rhs) - } -} - -impl<'a> Shr for &'a BigInt { - type Output = BigInt; - - #[inline] - fn shr(self, rhs: usize) -> BigInt { - BigInt::from_biguint(self.sign, &self.data >> rhs) - } -} - -impl Zero for BigInt { - #[inline] - fn zero() -> BigInt { - BigInt::from_biguint(NoSign, Zero::zero()) - } - - #[inline] - fn is_zero(&self) -> bool { - self.sign == NoSign - } -} - -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 | NoSign => 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()), - NoSign => Zero::zero(), - } - } - - #[inline] - fn is_positive(&self) -> bool { - self.sign == Plus - } - - #[inline] - fn is_negative(&self) -> bool { - self.sign == Minus - } -} - -// A convenience method for getting the absolute value of an i32 in a u32. -#[inline] -fn i32_abs_as_u32(a: i32) -> u32 { - if a == i32::min_value() { - a as u32 - } else { - a.abs() as u32 - } -} - -// A convenience method for getting the absolute value of an i64 in a u64. -#[inline] -fn i64_abs_as_u64(a: i64) -> u64 { - if a == i64::min_value() { - a as u64 - } else { - a.abs() as u64 - } -} - -// We want to forward to BigUint::add, but it's not clear how that will go until -// we compare both sign and magnitude. So we duplicate this body for every -// val/ref combination, deferring that decision to BigUint's own forwarding. -macro_rules! bigint_add { - ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { - match ($a.sign, $b.sign) { - (_, NoSign) => $a_owned, - (NoSign, _) => $b_owned, - // same sign => keep the sign with the sum of magnitudes - (Plus, Plus) | (Minus, Minus) => - BigInt::from_biguint($a.sign, $a_data + $b_data), - // opposite signs => keep the sign of the larger with the difference of magnitudes - (Plus, Minus) | (Minus, Plus) => - match $a.data.cmp(&$b.data) { - Less => BigInt::from_biguint($b.sign, $b_data - $a_data), - Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), - Equal => Zero::zero(), - }, - } - }; -} - -impl<'a, 'b> Add<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: &BigInt) -> BigInt { - bigint_add!(self, - self.clone(), - &self.data, - other, - other.clone(), - &other.data) - } -} - -impl<'a> Add for &'a BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: BigInt) -> BigInt { - bigint_add!(self, self.clone(), &self.data, other, other, other.data) - } -} - -impl<'a> Add<&'a BigInt> for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: &BigInt) -> BigInt { - bigint_add!(self, self, self.data, other, other.clone(), &other.data) - } -} - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: BigInt) -> BigInt { - bigint_add!(self, self, self.data, other, other, other.data) - } -} - -promote_all_scalars!(impl Add for BigInt, add); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: BigDigit) -> BigInt { - match self.sign { - NoSign => From::from(other), - Plus => BigInt::from_biguint(Plus, self.data + other), - Minus => - match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Less => BigInt::from_biguint(Plus, other - self.data), - Greater => BigInt::from_biguint(Minus, self.data - other), - } - } - } -} - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: DoubleBigDigit) -> BigInt { - match self.sign { - NoSign => From::from(other), - Plus => BigInt::from_biguint(Plus, self.data + other), - Minus => - match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Less => BigInt::from_biguint(Plus, other - self.data), - Greater => BigInt::from_biguint(Minus, self.data - other), - } - } - } -} - -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: i32) -> BigInt { - if other >= 0 { - self + other as u32 - } else { - self - i32_abs_as_u32(other) - } - } -} - -impl Add for BigInt { - type Output = BigInt; - - #[inline] - fn add(self, other: i64) -> BigInt { - if other >= 0 { - self + other as u64 - } else { - self - i64_abs_as_u64(other) - } - } -} - -// We want to forward to BigUint::sub, but it's not clear how that will go until -// we compare both sign and magnitude. So we duplicate this body for every -// val/ref combination, deferring that decision to BigUint's own forwarding. -macro_rules! bigint_sub { - ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { - match ($a.sign, $b.sign) { - (_, NoSign) => $a_owned, - (NoSign, _) => -$b_owned, - // opposite signs => keep the sign of the left with the sum of magnitudes - (Plus, Minus) | (Minus, Plus) => - BigInt::from_biguint($a.sign, $a_data + $b_data), - // same sign => keep or toggle the sign of the left with the difference of magnitudes - (Plus, Plus) | (Minus, Minus) => - match $a.data.cmp(&$b.data) { - Less => BigInt::from_biguint(-$a.sign, $b_data - $a_data), - Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), - Equal => Zero::zero(), - }, - } - }; -} - -impl<'a, 'b> Sub<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: &BigInt) -> BigInt { - bigint_sub!(self, - self.clone(), - &self.data, - other, - other.clone(), - &other.data) - } -} - -impl<'a> Sub for &'a BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - bigint_sub!(self, self.clone(), &self.data, other, other, other.data) - } -} - -impl<'a> Sub<&'a BigInt> for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: &BigInt) -> BigInt { - bigint_sub!(self, self, self.data, other, other.clone(), &other.data) - } -} - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - bigint_sub!(self, self, self.data, other, other, other.data) - } -} - -promote_all_scalars!(impl Sub for BigInt, sub); -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigDigit) -> BigInt { - match self.sign { - NoSign => BigInt::from_biguint(Minus, From::from(other)), - Minus => BigInt::from_biguint(Minus, self.data + other), - Plus => - match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Greater => BigInt::from_biguint(Plus, self.data - other), - Less => BigInt::from_biguint(Minus, other - self.data), - } - } - } -} - -impl Sub for BigDigit { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - -(other - self) - } -} - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: DoubleBigDigit) -> BigInt { - match self.sign { - NoSign => BigInt::from_biguint(Minus, From::from(other)), - Minus => BigInt::from_biguint(Minus, self.data + other), - Plus => - match self.data.cmp(&From::from(other)) { - Equal => Zero::zero(), - Greater => BigInt::from_biguint(Plus, self.data - other), - Less => BigInt::from_biguint(Minus, other - self.data), - } - } - } -} - -impl Sub for DoubleBigDigit { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - -(other - self) - } -} - -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); -forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: i32) -> BigInt { - if other >= 0 { - self - other as u32 - } else { - self + i32_abs_as_u32(other) - } - } -} - -impl Sub for i32 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u32 - other - } else { - -other - i32_abs_as_u32(self) - } - } -} - -impl Sub for BigInt { - type Output = BigInt; - - #[inline] - fn sub(self, other: i64) -> BigInt { - if other >= 0 { - self - other as u64 - } else { - self + i64_abs_as_u64(other) - } - } -} - -impl Sub for i64 { - type Output = BigInt; - - #[inline] - fn sub(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u64 - other - } else { - -other - i64_abs_as_u64(self) - } - } -} - -forward_all_binop_to_ref_ref!(impl Mul for BigInt, mul); - -impl<'a, 'b> Mul<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: &BigInt) -> BigInt { - BigInt::from_biguint(self.sign * other.sign, &self.data * &other.data) - } -} - -promote_all_scalars!(impl Mul for BigInt, mul); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: BigDigit) -> BigInt { - BigInt::from_biguint(self.sign, self.data * other) - } -} - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: DoubleBigDigit) -> BigInt { - BigInt::from_biguint(self.sign, self.data * other) - } -} - -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: i32) -> BigInt { - if other >= 0 { - self * other as u32 - } else { - -(self * i32_abs_as_u32(other)) - } - } -} - -impl Mul for BigInt { - type Output = BigInt; - - #[inline] - fn mul(self, other: i64) -> BigInt { - if other >= 0 { - self * other as u64 - } else { - -(self * i64_abs_as_u64(other)) - } - } -} - -forward_all_binop_to_ref_ref!(impl Div for BigInt, div); - -impl<'a, 'b> Div<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: &BigInt) -> BigInt { - let (q, _) = self.div_rem(other); - q - } -} - -promote_all_scalars!(impl Div for BigInt, div); -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: BigDigit) -> BigInt { - BigInt::from_biguint(self.sign, self.data / other) - } -} - -impl Div for BigDigit { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - BigInt::from_biguint(other.sign, self / other.data) - } -} - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: DoubleBigDigit) -> BigInt { - BigInt::from_biguint(self.sign, self.data / other) - } -} - -impl Div for DoubleBigDigit { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - BigInt::from_biguint(other.sign, self / other.data) - } -} - -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); -forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: i32) -> BigInt { - if other >= 0 { - self / other as u32 - } else { - -(self / i32_abs_as_u32(other)) - } - } -} - -impl Div for i32 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u32 / other - } else { - -(i32_abs_as_u32(self) / other) - } - } -} - -impl Div for BigInt { - type Output = BigInt; - - #[inline] - fn div(self, other: i64) -> BigInt { - if other >= 0 { - self / other as u64 - } else { - -(self / i64_abs_as_u64(other)) - } - } -} - -impl Div for i64 { - type Output = BigInt; - - #[inline] - fn div(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u64 / other - } else { - -(i64_abs_as_u64(self) / other) - } - } -} - -forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem); - -impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: &BigInt) -> BigInt { - let (_, r) = self.div_rem(other); - r - } -} - -promote_all_scalars!(impl Rem for BigInt, rem); -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigDigit) -> BigInt { - BigInt::from_biguint(self.sign, self.data % other) - } -} - -impl Rem for BigDigit { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - BigInt::from_biguint(Plus, self % other.data) - } -} - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: DoubleBigDigit) -> BigInt { - BigInt::from_biguint(self.sign, self.data % other) - } -} - -impl Rem for DoubleBigDigit { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - BigInt::from_biguint(Plus, self % other.data) - } -} - -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); -forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: i32) -> BigInt { - if other >= 0 { - self % other as u32 - } else { - self % i32_abs_as_u32(other) - } - } -} - -impl Rem for i32 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u32 % other - } else { - -(i32_abs_as_u32(self) % other) - } - } -} - -impl Rem for BigInt { - type Output = BigInt; - - #[inline] - fn rem(self, other: i64) -> BigInt { - if other >= 0 { - self % other as u64 - } else { - self % i64_abs_as_u64(other) - } - } -} - -impl Rem for i64 { - type Output = BigInt; - - #[inline] - fn rem(self, other: BigInt) -> BigInt { - if self >= 0 { - self as u64 % other - } else { - -(i64_abs_as_u64(self) % other) - } - } -} - -impl Neg for BigInt { - type Output = BigInt; - - #[inline] - fn neg(mut self) -> BigInt { - self.sign = -self.sign; - self - } -} - -impl<'a> Neg for &'a BigInt { - type Output = BigInt; - - #[inline] - fn neg(self) -> BigInt { - -self.clone() - } -} - -impl CheckedAdd for BigInt { - #[inline] - fn checked_add(&self, v: &BigInt) -> Option { - return Some(self.add(v)); - } -} - -impl CheckedSub for BigInt { - #[inline] - fn checked_sub(&self, v: &BigInt) -> Option { - return Some(self.sub(v)); - } -} - -impl CheckedMul for BigInt { - #[inline] - fn checked_mul(&self, v: &BigInt) -> Option { - return Some(self.mul(v)); - } -} - -impl CheckedDiv for BigInt { - #[inline] - fn checked_div(&self, v: &BigInt) -> Option { - if v.is_zero() { - return None; - } - return Some(self.div(v)); - } -} - -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(self.sign, d_ui); - let r = BigInt::from_biguint(self.sign, r_ui); - if other.is_negative() { - (-d, r) - } else { - (d, r) - } - } - - #[inline] - fn div_floor(&self, other: &BigInt) -> BigInt { - let (d, _) = self.div_mod_floor(other); - d - } - - #[inline] - fn mod_floor(&self, other: &BigInt) -> BigInt { - let (_, m) = self.div_mod_floor(other); - 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); - let one: BigInt = One::one(); - match (self.sign, other.sign) { - (_, NoSign) => panic!(), - (Plus, Plus) | (NoSign, Plus) => (d, m), - (Plus, Minus) | (NoSign, Minus) => { - if m.is_zero() { - (-d, Zero::zero()) - } else { - (-d - one, m + other) - } - } - (Minus, Plus) => { - if m.is_zero() { - (-d, Zero::zero()) - } else { - (-d - 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)) - } - - /// Deprecated, use `is_multiple_of` instead. - #[inline] - fn divides(&self, other: &BigInt) -> bool { - return self.is_multiple_of(other); - } - - /// Returns `true` if the number is a multiple of `other`. - #[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 { - match self.sign { - Plus => self.data.to_i64(), - NoSign => 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 { - match self.sign { - Plus => self.data.to_u64(), - NoSign => Some(0), - Minus => None, - } - } - - #[inline] - fn to_f32(&self) -> Option { - self.data.to_f32().map(|n| { - if self.sign == Minus { - -n - } else { - n - } - }) - } - - #[inline] - fn to_f64(&self) -> Option { - self.data.to_f64().map(|n| { - if self.sign == Minus { - -n - } else { - n - } - }) - } -} - -impl FromPrimitive for BigInt { - #[inline] - fn from_i64(n: i64) -> Option { - Some(BigInt::from(n)) - } - - #[inline] - fn from_u64(n: u64) -> Option { - Some(BigInt::from(n)) - } - - #[inline] - fn from_f64(n: f64) -> Option { - if n >= 0.0 { - BigUint::from_f64(n).map(|x| BigInt::from_biguint(Plus, x)) - } else { - BigUint::from_f64(-n).map(|x| BigInt::from_biguint(Minus, x)) - } - } -} - -impl From for BigInt { - #[inline] - fn from(n: i64) -> Self { - if n >= 0 { - BigInt::from(n as u64) - } else { - let u = u64::MAX - (n as u64) + 1; - BigInt { - sign: Minus, - data: BigUint::from(u), - } - } - } -} - -macro_rules! impl_bigint_from_int { - ($T:ty) => { - impl From<$T> for BigInt { - #[inline] - fn from(n: $T) -> Self { - BigInt::from(n as i64) - } - } - } -} - -impl_bigint_from_int!(i8); -impl_bigint_from_int!(i16); -impl_bigint_from_int!(i32); -impl_bigint_from_int!(isize); - -impl From for BigInt { - #[inline] - fn from(n: u64) -> Self { - if n > 0 { - BigInt { - sign: Plus, - data: BigUint::from(n), - } - } else { - BigInt::zero() - } - } -} - -macro_rules! impl_bigint_from_uint { - ($T:ty) => { - impl From<$T> for BigInt { - #[inline] - fn from(n: $T) -> Self { - BigInt::from(n as u64) - } - } - } -} - -impl_bigint_from_uint!(u8); -impl_bigint_from_uint!(u16); -impl_bigint_from_uint!(u32); -impl_bigint_from_uint!(usize); - -impl From for BigInt { - #[inline] - fn from(n: BigUint) -> Self { - if n.is_zero() { - BigInt::zero() - } else { - BigInt { - sign: Plus, - data: n, - } - } - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for BigInt { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: serde::Serializer - { - (self.sign, &self.data).serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl serde::Deserialize for BigInt { - fn deserialize(deserializer: &mut D) -> Result - where D: serde::Deserializer - { - let (sign, data) = try!(serde::Deserialize::deserialize(deserializer)); - Ok(BigInt { - sign: sign, - data: data, - }) - } -} - -/// 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; -} - -impl ToBigInt for BigInt { - #[inline] - fn to_bigint(&self) -> Option { - Some(self.clone()) - } -} - -impl ToBigInt for BigUint { - #[inline] - fn to_bigint(&self) -> Option { - if self.is_zero() { - Some(Zero::zero()) - } else { - Some(BigInt { - sign: Plus, - data: self.clone(), - }) - } - } -} - -impl biguint::ToBigUint for BigInt { - #[inline] - fn to_biguint(&self) -> Option { - match self.sign() { - Plus => Some(self.data.clone()), - NoSign => Some(Zero::zero()), - Minus => None, - } - } -} - -macro_rules! impl_to_bigint { - ($T:ty, $from_ty:path) => { - impl ToBigInt for $T { - #[inline] - fn to_bigint(&self) -> Option { - $from_ty(*self) - } - } - } -} - -impl_to_bigint!(isize, FromPrimitive::from_isize); -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!(usize, FromPrimitive::from_usize); -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_to_bigint!(f32, FromPrimitive::from_f32); -impl_to_bigint!(f64, FromPrimitive::from_f64); - -pub trait RandBigInt { - /// Generate a random `BigUint` of the given bit size. - fn gen_biguint(&mut self, bit_size: usize) -> BigUint; - - /// Generate a random BigInt of the given bit size. - fn gen_bigint(&mut self, bit_size: usize) -> 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; -} - -#[cfg(any(feature = "rand", test))] -impl RandBigInt for R { - fn gen_biguint(&mut self, bit_size: usize) -> BigUint { - let (digits, rem) = bit_size.div_rem(&big_digit::BITS); - let mut data = Vec::with_capacity(digits + 1); - for _ in 0..digits { - data.push(self.gen()); - } - if rem > 0 { - let final_digit: BigDigit = self.gen(); - data.push(final_digit >> (big_digit::BITS - rem)); - } - BigUint::new(data) - } - - fn gen_bigint(&mut self, bit_size: usize) -> 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 { - NoSign - } - } else if self.gen() { - Plus - } else { - Minus - }; - 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. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn new(sign: Sign, digits: Vec) -> BigInt { - BigInt::from_biguint(sign, BigUint::new(digits)) - } - - /// Creates and initializes a `BigInt`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt { - if sign == NoSign { - data.assign_from_slice(&[]); - } else if data.is_zero() { - sign = NoSign; - } - - 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)) - } - - /// Reinitializes a `BigInt`. - #[inline] - pub fn assign_from_slice(&mut self, sign: Sign, slice: &[BigDigit]) { - if sign == NoSign { - self.data.assign_from_slice(&[]); - self.sign = NoSign; - } else { - self.data.assign_from_slice(slice); - self.sign = match self.data.is_zero() { - true => NoSign, - false => sign, - } - } - } - - /// Creates and initializes a `BigInt`. - /// - /// The bytes are in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"A"), - /// BigInt::parse_bytes(b"65", 10).unwrap()); - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AA"), - /// BigInt::parse_bytes(b"16705", 10).unwrap()); - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"AB"), - /// BigInt::parse_bytes(b"16706", 10).unwrap()); - /// assert_eq!(BigInt::from_bytes_be(Sign::Plus, b"Hello world!"), - /// BigInt::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); - /// ``` - #[inline] - pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> BigInt { - BigInt::from_biguint(sign, BigUint::from_bytes_be(bytes)) - } - - /// Creates and initializes a `BigInt`. - /// - /// The bytes are in little-endian byte order. - #[inline] - pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> BigInt { - BigInt::from_biguint(sign, BigUint::from_bytes_le(bytes)) - } - - /// Creates and initializes a `BigInt` from an array of bytes in - /// two's complement binary representation. - /// - /// The digits are in big-endian base 28. - #[inline] - pub fn from_signed_bytes_be(digits: &[u8]) -> BigInt { - let sign = match digits.first() { - Some(v) if *v > 0x7f => Sign::Minus, - Some(_) => Sign::Plus, - None => return BigInt::zero(), - }; - - if sign == Sign::Minus { - // two's-complement the content to retrieve the magnitude - let mut digits = Vec::from(digits); - twos_complement_be(&mut digits); - BigInt::from_biguint(sign, BigUint::from_bytes_be(&*digits)) - } else { - BigInt::from_biguint(sign, BigUint::from_bytes_be(digits)) - } - } - - /// Creates and initializes a `BigInt` from an array of bytes in two's complement. - /// - /// The digits are in little-endian base 28. - #[inline] - pub fn from_signed_bytes_le(digits: &[u8]) -> BigInt { - let sign = match digits.last() { - Some(v) if *v > 0x7f => Sign::Minus, - Some(_) => Sign::Plus, - None => return BigInt::zero(), - }; - - if sign == Sign::Minus { - // two's-complement the content to retrieve the magnitude - let mut digits = Vec::from(digits); - twos_complement_le(&mut digits); - BigInt::from_biguint(sign, BigUint::from_bytes_le(&*digits)) - } else { - BigInt::from_biguint(sign, BigUint::from_bytes_le(digits)) - } - } - - /// Creates and initializes a `BigInt`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, ToBigInt}; - /// - /// assert_eq!(BigInt::parse_bytes(b"1234", 10), ToBigInt::to_bigint(&1234)); - /// assert_eq!(BigInt::parse_bytes(b"ABCD", 16), ToBigInt::to_bigint(&0xABCD)); - /// assert_eq!(BigInt::parse_bytes(b"G", 16), None); - /// ``` - #[inline] - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - str::from_utf8(buf).ok().and_then(|s| BigInt::from_str_radix(s, radix).ok()) - } - - /// Creates and initializes a `BigInt`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in big-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// let inbase190 = vec![15, 33, 125, 12, 14]; - /// let a = BigInt::from_radix_be(Sign::Minus, &inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), (Sign:: Minus, inbase190)); - /// ``` - pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option { - BigUint::from_radix_be(buf, radix).map(|u| BigInt::from_biguint(sign, u)) - } - - /// Creates and initializes a `BigInt`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in little-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// let inbase190 = vec![14, 12, 125, 33, 15]; - /// let a = BigInt::from_radix_be(Sign::Minus, &inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), (Sign::Minus, inbase190)); - /// ``` - pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option { - BigUint::from_radix_le(buf, radix).map(|u| BigInt::from_biguint(sign, u)) - } - - /// Returns the sign and the byte representation of the `BigInt` in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{ToBigInt, Sign}; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_bytes_be(), (Sign::Minus, vec![4, 101])); - /// ``` - #[inline] - pub fn to_bytes_be(&self) -> (Sign, Vec) { - (self.sign, self.data.to_bytes_be()) - } - - /// Returns the sign and the byte representation of the `BigInt` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{ToBigInt, Sign}; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_bytes_le(), (Sign::Minus, vec![101, 4])); - /// ``` - #[inline] - pub fn to_bytes_le(&self) -> (Sign, Vec) { - (self.sign, self.data.to_bytes_le()) - } - - /// Returns the two's complement byte representation of the `BigInt` in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::ToBigInt; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_signed_bytes_be(), vec![251, 155]); - /// ``` - #[inline] - pub fn to_signed_bytes_be(&self) -> Vec { - let mut bytes = self.data.to_bytes_be(); - let first_byte = bytes.first().map(|v| *v).unwrap_or(0); - if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero)) { - // msb used by magnitude, extend by 1 byte - bytes.insert(0, 0); - } - if self.sign == Sign::Minus { - twos_complement_be(&mut bytes); - } - bytes - } - - /// Returns the two's complement byte representation of the `BigInt` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::ToBigInt; - /// - /// let i = -1125.to_bigint().unwrap(); - /// assert_eq!(i.to_signed_bytes_le(), vec![155, 251]); - /// ``` - #[inline] - pub fn to_signed_bytes_le(&self) -> Vec { - let mut bytes = self.data.to_bytes_le(); - let last_byte = bytes.last().map(|v| *v).unwrap_or(0); - if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero)) { - // msb used by magnitude, extend by 1 byte - bytes.push(0); - } - if self.sign == Sign::Minus { - twos_complement_le(&mut bytes); - } - bytes - } - - /// Returns the integer formatted as a string in the given radix. - /// `radix` must be in the range `2...36`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigInt; - /// - /// let i = BigInt::parse_bytes(b"ff", 16).unwrap(); - /// assert_eq!(i.to_str_radix(16), "ff"); - /// ``` - #[inline] - pub fn to_str_radix(&self, radix: u32) -> String { - let mut v = to_str_radix_reversed(&self.data, radix); - - if self.is_negative() { - v.push(b'-'); - } - - v.reverse(); - unsafe { String::from_utf8_unchecked(v) } - } - - /// Returns the integer in the requested base in big-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// assert_eq!(BigInt::from(-0xFFFFi64).to_radix_be(159), - /// (Sign::Minus, vec![2, 94, 27])); - /// // 0xFFFF = 65535 = 2*(159^2) + 94*159 + 27 - /// ``` - #[inline] - pub fn to_radix_be(&self, radix: u32) -> (Sign, Vec) { - (self.sign, self.data.to_radix_be(radix)) - } - - /// Returns the integer in the requested base in little-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigInt, Sign}; - /// - /// assert_eq!(BigInt::from(-0xFFFFi64).to_radix_le(159), - /// (Sign::Minus, vec![27, 94, 2])); - /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) - /// ``` - #[inline] - pub fn to_radix_le(&self, radix: u32) -> (Sign, Vec) { - (self.sign, self.data.to_radix_le(radix)) - } - - /// Returns the sign of the `BigInt` as a `Sign`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{ToBigInt, Sign}; - /// - /// assert_eq!(ToBigInt::to_bigint(&1234).unwrap().sign(), Sign::Plus); - /// assert_eq!(ToBigInt::to_bigint(&-4321).unwrap().sign(), Sign::Minus); - /// assert_eq!(ToBigInt::to_bigint(&0).unwrap().sign(), Sign::NoSign); - /// ``` - #[inline] - pub fn sign(&self) -> Sign { - self.sign - } - - /// Determines the fewest bits necessary to express the `BigInt`, - /// not including the sign. - #[inline] - pub fn bits(&self) -> usize { - self.data.bits() - } - - /// Converts this `BigInt` into a `BigUint`, if it's not negative. - #[inline] - pub fn to_biguint(&self) -> Option { - match self.sign { - Plus => Some(self.data.clone()), - NoSign => Some(Zero::zero()), - Minus => None, - } - } - - #[inline] - pub fn checked_add(&self, v: &BigInt) -> Option { - return Some(self.add(v)); - } - - #[inline] - pub fn checked_sub(&self, v: &BigInt) -> Option { - return Some(self.sub(v)); - } - - #[inline] - pub fn checked_mul(&self, v: &BigInt) -> Option { - return Some(self.mul(v)); - } - - #[inline] - pub fn checked_div(&self, v: &BigInt) -> Option { - if v.is_zero() { - return None; - } - return Some(self.div(v)); - } -} - -/// Perform in-place two's complement of the given binary representation, -/// in little-endian byte order. -#[inline] -fn twos_complement_le(digits: &mut [u8]) { - twos_complement(digits) -} - -/// Perform in-place two's complement of the given binary representation -/// in big-endian byte order. -#[inline] -fn twos_complement_be(digits: &mut [u8]) { - twos_complement(digits.iter_mut().rev()) -} - -/// Perform in-place two's complement of the given digit iterator -/// starting from the least significant byte. -#[inline] -fn twos_complement<'a, I>(digits: I) - where I: IntoIterator -{ - let mut carry = true; - for d in digits { - *d = d.not(); - if carry { - *d = d.wrapping_add(1); - carry = d.is_zero(); - } - } -} diff --git a/bigint/src/biguint.rs b/bigint/src/biguint.rs deleted file mode 100644 index df551ba..0000000 --- a/bigint/src/biguint.rs +++ /dev/null @@ -1,2242 +0,0 @@ -use std::borrow::Cow; -use std::default::Default; -use std::iter::repeat; -use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub, - AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, - MulAssign, RemAssign, ShlAssign, ShrAssign, SubAssign}; -use std::str::{self, FromStr}; -use std::fmt; -use std::cmp; -use std::cmp::Ordering::{self, Less, Greater, Equal}; -use std::{f32, f64}; -use std::{u8, u64}; -use std::ascii::AsciiExt; - -#[cfg(feature = "serde")] -use serde; - -use integer::Integer; -use traits::{ToPrimitive, FromPrimitive, Float, Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, - CheckedDiv, Zero, One}; - -#[path = "algorithms.rs"] -mod algorithms; -#[path = "monty.rs"] -mod monty; -pub use self::algorithms::big_digit; -pub use self::big_digit::{BigDigit, DoubleBigDigit, ZERO_BIG_DIGIT}; - -use self::algorithms::{mac_with_carry, mul3, scalar_mul, div_rem, div_rem_digit}; -use self::algorithms::{__add2, add2, sub2, sub2rev}; -use self::algorithms::{biguint_shl, biguint_shr}; -use self::algorithms::{cmp_slice, fls, ilog2}; -use self::monty::monty_modpow; - -use UsizePromotion; - -use ParseBigIntError; - -#[cfg(test)] -#[path = "tests/biguint.rs"] -mod biguint_tests; - -/// A big unsigned integer type. -/// -/// A `BigUint`-typed value `BigUint { data: vec!(a, b, c) }` represents a number -/// `(a + b * big_digit::BASE + c * big_digit::BASE^2)`. -#[derive(Clone, Debug, Hash)] -#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] -pub struct BigUint { - data: Vec, -} - -impl PartialEq for BigUint { - #[inline] - fn eq(&self, other: &BigUint) -> bool { - match self.cmp(other) { - Equal => true, - _ => false, - } - } -} -impl Eq for BigUint {} - -impl PartialOrd for BigUint { - #[inline] - fn partial_cmp(&self, other: &BigUint) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for BigUint { - #[inline] - fn cmp(&self, other: &BigUint) -> Ordering { - cmp_slice(&self.data[..], &other.data[..]) - } -} - -impl Default for BigUint { - #[inline] - fn default() -> BigUint { - Zero::zero() - } -} - -impl fmt::Display for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "", &self.to_str_radix(10)) - } -} - -impl fmt::LowerHex for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "0x", &self.to_str_radix(16)) - } -} - -impl fmt::UpperHex for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "0x", &self.to_str_radix(16).to_ascii_uppercase()) - } -} - -impl fmt::Binary for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "0b", &self.to_str_radix(2)) - } -} - -impl fmt::Octal for BigUint { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "0o", &self.to_str_radix(8)) - } -} - -impl FromStr for BigUint { - type Err = ParseBigIntError; - - #[inline] - fn from_str(s: &str) -> Result { - BigUint::from_str_radix(s, 10) - } -} - -// Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides -// BigDigit::BITS -fn from_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { - debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0); - debug_assert!(v.iter().all(|&c| (c as BigDigit) < (1 << bits))); - - let digits_per_big_digit = big_digit::BITS / bits; - - let data = v.chunks(digits_per_big_digit) - .map(|chunk| { - chunk.iter().rev().fold(0, |acc, &c| (acc << bits) | c as BigDigit) - }) - .collect(); - - BigUint::new(data) -} - -// Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide -// BigDigit::BITS -fn from_inexact_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { - debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0); - debug_assert!(v.iter().all(|&c| (c as BigDigit) < (1 << bits))); - - let big_digits = (v.len() * bits + big_digit::BITS - 1) / big_digit::BITS; - let mut data = Vec::with_capacity(big_digits); - - let mut d = 0; - let mut dbits = 0; // number of bits we currently have in d - - // walk v accumululating bits in d; whenever we accumulate big_digit::BITS in d, spit out a - // big_digit: - for &c in v { - d |= (c as BigDigit) << dbits; - dbits += bits; - - if dbits >= big_digit::BITS { - data.push(d); - dbits -= big_digit::BITS; - // if dbits was > big_digit::BITS, we dropped some of the bits in c (they couldn't fit - // in d) - grab the bits we lost here: - d = (c as BigDigit) >> (bits - dbits); - } - } - - if dbits > 0 { - debug_assert!(dbits < big_digit::BITS); - data.push(d as BigDigit); - } - - BigUint::new(data) -} - -// Read little-endian radix digits -fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { - debug_assert!(!v.is_empty() && !radix.is_power_of_two()); - debug_assert!(v.iter().all(|&c| (c as u32) < radix)); - - // Estimate how big the result will be, so we can pre-allocate it. - let bits = (radix as f64).log2() * v.len() as f64; - let big_digits = (bits / big_digit::BITS as f64).ceil(); - let mut data = Vec::with_capacity(big_digits as usize); - - let (base, power) = get_radix_base(radix); - let radix = radix as BigDigit; - - let r = v.len() % power; - let i = if r == 0 { - power - } else { - r - }; - let (head, tail) = v.split_at(i); - - let first = head.iter().fold(0, |acc, &d| acc * radix + d as BigDigit); - data.push(first); - - debug_assert!(tail.len() % power == 0); - for chunk in tail.chunks(power) { - if data.last() != Some(&0) { - data.push(0); - } - - let mut carry = 0; - for d in data.iter_mut() { - *d = mac_with_carry(0, *d, base, &mut carry); - } - debug_assert!(carry == 0); - - let n = chunk.iter().fold(0, |acc, &d| acc * radix + d as BigDigit); - add2(&mut data, &[n]); - } - - BigUint::new(data) -} - -impl Num for BigUint { - type FromStrRadixErr = ParseBigIntError; - - /// Creates and initializes a `BigUint`. - fn from_str_radix(s: &str, radix: u32) -> Result { - assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); - let mut s = s; - if s.starts_with('+') { - let tail = &s[1..]; - if !tail.starts_with('+') { - s = tail - } - } - - if s.is_empty() { - // create ParseIntError::Empty - let e = u64::from_str_radix(s, radix).unwrap_err(); - return Err(e.into()); - } - - if s.starts_with('_') { - // Must lead with a real digit! - // create ParseIntError::InvalidDigit - let e = u64::from_str_radix(s, radix).unwrap_err(); - return Err(e.into()); - } - - // First normalize all characters to plain digit values - let mut v = Vec::with_capacity(s.len()); - for b in s.bytes() { - let d = match b { - b'0'...b'9' => b - b'0', - b'a'...b'z' => b - b'a' + 10, - b'A'...b'Z' => b - b'A' + 10, - b'_' => continue, - _ => u8::MAX, - }; - if d < radix as u8 { - v.push(d); - } else { - // create ParseIntError::InvalidDigit - // Include the previous character for context. - let i = cmp::max(v.len(), 1) - 1; - let e = u64::from_str_radix(&s[i..], radix).unwrap_err(); - return Err(e.into()); - } - } - - let res = if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of multiplication - let bits = ilog2(radix); - v.reverse(); - if big_digit::BITS % bits == 0 { - from_bitwise_digits_le(&v, bits) - } else { - from_inexact_bitwise_digits_le(&v, bits) - } - } else { - from_radix_digits_be(&v, radix) - }; - Ok(res) - } -} - -forward_all_binop_to_val_ref_commutative!(impl BitAnd for BigUint, bitand); -forward_val_assign!(impl BitAndAssign for BigUint, bitand_assign); - -impl<'a> BitAnd<&'a BigUint> for BigUint { - type Output = BigUint; - - #[inline] - fn bitand(mut self, other: &BigUint) -> BigUint { - self &= other; - self - } -} -impl<'a> BitAndAssign<&'a BigUint> for BigUint { - #[inline] - fn bitand_assign(&mut self, other: &BigUint) { - for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { - *ai &= bi; - } - self.data.truncate(other.data.len()); - self.normalize(); - } -} - -forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor); -forward_val_assign!(impl BitOrAssign for BigUint, bitor_assign); - -impl<'a> BitOr<&'a BigUint> for BigUint { - type Output = BigUint; - - fn bitor(mut self, other: &BigUint) -> BigUint { - self |= other; - self - } -} -impl<'a> BitOrAssign<&'a BigUint> for BigUint { - #[inline] - fn bitor_assign(&mut self, other: &BigUint) { - for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { - *ai |= bi; - } - if other.data.len() > self.data.len() { - let extra = &other.data[self.data.len()..]; - self.data.extend(extra.iter().cloned()); - } - } -} - -forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor); -forward_val_assign!(impl BitXorAssign for BigUint, bitxor_assign); - -impl<'a> BitXor<&'a BigUint> for BigUint { - type Output = BigUint; - - fn bitxor(mut self, other: &BigUint) -> BigUint { - self ^= other; - self - } -} -impl<'a> BitXorAssign<&'a BigUint> for BigUint { - #[inline] - fn bitxor_assign(&mut self, other: &BigUint) { - for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { - *ai ^= bi; - } - if other.data.len() > self.data.len() { - let extra = &other.data[self.data.len()..]; - self.data.extend(extra.iter().cloned()); - } - self.normalize(); - } -} - -impl Shl for BigUint { - type Output = BigUint; - - #[inline] - fn shl(self, rhs: usize) -> BigUint { - biguint_shl(Cow::Owned(self), rhs) - } -} -impl<'a> Shl for &'a BigUint { - type Output = BigUint; - - #[inline] - fn shl(self, rhs: usize) -> BigUint { - biguint_shl(Cow::Borrowed(self), rhs) - } -} - -impl ShlAssign for BigUint { - #[inline] - fn shl_assign(&mut self, rhs: usize) { - *self = biguint_shl(Cow::Borrowed(&*self), rhs); - } -} - -impl Shr for BigUint { - type Output = BigUint; - - #[inline] - fn shr(self, rhs: usize) -> BigUint { - biguint_shr(Cow::Owned(self), rhs) - } -} -impl<'a> Shr for &'a BigUint { - type Output = BigUint; - - #[inline] - fn shr(self, rhs: usize) -> BigUint { - biguint_shr(Cow::Borrowed(self), rhs) - } -} - -impl ShrAssign for BigUint { - #[inline] - fn shr_assign(&mut self, rhs: usize) { - *self = biguint_shr(Cow::Borrowed(&*self), rhs); - } -} - -impl Zero for BigUint { - #[inline] - fn zero() -> BigUint { - BigUint::new(Vec::new()) - } - - #[inline] - fn is_zero(&self) -> bool { - self.data.is_empty() - } -} - -impl One for BigUint { - #[inline] - fn one() -> BigUint { - BigUint::new(vec![1]) - } -} - -impl Unsigned for BigUint {} - -forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); -forward_val_assign!(impl AddAssign for BigUint, add_assign); - -impl<'a> Add<&'a BigUint> for BigUint { - type Output = BigUint; - - fn add(mut self, other: &BigUint) -> BigUint { - self += other; - self - } -} -impl<'a> AddAssign<&'a BigUint> for BigUint { - #[inline] - fn add_assign(&mut self, other: &BigUint) { - if self.data.len() < other.data.len() { - let extra = other.data.len() - self.data.len(); - self.data.extend(repeat(0).take(extra)); - } - - let carry = __add2(&mut self.data[..], &other.data[..]); - if carry != 0 { - self.data.push(carry); - } - } -} - -promote_unsigned_scalars!(impl Add for BigUint, add); -promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); - -impl Add for BigUint { - type Output = BigUint; - - #[inline] - fn add(mut self, other: BigDigit) -> BigUint { - self += other; - self - } -} -impl AddAssign for BigUint { - #[inline] - fn add_assign(&mut self, other: BigDigit) { - if other != 0 { - if self.data.len() == 0 { - self.data.push(0); - } - - let carry = __add2(&mut self.data, &[other]); - if carry != 0 { - self.data.push(carry); - } - } - } -} - -impl Add for BigUint { - type Output = BigUint; - - #[inline] - fn add(mut self, other: DoubleBigDigit) -> BigUint { - self += other; - self - } -} -impl AddAssign for BigUint { - #[inline] - fn add_assign(&mut self, other: DoubleBigDigit) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - if hi == 0 { - *self += lo; - } else { - while self.data.len() < 2 { - self.data.push(0); - } - - let carry = __add2(&mut self.data, &[lo, hi]); - if carry != 0 { - self.data.push(carry); - } - } - } -} - -forward_val_val_binop!(impl Sub for BigUint, sub); -forward_ref_ref_binop!(impl Sub for BigUint, sub); -forward_val_assign!(impl SubAssign for BigUint, sub_assign); - -impl<'a> Sub<&'a BigUint> for BigUint { - type Output = BigUint; - - fn sub(mut self, other: &BigUint) -> BigUint { - self -= other; - self - } -} -impl<'a> SubAssign<&'a BigUint> for BigUint { - fn sub_assign(&mut self, other: &'a BigUint) { - sub2(&mut self.data[..], &other.data[..]); - self.normalize(); - } -} - -impl<'a> Sub for &'a BigUint { - type Output = BigUint; - - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.len() < self.data.len() { - let extra = self.data.len() - other.data.len(); - other.data.extend(repeat(0).take(extra)); - } - - sub2rev(&self.data[..], &mut other.data[..]); - other.normalized() - } -} - -promote_unsigned_scalars!(impl Sub for BigUint, sub); -promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign); -forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); -forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); - -impl Sub for BigUint { - type Output = BigUint; - - #[inline] - fn sub(mut self, other: BigDigit) -> BigUint { - self -= other; - self - } -} -impl SubAssign for BigUint { - fn sub_assign(&mut self, other: BigDigit) { - sub2(&mut self.data[..], &[other]); - self.normalize(); - } -} - -impl Sub for BigDigit { - type Output = BigUint; - - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - if other.data.len() == 0 { - other.data.push(0); - } - - sub2rev(&[self], &mut other.data[..]); - other.normalized() - } -} - -impl Sub for BigUint { - type Output = BigUint; - - #[inline] - fn sub(mut self, other: DoubleBigDigit) -> BigUint { - self -= other; - self - } -} -impl SubAssign for BigUint { - fn sub_assign(&mut self, other: DoubleBigDigit) { - let (hi, lo) = big_digit::from_doublebigdigit(other); - sub2(&mut self.data[..], &[lo, hi]); - self.normalize(); - } -} - -impl Sub for DoubleBigDigit { - type Output = BigUint; - - #[inline] - fn sub(self, mut other: BigUint) -> BigUint { - while other.data.len() < 2 { - other.data.push(0); - } - - let (hi, lo) = big_digit::from_doublebigdigit(self); - sub2rev(&[lo, hi], &mut other.data[..]); - other.normalized() - } -} - -forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul); -forward_val_assign!(impl MulAssign for BigUint, mul_assign); - -impl<'a, 'b> Mul<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn mul(self, other: &BigUint) -> BigUint { - mul3(&self.data[..], &other.data[..]) - } -} -impl<'a> MulAssign<&'a BigUint> for BigUint { - #[inline] - fn mul_assign(&mut self, other: &'a BigUint) { - *self = &*self * other - } -} - -promote_unsigned_scalars!(impl Mul for BigUint, mul); -promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); - -impl Mul for BigUint { - type Output = BigUint; - - #[inline] - fn mul(mut self, other: BigDigit) -> BigUint { - self *= other; - self - } -} -impl MulAssign for BigUint { - #[inline] - fn mul_assign(&mut self, other: BigDigit) { - if other == 0 { - self.data.clear(); - } else { - let carry = scalar_mul(&mut self.data[..], other); - if carry != 0 { - self.data.push(carry); - } - } - } -} - -impl Mul for BigUint { - type Output = BigUint; - - #[inline] - fn mul(mut self, other: DoubleBigDigit) -> BigUint { - self *= other; - self - } -} -impl MulAssign for BigUint { - #[inline] - fn mul_assign(&mut self, other: DoubleBigDigit) { - if other == 0 { - self.data.clear(); - } else if other <= BigDigit::max_value() as DoubleBigDigit { - *self *= other as BigDigit - } else { - let (hi, lo) = big_digit::from_doublebigdigit(other); - *self = mul3(&self.data[..], &[lo, hi]) - } - } -} - -forward_all_binop_to_ref_ref!(impl Div for BigUint, div); -forward_val_assign!(impl DivAssign for BigUint, div_assign); - -impl<'a, 'b> Div<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: &BigUint) -> BigUint { - let (q, _) = self.div_rem(other); - q - } -} -impl<'a> DivAssign<&'a BigUint> for BigUint { - #[inline] - fn div_assign(&mut self, other: &'a BigUint) { - *self = &*self / other; - } -} - -promote_unsigned_scalars!(impl Div for BigUint, div); -promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign); -forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); -forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); - -impl Div for BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: BigDigit) -> BigUint { - let (q, _) = div_rem_digit(self, other); - q - } -} -impl DivAssign for BigUint { - #[inline] - fn div_assign(&mut self, other: BigDigit) { - *self = &*self / other; - } -} - -impl Div for BigDigit { - type Output = BigUint; - - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!(), - 1 => From::from(self / other.data[0]), - _ => Zero::zero(), - } - } -} - -impl Div for BigUint { - type Output = BigUint; - - #[inline] - fn div(self, other: DoubleBigDigit) -> BigUint { - let (q, _) = self.div_rem(&From::from(other)); - q - } -} -impl DivAssign for BigUint { - #[inline] - fn div_assign(&mut self, other: DoubleBigDigit) { - *self = &*self / other; - } -} - -impl Div for DoubleBigDigit { - type Output = BigUint; - - #[inline] - fn div(self, other: BigUint) -> BigUint { - match other.data.len() { - 0 => panic!(), - 1 => From::from(self / other.data[0] as u64), - 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), - _ => Zero::zero(), - } - } -} - -forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem); -forward_val_assign!(impl RemAssign for BigUint, rem_assign); - -impl<'a, 'b> Rem<&'b BigUint> for &'a BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: &BigUint) -> BigUint { - let (_, r) = self.div_rem(other); - r - } -} -impl<'a> RemAssign<&'a BigUint> for BigUint { - #[inline] - fn rem_assign(&mut self, other: &BigUint) { - *self = &*self % other; - } -} - -promote_unsigned_scalars!(impl Rem for BigUint, rem); -promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign); -forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); -forward_all_scalar_binop_to_val_val!(impl Rem for BigUint, rem); - -impl Rem for BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: BigDigit) -> BigUint { - let (_, r) = div_rem_digit(self, other); - From::from(r) - } -} -impl RemAssign for BigUint { - #[inline] - fn rem_assign(&mut self, other: BigDigit) { - *self = &*self % other; - } -} - -impl Rem for BigDigit { - type Output = BigUint; - - #[inline] - fn rem(mut self, other: BigUint) -> BigUint { - self %= other; - From::from(self) - } -} - -macro_rules! impl_rem_assign_scalar { - ($scalar:ty, $to_scalar:ident) => { - forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign); - impl<'a> RemAssign<&'a BigUint> for $scalar { - #[inline] - fn rem_assign(&mut self, other: &BigUint) { - *self = match other.$to_scalar() { - None => *self, - Some(0) => panic!(), - Some(v) => *self % v - }; - } - } - } -} -// we can scalar %= BigUint for any scalar, including signed types -impl_rem_assign_scalar!(usize, to_usize); -impl_rem_assign_scalar!(u64, to_u64); -impl_rem_assign_scalar!(u32, to_u32); -impl_rem_assign_scalar!(u16, to_u16); -impl_rem_assign_scalar!(u8, to_u8); -impl_rem_assign_scalar!(isize, to_isize); -impl_rem_assign_scalar!(i64, to_i64); -impl_rem_assign_scalar!(i32, to_i32); -impl_rem_assign_scalar!(i16, to_i16); -impl_rem_assign_scalar!(i8, to_i8); - -impl Rem for BigUint { - type Output = BigUint; - - #[inline] - fn rem(self, other: DoubleBigDigit) -> BigUint { - let (_, r) = self.div_rem(&From::from(other)); - r - } -} -impl RemAssign for BigUint { - #[inline] - fn rem_assign(&mut self, other: DoubleBigDigit) { - *self = &*self % other; - } -} - -impl Rem for DoubleBigDigit { - type Output = BigUint; - - #[inline] - fn rem(mut self, other: BigUint) -> BigUint { - self %= other; - From::from(self) - } -} - -impl Neg for BigUint { - type Output = BigUint; - - #[inline] - fn neg(self) -> BigUint { - panic!() - } -} - -impl<'a> Neg for &'a BigUint { - type Output = BigUint; - - #[inline] - fn neg(self) -> BigUint { - panic!() - } -} - -impl CheckedAdd for BigUint { - #[inline] - fn checked_add(&self, v: &BigUint) -> Option { - return Some(self.add(v)); - } -} - -impl CheckedSub for BigUint { - #[inline] - fn checked_sub(&self, v: &BigUint) -> Option { - match self.cmp(v) { - Less => None, - Equal => Some(Zero::zero()), - Greater => Some(self.sub(v)), - } - } -} - -impl CheckedMul for BigUint { - #[inline] - fn checked_mul(&self, v: &BigUint) -> Option { - return Some(self.mul(v)); - } -} - -impl CheckedDiv for BigUint { - #[inline] - fn checked_div(&self, v: &BigUint) -> Option { - if v.is_zero() { - return None; - } - return Some(self.div(v)); - } -} - -impl Integer for BigUint { - #[inline] - fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { - div_rem(self, other) - } - - #[inline] - fn div_floor(&self, other: &BigUint) -> BigUint { - let (d, _) = div_rem(self, other); - d - } - - #[inline] - fn mod_floor(&self, other: &BigUint) -> BigUint { - let (_, m) = div_rem(self, other); - m - } - - #[inline] - fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) { - div_rem(self, other) - } - - /// 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 / self.gcd(other) * other - } - - /// Deprecated, use `is_multiple_of` instead. - #[inline] - fn divides(&self, other: &BigUint) -> bool { - self.is_multiple_of(other) - } - - /// Returns `true` if the number is a multiple of `other`. - #[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. - match self.data.first() { - Some(x) => x.is_even(), - None => true, - } - } - - /// Returns `true` if the number is not divisible by `2`. - #[inline] - fn is_odd(&self) -> bool { - !self.is_even() - } -} - -fn high_bits_to_u64(v: &BigUint) -> u64 { - match v.data.len() { - 0 => 0, - 1 => v.data[0] as u64, - _ => { - let mut bits = v.bits(); - let mut ret = 0u64; - let mut ret_bits = 0; - - for d in v.data.iter().rev() { - let digit_bits = (bits - 1) % big_digit::BITS + 1; - let bits_want = cmp::min(64 - ret_bits, digit_bits); - - if bits_want != 64 { - ret <<= bits_want; - } - ret |= *d as u64 >> (digit_bits - bits_want); - ret_bits += bits_want; - bits -= bits_want; - - if ret_bits == 64 { - break; - } - } - - ret - } - } -} - -impl ToPrimitive for BigUint { - #[inline] - fn to_i64(&self) -> Option { - 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 - } - }) - } - - #[inline] - fn to_u64(&self) -> Option { - let mut ret: u64 = 0; - let mut bits = 0; - - for i in self.data.iter() { - if bits >= 64 { - return None; - } - - ret += (*i as u64) << bits; - bits += big_digit::BITS; - } - - Some(ret) - } - - #[inline] - fn to_f32(&self) -> Option { - let mantissa = high_bits_to_u64(self); - let exponent = self.bits() - fls(mantissa); - - if exponent > f32::MAX_EXP as usize { - None - } else { - let ret = (mantissa as f32) * 2.0f32.powi(exponent as i32); - if ret.is_infinite() { - None - } else { - Some(ret) - } - } - } - - #[inline] - fn to_f64(&self) -> Option { - let mantissa = high_bits_to_u64(self); - let exponent = self.bits() - fls(mantissa); - - if exponent > f64::MAX_EXP as usize { - None - } else { - let ret = (mantissa as f64) * 2.0f64.powi(exponent as i32); - if ret.is_infinite() { - None - } else { - Some(ret) - } - } - } -} - -impl FromPrimitive for BigUint { - #[inline] - fn from_i64(n: i64) -> Option { - if n >= 0 { - Some(BigUint::from(n as u64)) - } else { - None - } - } - - #[inline] - fn from_u64(n: u64) -> Option { - Some(BigUint::from(n)) - } - - #[inline] - fn from_f64(mut n: f64) -> Option { - // handle NAN, INFINITY, NEG_INFINITY - if !n.is_finite() { - return None; - } - - // match the rounding of casting from float to int - n = n.trunc(); - - // handle 0.x, -0.x - if n.is_zero() { - return Some(BigUint::zero()); - } - - let (mantissa, exponent, sign) = Float::integer_decode(n); - - if sign == -1 { - return None; - } - - let mut ret = BigUint::from(mantissa); - if exponent > 0 { - ret = ret << exponent as usize; - } else if exponent < 0 { - ret = ret >> (-exponent) as usize; - } - Some(ret) - } -} - -impl From for BigUint { - #[inline] - fn from(mut n: u64) -> Self { - let mut ret: BigUint = Zero::zero(); - - while n != 0 { - ret.data.push(n as BigDigit); - // don't overflow if BITS is 64: - n = (n >> 1) >> (big_digit::BITS - 1); - } - - ret - } -} - -macro_rules! impl_biguint_from_uint { - ($T:ty) => { - impl From<$T> for BigUint { - #[inline] - fn from(n: $T) -> Self { - BigUint::from(n as u64) - } - } - } -} - -impl_biguint_from_uint!(u8); -impl_biguint_from_uint!(u16); -impl_biguint_from_uint!(u32); -impl_biguint_from_uint!(usize); - -/// 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; -} - -impl ToBigUint for BigUint { - #[inline] - fn to_biguint(&self) -> Option { - Some(self.clone()) - } -} - -macro_rules! impl_to_biguint { - ($T:ty, $from_ty:path) => { - impl ToBigUint for $T { - #[inline] - fn to_biguint(&self) -> Option { - $from_ty(*self) - } - } - } -} - -impl_to_biguint!(isize, FromPrimitive::from_isize); -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!(usize, FromPrimitive::from_usize); -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_to_biguint!(f32, FromPrimitive::from_f32); -impl_to_biguint!(f64, FromPrimitive::from_f64); - -// Extract bitwise digits that evenly divide BigDigit -fn to_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { - debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0); - - let last_i = u.data.len() - 1; - let mask: BigDigit = (1 << bits) - 1; - let digits_per_big_digit = big_digit::BITS / bits; - let digits = (u.bits() + bits - 1) / bits; - let mut res = Vec::with_capacity(digits); - - for mut r in u.data[..last_i].iter().cloned() { - for _ in 0..digits_per_big_digit { - res.push((r & mask) as u8); - r >>= bits; - } - } - - let mut r = u.data[last_i]; - while r != 0 { - res.push((r & mask) as u8); - r >>= bits; - } - - res -} - -// Extract bitwise digits that don't evenly divide BigDigit -fn to_inexact_bitwise_digits_le(u: &BigUint, bits: usize) -> Vec { - debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0); - - let mask: BigDigit = (1 << bits) - 1; - let digits = (u.bits() + bits - 1) / bits; - let mut res = Vec::with_capacity(digits); - - let mut r = 0; - let mut rbits = 0; - - for c in &u.data { - r |= *c << rbits; - rbits += big_digit::BITS; - - while rbits >= bits { - res.push((r & mask) as u8); - r >>= bits; - - // r had more bits than it could fit - grab the bits we lost - if rbits > big_digit::BITS { - r = *c >> (big_digit::BITS - (rbits - bits)); - } - - rbits -= bits; - } - } - - if rbits != 0 { - res.push(r as u8); - } - - while let Some(&0) = res.last() { - res.pop(); - } - - res -} - -// Extract little-endian radix digits -#[inline(always)] // forced inline to get const-prop for radix=10 -fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { - debug_assert!(!u.is_zero() && !radix.is_power_of_two()); - - // Estimate how big the result will be, so we can pre-allocate it. - let radix_digits = ((u.bits() as f64) / (radix as f64).log2()).ceil(); - let mut res = Vec::with_capacity(radix_digits as usize); - let mut digits = u.clone(); - - let (base, power) = get_radix_base(radix); - let radix = radix as BigDigit; - - while digits.data.len() > 1 { - let (q, mut r) = div_rem_digit(digits, base); - for _ in 0..power { - res.push((r % radix) as u8); - r /= radix; - } - digits = q; - } - - let mut r = digits.data[0]; - while r != 0 { - res.push((r % radix) as u8); - r /= radix; - } - - res -} - -pub fn to_radix_le(u: &BigUint, radix: u32) -> Vec { - if u.is_zero() { - vec![0] - } else if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of division - let bits = ilog2(radix); - if big_digit::BITS % bits == 0 { - to_bitwise_digits_le(u, bits) - } else { - to_inexact_bitwise_digits_le(u, bits) - } - } else if radix == 10 { - // 10 is so common that it's worth separating out for const-propagation. - // Optimizers can often turn constant division into a faster multiplication. - to_radix_digits_le(u, 10) - } else { - to_radix_digits_le(u, radix) - } -} - -pub fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { - assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); - - if u.is_zero() { - return vec![b'0']; - } - - let mut res = to_radix_le(u, radix); - - // Now convert everything to ASCII digits. - for r in &mut res { - debug_assert!((*r as u32) < radix); - if *r < 10 { - *r += b'0'; - } else { - *r += b'a' - 10; - } - } - res -} - -impl BigUint { - /// Creates and initializes a `BigUint`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn new(digits: Vec) -> BigUint { - BigUint { data: digits }.normalized() - } - - /// Creates and initializes a `BigUint`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn from_slice(slice: &[BigDigit]) -> BigUint { - BigUint::new(slice.to_vec()) - } - - /// Assign a value to a `BigUint`. - /// - /// The digits are in little-endian base 232. - #[inline] - pub fn assign_from_slice(&mut self, slice: &[BigDigit]) { - self.data.resize(slice.len(), 0); - self.data.clone_from_slice(slice); - self.normalize(); - } - - /// Creates and initializes a `BigUint`. - /// - /// The bytes are in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from_bytes_be(b"A"), - /// BigUint::parse_bytes(b"65", 10).unwrap()); - /// assert_eq!(BigUint::from_bytes_be(b"AA"), - /// BigUint::parse_bytes(b"16705", 10).unwrap()); - /// assert_eq!(BigUint::from_bytes_be(b"AB"), - /// BigUint::parse_bytes(b"16706", 10).unwrap()); - /// assert_eq!(BigUint::from_bytes_be(b"Hello world!"), - /// BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); - /// ``` - #[inline] - pub fn from_bytes_be(bytes: &[u8]) -> BigUint { - if bytes.is_empty() { - Zero::zero() - } else { - let mut v = bytes.to_vec(); - v.reverse(); - BigUint::from_bytes_le(&*v) - } - } - - /// Creates and initializes a `BigUint`. - /// - /// The bytes are in little-endian byte order. - #[inline] - pub fn from_bytes_le(bytes: &[u8]) -> BigUint { - if bytes.is_empty() { - Zero::zero() - } else { - from_bitwise_digits_le(bytes, 8) - } - } - - /// Creates and initializes a `BigUint`. The input slice must contain - /// ascii/utf8 characters in [0-9a-zA-Z]. - /// `radix` must be in the range `2...36`. - /// - /// The function `from_str_radix` from the `Num` trait provides the same logic - /// for `&str` buffers. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigUint, ToBigUint}; - /// - /// assert_eq!(BigUint::parse_bytes(b"1234", 10), ToBigUint::to_biguint(&1234)); - /// assert_eq!(BigUint::parse_bytes(b"ABCD", 16), ToBigUint::to_biguint(&0xABCD)); - /// assert_eq!(BigUint::parse_bytes(b"G", 16), None); - /// ``` - #[inline] - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { - str::from_utf8(buf).ok().and_then(|s| BigUint::from_str_radix(s, radix).ok()) - } - - /// Creates and initializes a `BigUint`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in big-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigUint}; - /// - /// let inbase190 = &[15, 33, 125, 12, 14]; - /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), inbase190); - /// ``` - pub fn from_radix_be(buf: &[u8], radix: u32) -> Option { - assert!(2 <= radix && radix <= 256, "The radix must be within 2...256"); - - if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { - return None; - } - - let res = if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of multiplication - let bits = ilog2(radix); - let mut v = Vec::from(buf); - v.reverse(); - if big_digit::BITS % bits == 0 { - from_bitwise_digits_le(&v, bits) - } else { - from_inexact_bitwise_digits_le(&v, bits) - } - } else { - from_radix_digits_be(buf, radix) - }; - - Some(res) - } - - /// Creates and initializes a `BigUint`. Each u8 of the input slice is - /// interpreted as one digit of the number - /// and must therefore be less than `radix`. - /// - /// The bytes are in little-endian byte order. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::{BigUint}; - /// - /// let inbase190 = &[14, 12, 125, 33, 15]; - /// let a = BigUint::from_radix_be(inbase190, 190).unwrap(); - /// assert_eq!(a.to_radix_be(190), inbase190); - /// ``` - pub fn from_radix_le(buf: &[u8], radix: u32) -> Option { - assert!(2 <= radix && radix <= 256, "The radix must be within 2...256"); - - if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { - return None; - } - - let res = if radix.is_power_of_two() { - // Powers of two can use bitwise masks and shifting instead of multiplication - let bits = ilog2(radix); - if big_digit::BITS % bits == 0 { - from_bitwise_digits_le(buf, bits) - } else { - from_inexact_bitwise_digits_le(buf, bits) - } - } else { - let mut v = Vec::from(buf); - v.reverse(); - from_radix_digits_be(&v, radix) - }; - - Some(res) - } - - - /// Returns the byte representation of the `BigUint` in big-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); - /// assert_eq!(i.to_bytes_be(), vec![4, 101]); - /// ``` - #[inline] - pub fn to_bytes_be(&self) -> Vec { - let mut v = self.to_bytes_le(); - v.reverse(); - v - } - - /// Returns the byte representation of the `BigUint` in little-endian byte order. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// let i = BigUint::parse_bytes(b"1125", 10).unwrap(); - /// assert_eq!(i.to_bytes_le(), vec![101, 4]); - /// ``` - #[inline] - pub fn to_bytes_le(&self) -> Vec { - if self.is_zero() { - vec![0] - } else { - to_bitwise_digits_le(self, 8) - } - } - - /// Returns the integer formatted as a string in the given radix. - /// `radix` must be in the range `2...36`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// let i = BigUint::parse_bytes(b"ff", 16).unwrap(); - /// assert_eq!(i.to_str_radix(16), "ff"); - /// ``` - #[inline] - pub fn to_str_radix(&self, radix: u32) -> String { - let mut v = to_str_radix_reversed(self, radix); - v.reverse(); - unsafe { String::from_utf8_unchecked(v) } - } - - /// Returns the integer in the requested base in big-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_be(159), - /// vec![2, 94, 27]); - /// // 0xFFFF = 65535 = 2*(159^2) + 94*159 + 27 - /// ``` - #[inline] - pub fn to_radix_be(&self, radix: u32) -> Vec { - let mut v = to_radix_le(self, radix); - v.reverse(); - v - } - - /// Returns the integer in the requested base in little-endian digit order. - /// The output is not given in a human readable alphabet but as a zero - /// based u8 number. - /// `radix` must be in the range `2...256`. - /// - /// # Examples - /// - /// ``` - /// use num_bigint::BigUint; - /// - /// assert_eq!(BigUint::from(0xFFFFu64).to_radix_le(159), - /// vec![27, 94, 2]); - /// // 0xFFFF = 65535 = 27 + 94*159 + 2*(159^2) - /// ``` - #[inline] - pub fn to_radix_le(&self, radix: u32) -> Vec { - to_radix_le(self, radix) - } - - /// Determines the fewest bits necessary to express the `BigUint`. - #[inline] - pub fn bits(&self) -> usize { - if self.is_zero() { - return 0; - } - let zeros = self.data.last().unwrap().leading_zeros(); - return self.data.len() * big_digit::BITS - zeros as usize; - } - - /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to - /// be nonzero. - #[inline] - fn normalize(&mut self) { - while let Some(&0) = self.data.last() { - self.data.pop(); - } - } - - /// Returns a normalized `BigUint`. - #[inline] - fn normalized(mut self) -> BigUint { - self.normalize(); - self - } - - /// Returns `(self ^ exponent) % modulus`. - pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { - assert!(!modulus.is_zero(), "divide by zero!"); - - // For an odd modulus, we can use Montgomery multiplication in base 2^32. - if modulus.is_odd() { - return monty_modpow(self, exponent, modulus); - } - - // Otherwise do basically the same as `num::pow`, but with a modulus. - let one = BigUint::one(); - if exponent.is_zero() { return one; } - - let mut base = self % modulus; - let mut exp = exponent.clone(); - while exp.is_even() { - base = &base * &base % modulus; - exp >>= 1; - } - if exp == one { return base } - - let mut acc = base.clone(); - while exp > one { - exp >>= 1; - base = &base * &base % modulus; - if exp.is_odd() { - acc = acc * &base % modulus; - } - } - acc - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for BigUint { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: serde::Serializer - { - self.data.serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl serde::Deserialize for BigUint { - fn deserialize(deserializer: &mut D) -> Result - where D: serde::Deserializer - { - let data = try!(Vec::deserialize(deserializer)); - Ok(BigUint { data: data }) - } -} - -/// Returns the greatest power of the radix <= big_digit::BASE -#[inline] -fn get_radix_base(radix: u32) -> (BigDigit, usize) { - debug_assert!(2 <= radix && radix <= 256, "The radix must be within 2...256"); - debug_assert!(!radix.is_power_of_two()); - - // To generate this table: - // for radix in 2u64..257 { - // let mut power = big_digit::BITS / fls(radix as u64); - // let mut base = radix.pow(power as u32); - // - // while let Some(b) = base.checked_mul(radix) { - // if b > big_digit::MAX { - // break; - // } - // base = b; - // power += 1; - // } - // - // println!("({:10}, {:2}), // {:2}", base, power, radix); - // } - // and - // for radix in 2u64..257 { - // let mut power = 64 / fls(radix as u64); - // let mut base = radix.pow(power as u32); - // - // while let Some(b) = base.checked_mul(radix) { - // base = b; - // power += 1; - // } - // - // println!("({:20}, {:2}), // {:2}", base, power, radix); - // } - match big_digit::BITS { - 32 => { - const BASES: [(u32, usize); 257] = [ - ( 0, 0), - ( 0, 0), - ( 0, 0), // 2 - (3486784401, 20), // 3 - ( 0, 0), // 4 - (1220703125, 13), // 5 - (2176782336, 12), // 6 - (1977326743, 11), // 7 - ( 0, 0), // 8 - (3486784401, 10), // 9 - (1000000000, 9), // 10 - (2357947691, 9), // 11 - ( 429981696, 8), // 12 - ( 815730721, 8), // 13 - (1475789056, 8), // 14 - (2562890625, 8), // 15 - ( 0, 0), // 16 - ( 410338673, 7), // 17 - ( 612220032, 7), // 18 - ( 893871739, 7), // 19 - (1280000000, 7), // 20 - (1801088541, 7), // 21 - (2494357888, 7), // 22 - (3404825447, 7), // 23 - ( 191102976, 6), // 24 - ( 244140625, 6), // 25 - ( 308915776, 6), // 26 - ( 387420489, 6), // 27 - ( 481890304, 6), // 28 - ( 594823321, 6), // 29 - ( 729000000, 6), // 30 - ( 887503681, 6), // 31 - ( 0, 0), // 32 - (1291467969, 6), // 33 - (1544804416, 6), // 34 - (1838265625, 6), // 35 - (2176782336, 6), // 36 - (2565726409, 6), // 37 - (3010936384, 6), // 38 - (3518743761, 6), // 39 - (4096000000, 6), // 40 - ( 115856201, 5), // 41 - ( 130691232, 5), // 42 - ( 147008443, 5), // 43 - ( 164916224, 5), // 44 - ( 184528125, 5), // 45 - ( 205962976, 5), // 46 - ( 229345007, 5), // 47 - ( 254803968, 5), // 48 - ( 282475249, 5), // 49 - ( 312500000, 5), // 50 - ( 345025251, 5), // 51 - ( 380204032, 5), // 52 - ( 418195493, 5), // 53 - ( 459165024, 5), // 54 - ( 503284375, 5), // 55 - ( 550731776, 5), // 56 - ( 601692057, 5), // 57 - ( 656356768, 5), // 58 - ( 714924299, 5), // 59 - ( 777600000, 5), // 60 - ( 844596301, 5), // 61 - ( 916132832, 5), // 62 - ( 992436543, 5), // 63 - ( 0, 0), // 64 - (1160290625, 5), // 65 - (1252332576, 5), // 66 - (1350125107, 5), // 67 - (1453933568, 5), // 68 - (1564031349, 5), // 69 - (1680700000, 5), // 70 - (1804229351, 5), // 71 - (1934917632, 5), // 72 - (2073071593, 5), // 73 - (2219006624, 5), // 74 - (2373046875, 5), // 75 - (2535525376, 5), // 76 - (2706784157, 5), // 77 - (2887174368, 5), // 78 - (3077056399, 5), // 79 - (3276800000, 5), // 80 - (3486784401, 5), // 81 - (3707398432, 5), // 82 - (3939040643, 5), // 83 - (4182119424, 5), // 84 - ( 52200625, 4), // 85 - ( 54700816, 4), // 86 - ( 57289761, 4), // 87 - ( 59969536, 4), // 88 - ( 62742241, 4), // 89 - ( 65610000, 4), // 90 - ( 68574961, 4), // 91 - ( 71639296, 4), // 92 - ( 74805201, 4), // 93 - ( 78074896, 4), // 94 - ( 81450625, 4), // 95 - ( 84934656, 4), // 96 - ( 88529281, 4), // 97 - ( 92236816, 4), // 98 - ( 96059601, 4), // 99 - ( 100000000, 4), // 100 - ( 104060401, 4), // 101 - ( 108243216, 4), // 102 - ( 112550881, 4), // 103 - ( 116985856, 4), // 104 - ( 121550625, 4), // 105 - ( 126247696, 4), // 106 - ( 131079601, 4), // 107 - ( 136048896, 4), // 108 - ( 141158161, 4), // 109 - ( 146410000, 4), // 110 - ( 151807041, 4), // 111 - ( 157351936, 4), // 112 - ( 163047361, 4), // 113 - ( 168896016, 4), // 114 - ( 174900625, 4), // 115 - ( 181063936, 4), // 116 - ( 187388721, 4), // 117 - ( 193877776, 4), // 118 - ( 200533921, 4), // 119 - ( 207360000, 4), // 120 - ( 214358881, 4), // 121 - ( 221533456, 4), // 122 - ( 228886641, 4), // 123 - ( 236421376, 4), // 124 - ( 244140625, 4), // 125 - ( 252047376, 4), // 126 - ( 260144641, 4), // 127 - ( 0, 0), // 128 - ( 276922881, 4), // 129 - ( 285610000, 4), // 130 - ( 294499921, 4), // 131 - ( 303595776, 4), // 132 - ( 312900721, 4), // 133 - ( 322417936, 4), // 134 - ( 332150625, 4), // 135 - ( 342102016, 4), // 136 - ( 352275361, 4), // 137 - ( 362673936, 4), // 138 - ( 373301041, 4), // 139 - ( 384160000, 4), // 140 - ( 395254161, 4), // 141 - ( 406586896, 4), // 142 - ( 418161601, 4), // 143 - ( 429981696, 4), // 144 - ( 442050625, 4), // 145 - ( 454371856, 4), // 146 - ( 466948881, 4), // 147 - ( 479785216, 4), // 148 - ( 492884401, 4), // 149 - ( 506250000, 4), // 150 - ( 519885601, 4), // 151 - ( 533794816, 4), // 152 - ( 547981281, 4), // 153 - ( 562448656, 4), // 154 - ( 577200625, 4), // 155 - ( 592240896, 4), // 156 - ( 607573201, 4), // 157 - ( 623201296, 4), // 158 - ( 639128961, 4), // 159 - ( 655360000, 4), // 160 - ( 671898241, 4), // 161 - ( 688747536, 4), // 162 - ( 705911761, 4), // 163 - ( 723394816, 4), // 164 - ( 741200625, 4), // 165 - ( 759333136, 4), // 166 - ( 777796321, 4), // 167 - ( 796594176, 4), // 168 - ( 815730721, 4), // 169 - ( 835210000, 4), // 170 - ( 855036081, 4), // 171 - ( 875213056, 4), // 172 - ( 895745041, 4), // 173 - ( 916636176, 4), // 174 - ( 937890625, 4), // 175 - ( 959512576, 4), // 176 - ( 981506241, 4), // 177 - (1003875856, 4), // 178 - (1026625681, 4), // 179 - (1049760000, 4), // 180 - (1073283121, 4), // 181 - (1097199376, 4), // 182 - (1121513121, 4), // 183 - (1146228736, 4), // 184 - (1171350625, 4), // 185 - (1196883216, 4), // 186 - (1222830961, 4), // 187 - (1249198336, 4), // 188 - (1275989841, 4), // 189 - (1303210000, 4), // 190 - (1330863361, 4), // 191 - (1358954496, 4), // 192 - (1387488001, 4), // 193 - (1416468496, 4), // 194 - (1445900625, 4), // 195 - (1475789056, 4), // 196 - (1506138481, 4), // 197 - (1536953616, 4), // 198 - (1568239201, 4), // 199 - (1600000000, 4), // 200 - (1632240801, 4), // 201 - (1664966416, 4), // 202 - (1698181681, 4), // 203 - (1731891456, 4), // 204 - (1766100625, 4), // 205 - (1800814096, 4), // 206 - (1836036801, 4), // 207 - (1871773696, 4), // 208 - (1908029761, 4), // 209 - (1944810000, 4), // 210 - (1982119441, 4), // 211 - (2019963136, 4), // 212 - (2058346161, 4), // 213 - (2097273616, 4), // 214 - (2136750625, 4), // 215 - (2176782336, 4), // 216 - (2217373921, 4), // 217 - (2258530576, 4), // 218 - (2300257521, 4), // 219 - (2342560000, 4), // 220 - (2385443281, 4), // 221 - (2428912656, 4), // 222 - (2472973441, 4), // 223 - (2517630976, 4), // 224 - (2562890625, 4), // 225 - (2608757776, 4), // 226 - (2655237841, 4), // 227 - (2702336256, 4), // 228 - (2750058481, 4), // 229 - (2798410000, 4), // 230 - (2847396321, 4), // 231 - (2897022976, 4), // 232 - (2947295521, 4), // 233 - (2998219536, 4), // 234 - (3049800625, 4), // 235 - (3102044416, 4), // 236 - (3154956561, 4), // 237 - (3208542736, 4), // 238 - (3262808641, 4), // 239 - (3317760000, 4), // 240 - (3373402561, 4), // 241 - (3429742096, 4), // 242 - (3486784401, 4), // 243 - (3544535296, 4), // 244 - (3603000625, 4), // 245 - (3662186256, 4), // 246 - (3722098081, 4), // 247 - (3782742016, 4), // 248 - (3844124001, 4), // 249 - (3906250000, 4), // 250 - (3969126001, 4), // 251 - (4032758016, 4), // 252 - (4097152081, 4), // 253 - (4162314256, 4), // 254 - (4228250625, 4), // 255 - ( 0, 0), // 256 - ]; - - let (base, power) = BASES[radix as usize]; - (base as BigDigit, power) - } - 64 => { - const BASES: [(u64, usize); 257] = [ - ( 0, 0), - ( 0, 0), - ( 9223372036854775808, 63), // 2 - (12157665459056928801, 40), // 3 - ( 4611686018427387904, 31), // 4 - ( 7450580596923828125, 27), // 5 - ( 4738381338321616896, 24), // 6 - ( 3909821048582988049, 22), // 7 - ( 9223372036854775808, 21), // 8 - (12157665459056928801, 20), // 9 - (10000000000000000000, 19), // 10 - ( 5559917313492231481, 18), // 11 - ( 2218611106740436992, 17), // 12 - ( 8650415919381337933, 17), // 13 - ( 2177953337809371136, 16), // 14 - ( 6568408355712890625, 16), // 15 - ( 1152921504606846976, 15), // 16 - ( 2862423051509815793, 15), // 17 - ( 6746640616477458432, 15), // 18 - (15181127029874798299, 15), // 19 - ( 1638400000000000000, 14), // 20 - ( 3243919932521508681, 14), // 21 - ( 6221821273427820544, 14), // 22 - (11592836324538749809, 14), // 23 - ( 876488338465357824, 13), // 24 - ( 1490116119384765625, 13), // 25 - ( 2481152873203736576, 13), // 26 - ( 4052555153018976267, 13), // 27 - ( 6502111422497947648, 13), // 28 - (10260628712958602189, 13), // 29 - (15943230000000000000, 13), // 30 - ( 787662783788549761, 12), // 31 - ( 1152921504606846976, 12), // 32 - ( 1667889514952984961, 12), // 33 - ( 2386420683693101056, 12), // 34 - ( 3379220508056640625, 12), // 35 - ( 4738381338321616896, 12), // 36 - ( 6582952005840035281, 12), // 37 - ( 9065737908494995456, 12), // 38 - (12381557655576425121, 12), // 39 - (16777216000000000000, 12), // 40 - ( 550329031716248441, 11), // 41 - ( 717368321110468608, 11), // 42 - ( 929293739471222707, 11), // 43 - ( 1196683881290399744, 11), // 44 - ( 1532278301220703125, 11), // 45 - ( 1951354384207722496, 11), // 46 - ( 2472159215084012303, 11), // 47 - ( 3116402981210161152, 11), // 48 - ( 3909821048582988049, 11), // 49 - ( 4882812500000000000, 11), // 50 - ( 6071163615208263051, 11), // 51 - ( 7516865509350965248, 11), // 52 - ( 9269035929372191597, 11), // 53 - (11384956040305711104, 11), // 54 - (13931233916552734375, 11), // 55 - (16985107389382393856, 11), // 56 - ( 362033331456891249, 10), // 57 - ( 430804206899405824, 10), // 58 - ( 511116753300641401, 10), // 59 - ( 604661760000000000, 10), // 60 - ( 713342911662882601, 10), // 61 - ( 839299365868340224, 10), // 62 - ( 984930291881790849, 10), // 63 - ( 1152921504606846976, 10), // 64 - ( 1346274334462890625, 10), // 65 - ( 1568336880910795776, 10), // 66 - ( 1822837804551761449, 10), // 67 - ( 2113922820157210624, 10), // 68 - ( 2446194060654759801, 10), // 69 - ( 2824752490000000000, 10), // 70 - ( 3255243551009881201, 10), // 71 - ( 3743906242624487424, 10), // 72 - ( 4297625829703557649, 10), // 73 - ( 4923990397355877376, 10), // 74 - ( 5631351470947265625, 10), // 75 - ( 6428888932339941376, 10), // 76 - ( 7326680472586200649, 10), // 77 - ( 8335775831236199424, 10), // 78 - ( 9468276082626847201, 10), // 79 - (10737418240000000000, 10), // 80 - (12157665459056928801, 10), // 81 - (13744803133596058624, 10), // 82 - (15516041187205853449, 10), // 83 - (17490122876598091776, 10), // 84 - ( 231616946283203125, 9), // 85 - ( 257327417311663616, 9), // 86 - ( 285544154243029527, 9), // 87 - ( 316478381828866048, 9), // 88 - ( 350356403707485209, 9), // 89 - ( 387420489000000000, 9), // 90 - ( 427929800129788411, 9), // 91 - ( 472161363286556672, 9), // 92 - ( 520411082988487293, 9), // 93 - ( 572994802228616704, 9), // 94 - ( 630249409724609375, 9), // 95 - ( 692533995824480256, 9), // 96 - ( 760231058654565217, 9), // 97 - ( 833747762130149888, 9), // 98 - ( 913517247483640899, 9), // 99 - ( 1000000000000000000, 9), // 100 - ( 1093685272684360901, 9), // 101 - ( 1195092568622310912, 9), // 102 - ( 1304773183829244583, 9), // 103 - ( 1423311812421484544, 9), // 104 - ( 1551328215978515625, 9), // 105 - ( 1689478959002692096, 9), // 106 - ( 1838459212420154507, 9), // 107 - ( 1999004627104432128, 9), // 108 - ( 2171893279442309389, 9), // 109 - ( 2357947691000000000, 9), // 110 - ( 2558036924386500591, 9), // 111 - ( 2773078757450186752, 9), // 112 - ( 3004041937984268273, 9), // 113 - ( 3251948521156637184, 9), // 114 - ( 3517876291919921875, 9), // 115 - ( 3802961274698203136, 9), // 116 - ( 4108400332687853397, 9), // 117 - ( 4435453859151328768, 9), // 118 - ( 4785448563124474679, 9), // 119 - ( 5159780352000000000, 9), // 120 - ( 5559917313492231481, 9), // 121 - ( 5987402799531080192, 9), // 122 - ( 6443858614676334363, 9), // 123 - ( 6930988311686938624, 9), // 124 - ( 7450580596923828125, 9), // 125 - ( 8004512848309157376, 9), // 126 - ( 8594754748609397887, 9), // 127 - ( 9223372036854775808, 9), // 128 - ( 9892530380752880769, 9), // 129 - (10604499373000000000, 9), // 130 - (11361656654439817571, 9), // 131 - (12166492167065567232, 9), // 132 - (13021612539908538853, 9), // 133 - (13929745610903012864, 9), // 134 - (14893745087865234375, 9), // 135 - (15916595351771938816, 9), // 136 - (17001416405572203977, 9), // 137 - (18151468971815029248, 9), // 138 - ( 139353667211683681, 8), // 139 - ( 147578905600000000, 8), // 140 - ( 156225851787813921, 8), // 141 - ( 165312903998914816, 8), // 142 - ( 174859124550883201, 8), // 143 - ( 184884258895036416, 8), // 144 - ( 195408755062890625, 8), // 145 - ( 206453783524884736, 8), // 146 - ( 218041257467152161, 8), // 147 - ( 230193853492166656, 8), // 148 - ( 242935032749128801, 8), // 149 - ( 256289062500000000, 8), // 150 - ( 270281038127131201, 8), // 151 - ( 284936905588473856, 8), // 152 - ( 300283484326400961, 8), // 153 - ( 316348490636206336, 8), // 154 - ( 333160561500390625, 8), // 155 - ( 350749278894882816, 8), // 156 - ( 369145194573386401, 8), // 157 - ( 388379855336079616, 8), // 158 - ( 408485828788939521, 8), // 159 - ( 429496729600000000, 8), // 160 - ( 451447246258894081, 8), // 161 - ( 474373168346071296, 8), // 162 - ( 498311414318121121, 8), // 163 - ( 523300059815673856, 8), // 164 - ( 549378366500390625, 8), // 165 - ( 576586811427594496, 8), // 166 - ( 604967116961135041, 8), // 167 - ( 634562281237118976, 8), // 168 - ( 665416609183179841, 8), // 169 - ( 697575744100000000, 8), // 170 - ( 731086699811838561, 8), // 171 - ( 765997893392859136, 8), // 172 - ( 802359178476091681, 8), // 173 - ( 840221879151902976, 8), // 174 - ( 879638824462890625, 8), // 175 - ( 920664383502155776, 8), // 176 - ( 963354501121950081, 8), // 177 - ( 1007766734259732736, 8), // 178 - ( 1053960288888713761, 8), // 179 - ( 1101996057600000000, 8), // 180 - ( 1151936657823500641, 8), // 181 - ( 1203846470694789376, 8), // 182 - ( 1257791680575160641, 8), // 183 - ( 1313840315232157696, 8), // 184 - ( 1372062286687890625, 8), // 185 - ( 1432529432742502656, 8), // 186 - ( 1495315559180183521, 8), // 187 - ( 1560496482665168896, 8), // 188 - ( 1628150074335205281, 8), // 189 - ( 1698356304100000000, 8), // 190 - ( 1771197285652216321, 8), // 191 - ( 1846757322198614016, 8), // 192 - ( 1925122952918976001, 8), // 193 - ( 2006383000160502016, 8), // 194 - ( 2090628617375390625, 8), // 195 - ( 2177953337809371136, 8), // 196 - ( 2268453123948987361, 8), // 197 - ( 2362226417735475456, 8), // 198 - ( 2459374191553118401, 8), // 199 - ( 2560000000000000000, 8), // 200 - ( 2664210032449121601, 8), // 201 - ( 2772113166407885056, 8), // 202 - ( 2883821021683985761, 8), // 203 - ( 2999448015365799936, 8), // 204 - ( 3119111417625390625, 8), // 205 - ( 3242931408352297216, 8), // 206 - ( 3371031134626313601, 8), // 207 - ( 3503536769037500416, 8), // 208 - ( 3640577568861717121, 8), // 209 - ( 3782285936100000000, 8), // 210 - ( 3928797478390152481, 8), // 211 - ( 4080251070798954496, 8), // 212 - ( 4236788918503437921, 8), // 213 - ( 4398556620369715456, 8), // 214 - ( 4565703233437890625, 8), // 215 - ( 4738381338321616896, 8), // 216 - ( 4916747105530914241, 8), // 217 - ( 5100960362726891776, 8), // 218 - ( 5291184662917065441, 8), // 219 - ( 5487587353600000000, 8), // 220 - ( 5690339646868044961, 8), // 221 - ( 5899616690476974336, 8), // 222 - ( 6115597639891380481, 8), // 223 - ( 6338465731314712576, 8), // 224 - ( 6568408355712890625, 8), // 225 - ( 6805617133840466176, 8), // 226 - ( 7050287992278341281, 8), // 227 - ( 7302621240492097536, 8), // 228 - ( 7562821648920027361, 8), // 229 - ( 7831098528100000000, 8), // 230 - ( 8107665808844335041, 8), // 231 - ( 8392742123471896576, 8), // 232 - ( 8686550888106661441, 8), // 233 - ( 8989320386052055296, 8), // 234 - ( 9301283852250390625, 8), // 235 - ( 9622679558836781056, 8), // 236 - ( 9953750901796946721, 8), // 237 - (10294746488738365696, 8), // 238 - (10645920227784266881, 8), // 239 - (11007531417600000000, 8), // 240 - (11379844838561358721, 8), // 241 - (11763130845074473216, 8), // 242 - (12157665459056928801, 8), // 243 - (12563730464589807616, 8), // 244 - (12981613503750390625, 8), // 245 - (13411608173635297536, 8), // 246 - (13854014124583882561, 8), // 247 - (14309137159611744256, 8), // 248 - (14777289335064248001, 8), // 249 - (15258789062500000000, 8), // 250 - (15753961211814252001, 8), // 251 - (16263137215612256256, 8), // 252 - (16786655174842630561, 8), // 253 - (17324859965700833536, 8), // 254 - (17878103347812890625, 8), // 255 - ( 72057594037927936, 7), // 256 - ]; - - let (base, power) = BASES[radix as usize]; - (base as BigDigit, power) - } - _ => panic!("Invalid bigdigit size") - } -} diff --git a/bigint/src/lib.rs b/bigint/src/lib.rs deleted file mode 100644 index 02b9992..0000000 --- a/bigint/src/lib.rs +++ /dev/null @@ -1,154 +0,0 @@ -// 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 or the MIT license -// , 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 a vector of `BigDigit`s. -//! A `BigInt` is a combination of `BigUint` and `Sign`. -//! -//! Common numerical operations are overloaded, so we can treat them -//! the same way we treat other numbers. -//! -//! ## Example -//! -//! ```rust -//! extern crate num_bigint; -//! extern crate num_traits; -//! -//! # fn main() { -//! use num_bigint::BigUint; -//! use num_traits::{Zero, One}; -//! use std::mem::replace; -//! -//! // Calculate large fibonacci numbers. -//! fn fib(n: usize) -> BigUint { -//! let mut f0: BigUint = Zero::zero(); -//! let mut f1: BigUint = One::one(); -//! for _ in 0..n { -//! let f2 = f0 + &f1; -//! // This is a low cost way of swapping f0 with f1 and f1 with f2. -//! f0 = replace(&mut f1, f2); -//! } -//! f0 -//! } -//! -//! // This is a very large number. -//! println!("fib(1000) = {}", fib(1000)); -//! # } -//! ``` -//! -//! It's easy to generate large random numbers: -//! -//! ```rust -//! extern crate rand; -//! extern crate num_bigint as bigint; -//! -//! # #[cfg(feature = "rand")] -//! # fn main() { -//! use bigint::{ToBigInt, RandBigInt}; -//! -//! let mut rng = rand::thread_rng(); -//! let a = rng.gen_bigint(1000); -//! -//! let low = -10000.to_bigint().unwrap(); -//! let high = 10000.to_bigint().unwrap(); -//! let b = rng.gen_bigint_range(&low, &high); -//! -//! // Probably an even larger number. -//! println!("{}", a * b); -//! # } -//! -//! # #[cfg(not(feature = "rand"))] -//! # fn main() { -//! # } -//! ``` -#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://rust-num.github.io/num/favicon.ico", - html_root_url = "https://rust-num.github.io/num/", - html_playground_url = "http://play.integer32.com/")] - -#[cfg(any(feature = "rand", test))] -extern crate rand; -#[cfg(feature = "rustc-serialize")] -extern crate rustc_serialize; -#[cfg(feature = "serde")] -extern crate serde; - -extern crate num_integer as integer; -extern crate num_traits as traits; - -use std::error::Error; -use std::num::ParseIntError; -use std::fmt; - -#[cfg(target_pointer_width = "32")] -type UsizePromotion = u32; -#[cfg(target_pointer_width = "64")] -type UsizePromotion = u64; - -#[cfg(target_pointer_width = "32")] -type IsizePromotion = i32; -#[cfg(target_pointer_width = "64")] -type IsizePromotion = i64; - -#[derive(Debug, PartialEq)] -pub enum ParseBigIntError { - ParseInt(ParseIntError), - Other, -} - -impl fmt::Display for ParseBigIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &ParseBigIntError::ParseInt(ref e) => e.fmt(f), - &ParseBigIntError::Other => "failed to parse provided string".fmt(f), - } - } -} - -impl Error for ParseBigIntError { - fn description(&self) -> &str { - "failed to parse bigint/biguint" - } -} - -impl From for ParseBigIntError { - fn from(err: ParseIntError) -> ParseBigIntError { - ParseBigIntError::ParseInt(err) - } -} - -#[cfg(test)] -use std::hash; - -#[cfg(test)] -fn hash(x: &T) -> u64 { - use std::hash::{BuildHasher, Hasher}; - use std::collections::hash_map::RandomState; - let mut hasher = ::Hasher::new(); - x.hash(&mut hasher); - hasher.finish() -} - -#[macro_use] -mod macros; - -mod biguint; -mod bigint; - -pub use biguint::BigUint; -pub use biguint::ToBigUint; -pub use biguint::big_digit; -pub use biguint::big_digit::{BigDigit, DoubleBigDigit, ZERO_BIG_DIGIT}; - -pub use bigint::Sign; -pub use bigint::BigInt; -pub use bigint::ToBigInt; -pub use bigint::RandBigInt; diff --git a/bigint/src/macros.rs b/bigint/src/macros.rs deleted file mode 100644 index 9343361..0000000 --- a/bigint/src/macros.rs +++ /dev/null @@ -1,316 +0,0 @@ -#![allow(unknown_lints)] // older rustc doesn't know `unused_macros` -#![allow(unused_macros)] - -macro_rules! forward_val_val_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // forward to val-ref - $imp::$method(self, &other) - } - } - } -} - -macro_rules! forward_val_val_binop_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // forward to val-ref, with the larger capacity as val - if self.data.capacity() >= other.data.capacity() { - $imp::$method(self, &other) - } else { - $imp::$method(other, &self) - } - } - } - } -} - -macro_rules! forward_ref_val_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a> $imp<$res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // forward to ref-ref - $imp::$method(self, &other) - } - } - } -} - -macro_rules! forward_ref_val_binop_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a> $imp<$res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - // reverse, forward to val-ref - $imp::$method(other, self) - } - } - } -} - -macro_rules! forward_val_ref_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a> $imp<&'a $res> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - // forward to ref-ref - $imp::$method(&self, other) - } - } - } -} - -macro_rules! forward_ref_ref_binop { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a, 'b> $imp<&'b $res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - // forward to val-ref - $imp::$method(self.clone(), other) - } - } - } -} - -macro_rules! forward_ref_ref_binop_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - impl<'a, 'b> $imp<&'b $res> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - // forward to val-ref, choosing the larger to clone - if self.data.len() >= other.data.len() { - $imp::$method(self.clone(), other) - } else { - $imp::$method(other.clone(), self) - } - } - } - } -} - -macro_rules! forward_val_assign { - (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { - #[inline] - fn $method(&mut self, other: $res) { - self.$method(&other); - } - } - } -} -macro_rules! forward_val_assign_scalar { - (impl $imp:ident for $res:ty, $scalar:ty, $method:ident) => { - impl $imp<$res> for $scalar { - #[inline] - fn $method(&mut self, other: $res) { - self.$method(&other); - } - } - } -} - -macro_rules! forward_scalar_val_val_binop_commutative { - (impl $imp:ident<$scalar:ty> for $res:ty, $method: ident) => { - impl $imp<$res> for $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(other, self) - } - } - } -} - -macro_rules! forward_scalar_val_ref_binop { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl<'a> $imp<&'a $scalar> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$scalar) -> $res { - $imp::$method(self, *other) - } - } - - impl<'a> $imp<$res> for &'a $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(*self, other) - } - } - } -} - -macro_rules! forward_scalar_ref_val_binop { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl<'a> $imp<$scalar> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: $scalar) -> $res { - $imp::$method(self.clone(), other) - } - } - - impl<'a> $imp<&'a $res> for $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - $imp::$method(self, other.clone()) - } - } - } -} - -macro_rules! forward_scalar_ref_ref_binop { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl<'a, 'b> $imp<&'b $scalar> for &'a $res { - type Output = $res; - - #[inline] - fn $method(self, other: &$scalar) -> $res { - $imp::$method(self.clone(), *other) - } - } - - impl<'a, 'b> $imp<&'a $res> for &'b $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: &$res) -> $res { - $imp::$method(*self, other.clone()) - } - } - } -} - -macro_rules! promote_scalars { - (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { - $( - forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - - impl $imp<$scalar> for $res { - type Output = $res; - - #[inline] - fn $method(self, other: $scalar) -> $res { - $imp::$method(self, other as $promo) - } - } - - impl $imp<$res> for $scalar { - type Output = $res; - - #[inline] - fn $method(self, other: $res) -> $res { - $imp::$method(self as $promo, other) - } - } - )* - } -} -macro_rules! promote_scalars_assign { - (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { - $( - impl $imp<$scalar> for $res { - #[inline] - fn $method(&mut self, other: $scalar) { - self.$method(other as $promo); - } - } - )* - } -} - -macro_rules! promote_unsigned_scalars { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_scalars!(impl $imp for $res, $method, u8, u16); - promote_scalars!(impl $imp for $res, $method, usize); - } -} - -macro_rules! promote_unsigned_scalars_assign { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_scalars_assign!(impl $imp for $res, $method, u8, u16); - promote_scalars_assign!(impl $imp for $res, $method, usize); - } -} - -macro_rules! promote_signed_scalars { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_scalars!(impl $imp for $res, $method, i8, i16); - promote_scalars!(impl $imp for $res, $method, isize); - } -} - -// Forward everything to ref-ref, when reusing storage is not helpful -macro_rules! forward_all_binop_to_ref_ref { - (impl $imp:ident for $res:ty, $method:ident) => { - forward_val_val_binop!(impl $imp for $res, $method); - forward_val_ref_binop!(impl $imp for $res, $method); - forward_ref_val_binop!(impl $imp for $res, $method); - }; -} - -// Forward everything to val-ref, so LHS storage can be reused -macro_rules! forward_all_binop_to_val_ref { - (impl $imp:ident for $res:ty, $method:ident) => { - forward_val_val_binop!(impl $imp for $res, $method); - forward_ref_val_binop!(impl $imp for $res, $method); - forward_ref_ref_binop!(impl $imp for $res, $method); - }; -} - -// Forward everything to val-ref, commutatively, so either LHS or RHS storage can be reused -macro_rules! forward_all_binop_to_val_ref_commutative { - (impl $imp:ident for $res:ty, $method:ident) => { - forward_val_val_binop_commutative!(impl $imp for $res, $method); - forward_ref_val_binop_commutative!(impl $imp for $res, $method); - forward_ref_ref_binop_commutative!(impl $imp for $res, $method); - }; -} - -macro_rules! forward_all_scalar_binop_to_val_val { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - forward_scalar_val_ref_binop!(impl $imp<$scalar> for $res, $method); - forward_scalar_ref_val_binop!(impl $imp<$scalar> for $res, $method); - forward_scalar_ref_ref_binop!(impl $imp<$scalar> for $res, $method); - } -} - -macro_rules! forward_all_scalar_binop_to_val_val_commutative { - (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - forward_scalar_val_val_binop_commutative!(impl $imp<$scalar> for $res, $method); - forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - } -} - -macro_rules! promote_all_scalars { - (impl $imp:ident for $res:ty, $method:ident) => { - promote_unsigned_scalars!(impl $imp for $res, $method); - promote_signed_scalars!(impl $imp for $res, $method); - } -} diff --git a/bigint/src/monty.rs b/bigint/src/monty.rs deleted file mode 100644 index 3cf526b..0000000 --- a/bigint/src/monty.rs +++ /dev/null @@ -1,127 +0,0 @@ -use integer::Integer; -use traits::Zero; - -use biguint::BigUint; - -struct MontyReducer<'a> { - n: &'a BigUint, - n0inv: u32 -} - -// Calculate the modular inverse of `num`, using Extended GCD. -// -// Reference: -// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 1.20 -fn inv_mod_u32(num: u32) -> u32 { - // num needs to be relatively prime to 2**32 -- i.e. it must be odd. - assert!(num % 2 != 0); - - let mut a: i64 = num as i64; - let mut b: i64 = (u32::max_value() as i64) + 1; - - // ExtendedGcd - // Input: positive integers a and b - // Output: integers (g, u, v) such that g = gcd(a, b) = ua + vb - // As we don't need v for modular inverse, we don't calculate it. - - // 1: (u, w) <- (1, 0) - let mut u = 1; - let mut w = 0; - // 3: while b != 0 - while b != 0 { - // 4: (q, r) <- DivRem(a, b) - let q = a / b; - let r = a % b; - // 5: (a, b) <- (b, r) - a = b; b = r; - // 6: (u, w) <- (w, u - qw) - let m = u - w*q; - u = w; w = m; - } - - assert!(a == 1); - // Downcasting acts like a mod 2^32 too. - u as u32 -} - -impl<'a> MontyReducer<'a> { - fn new(n: &'a BigUint) -> Self { - let n0inv = inv_mod_u32(n.data[0]); - MontyReducer { n: n, n0inv: n0inv } - } -} - -// Montgomery Reduction -// -// Reference: -// Brent & Zimmermann, Modern Computer Arithmetic, v0.5.9, Algorithm 2.6 -fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint { - let mut c = a.data; - let n = &mr.n.data; - let n_size = n.len(); - - // Allocate sufficient work space - c.resize(2 * n_size + 2, 0); - - // β is the size of a word, in this case 32 bits. So "a mod β" is - // equivalent to masking a to 32 bits. - // mu <- -N^(-1) mod β - let mu = 0u32.wrapping_sub(mr.n0inv); - - // 1: for i = 0 to (n-1) - for i in 0..n_size { - // 2: q_i <- mu*c_i mod β - let q_i = c[i].wrapping_mul(mu); - - // 3: C <- C + q_i * N * β^i - super::algorithms::mac_digit(&mut c[i..], n, q_i); - } - - // 4: R <- C * β^(-n) - // This is an n-word bitshift, equivalent to skipping n words. - let ret = BigUint::new(c[n_size..].to_vec()); - - // 5: if R >= β^n then return R-N else return R. - if &ret < mr.n { - ret - } else { - ret - mr.n - } -} - -// Montgomery Multiplication -fn monty_mult(a: BigUint, b: &BigUint, mr: &MontyReducer) -> BigUint { - monty_redc(a * b, mr) -} - -// Montgomery Squaring -fn monty_sqr(a: BigUint, mr: &MontyReducer) -> BigUint { - // TODO: Replace with an optimised squaring function - monty_redc(&a * &a, mr) -} - -pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint{ - let mr = MontyReducer::new(modulus); - - // Calculate the Montgomery parameter - let mut v = vec![0; modulus.data.len()]; - v.push(1); - let r = BigUint::new(v); - - // Map the base to the Montgomery domain - let mut apri = a * &r % modulus; - - // Binary exponentiation - let mut ans = &r % modulus; - let mut e = exp.clone(); - while !e.is_zero() { - if e.is_odd() { - ans = monty_mult(ans, &apri, &mr); - } - apri = monty_sqr(apri, &mr); - e = e >> 1; - } - - // Map the result back to the residues domain - monty_redc(ans, &mr) -} diff --git a/bigint/src/tests/bigint.rs b/bigint/src/tests/bigint.rs deleted file mode 100644 index a3c8f6f..0000000 --- a/bigint/src/tests/bigint.rs +++ /dev/null @@ -1,1194 +0,0 @@ -use {BigDigit, BigUint, big_digit}; -use {Sign, BigInt, RandBigInt, ToBigInt}; -use Sign::{Minus, NoSign, Plus}; - -use std::cmp::Ordering::{Less, Equal, Greater}; -use std::{f32, f64}; -use std::{i8, i16, i32, i64, isize}; -use std::iter::repeat; -use std::{u8, u16, u32, u64, usize}; -use std::ops::Neg; - -use rand::thread_rng; - -use integer::Integer; -use traits::{Zero, One, Signed, ToPrimitive, FromPrimitive, Num, Float}; - -/// Assert that an op works for all val/ref combinations -macro_rules! assert_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_eq!((&$left) $op (&$right), $expected); - assert_eq!((&$left) $op $right.clone(), $expected); - assert_eq!($left.clone() $op (&$right), $expected); - assert_eq!($left.clone() $op $right.clone(), $expected); - }; -} - -/// Assert that an op works for scalar left or right -macro_rules! assert_scalar_op { - (($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => { - $( - if let Some(left) = $left.$to() { - assert_op!(left $op $right == $expected); - } - if let Some(right) = $right.$to() { - assert_op!($left $op right == $expected); - } - )* - }; - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, - to_i8, to_i16, to_i32, to_i64, to_isize) - $left $op $right == $expected); - }; -} - -#[test] -fn test_from_biguint() { - fn check(inp_s: Sign, inp_n: usize, ans_s: Sign, ans_n: usize) { - let inp = BigInt::from_biguint(inp_s, FromPrimitive::from_usize(inp_n).unwrap()); - let ans = BigInt { - sign: ans_s, - data: FromPrimitive::from_usize(ans_n).unwrap(), - }; - assert_eq!(inp, ans); - } - check(Plus, 1, Plus, 1); - check(Plus, 0, NoSign, 0); - check(Minus, 1, Minus, 1); - check(NoSign, 1, NoSign, 0); -} - -#[test] -fn test_from_slice() { - fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) { - let inp = BigInt::from_slice(inp_s, &[inp_n]); - let ans = BigInt { - sign: ans_s, - data: FromPrimitive::from_u32(ans_n).unwrap(), - }; - assert_eq!(inp, ans); - } - check(Plus, 1, Plus, 1); - check(Plus, 0, NoSign, 0); - check(Minus, 1, Minus, 1); - check(NoSign, 1, NoSign, 0); -} - -#[test] -fn test_assign_from_slice() { - fn check(inp_s: Sign, inp_n: u32, ans_s: Sign, ans_n: u32) { - let mut inp = BigInt::from_slice(Minus, &[2627_u32, 0_u32, 9182_u32, 42_u32]); - inp.assign_from_slice(inp_s, &[inp_n]); - let ans = BigInt { - sign: ans_s, - data: FromPrimitive::from_u32(ans_n).unwrap(), - }; - assert_eq!(inp, ans); - } - check(Plus, 1, Plus, 1); - check(Plus, 0, NoSign, 0); - check(Minus, 1, Minus, 1); - check(NoSign, 1, NoSign, 0); -} - -#[test] -fn test_from_bytes_be() { - fn check(s: &str, result: &str) { - assert_eq!(BigInt::from_bytes_be(Plus, s.as_bytes()), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap()); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - assert_eq!(BigInt::from_bytes_be(Plus, &[]), Zero::zero()); - assert_eq!(BigInt::from_bytes_be(Minus, &[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_be() { - fn check(s: &str, result: &str) { - let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); - let (sign, v) = b.to_bytes_be(); - assert_eq!((Plus, s.as_bytes()), (sign, &*v)); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - let b: BigInt = Zero::zero(); - assert_eq!(b.to_bytes_be(), (NoSign, vec![0])); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_be(), (Plus, vec![1, 0, 0, 0, 0, 0, 0, 2, 0])); -} - -#[test] -fn test_from_bytes_le() { - fn check(s: &str, result: &str) { - assert_eq!(BigInt::from_bytes_le(Plus, s.as_bytes()), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap()); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - assert_eq!(BigInt::from_bytes_le(Plus, &[]), Zero::zero()); - assert_eq!(BigInt::from_bytes_le(Minus, &[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_le() { - fn check(s: &str, result: &str) { - let b = BigInt::parse_bytes(result.as_bytes(), 10).unwrap(); - let (sign, v) = b.to_bytes_le(); - assert_eq!((Plus, s.as_bytes()), (sign, &*v)); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - let b: BigInt = Zero::zero(); - assert_eq!(b.to_bytes_le(), (NoSign, vec![0])); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigInt::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_le(), (Plus, vec![0, 2, 0, 0, 0, 0, 0, 0, 1])); -} - -#[test] -fn test_to_signed_bytes_le() { - fn check(s: &str, result: Vec) { - assert_eq!(BigInt::parse_bytes(s.as_bytes(), 10).unwrap().to_signed_bytes_le(), - result); - } - - check("0", vec![0]); - check("32767", vec![0xff, 0x7f]); - check("-1", vec![0xff]); - check("16777216", vec![0, 0, 0, 1]); - check("-100", vec![156]); - check("-8388608", vec![0, 0, 0x80]); - check("-192", vec![0x40, 0xff]); -} - -#[test] -fn test_from_signed_bytes_le() { - fn check(s: &[u8], result: &str) { - assert_eq!(BigInt::from_signed_bytes_le(s), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap()); - } - - check(&[], "0"); - check(&[0], "0"); - check(&[0; 10], "0"); - check(&[0xff, 0x7f], "32767"); - check(&[0xff], "-1"); - check(&[0, 0, 0, 1], "16777216"); - check(&[156], "-100"); - check(&[0, 0, 0x80], "-8388608"); - check(&[0xff; 10], "-1"); - check(&[0x40, 0xff], "-192"); -} - -#[test] -fn test_to_signed_bytes_be() { - fn check(s: &str, result: Vec) { - assert_eq!(BigInt::parse_bytes(s.as_bytes(), 10).unwrap().to_signed_bytes_be(), - result); - } - - check("0", vec![0]); - check("32767", vec![0x7f, 0xff]); - check("-1", vec![255]); - check("16777216", vec![1, 0, 0, 0]); - check("-100", vec![156]); - check("-8388608", vec![128, 0, 0]); - check("-192", vec![0xff, 0x40]); -} - -#[test] -fn test_from_signed_bytes_be() { - fn check(s: &[u8], result: &str) { - assert_eq!(BigInt::from_signed_bytes_be(s), - BigInt::parse_bytes(result.as_bytes(), 10).unwrap()); - } - - check(&[], "0"); - check(&[0], "0"); - check(&[0; 10], "0"); - check(&[127, 255], "32767"); - check(&[255], "-1"); - check(&[1, 0, 0, 0], "16777216"); - check(&[156], "-100"); - check(&[128, 0, 0], "-8388608"); - check(&[255; 10], "-1"); - check(&[0xff, 0x40], "-192"); -} - -#[test] -fn test_cmp() { - let vs: [&[BigDigit]; 4] = [&[2 as BigDigit], &[1, 1], &[2, 1], &[1, 1, 1]]; - let mut nums = Vec::new(); - for s in vs.iter().rev() { - nums.push(BigInt::from_slice(Minus, *s)); - } - nums.push(Zero::zero()); - nums.extend(vs.iter().map(|s| BigInt::from_slice(Plus, *s))); - - for (i, ni) in nums.iter().enumerate() { - for (j0, nj) in nums[i..].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_hash() { - use hash; - - let a = BigInt::new(NoSign, vec![]); - let b = BigInt::new(NoSign, vec![0]); - let c = BigInt::new(Plus, vec![1]); - let d = BigInt::new(Plus, vec![1, 0, 0, 0, 0, 0]); - let e = BigInt::new(Plus, vec![0, 0, 0, 0, 0, 1]); - let f = BigInt::new(Minus, vec![1]); - assert!(hash(&a) == hash(&b)); - assert!(hash(&b) != hash(&c)); - assert!(hash(&c) == hash(&d)); - assert!(hash(&d) != hash(&e)); - assert!(hash(&c) != hash(&f)); -} - -#[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(vec![1, 2, 3, 4, 5])).to_i64(), - None); - - assert_eq!(BigInt::from_biguint(Minus, - BigUint::new(vec![1, 0, 0, 1 << (big_digit::BITS - 1)])) - .to_i64(), - None); - - assert_eq!(BigInt::from_biguint(Minus, BigUint::new(vec![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(vec![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(vec![1, 2, 3, 4, 5])).to_u64(), - None); -} - -#[test] -fn test_convert_f32() { - fn check(b1: &BigInt, f: f32) { - let b2 = BigInt::from_f32(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f32().unwrap(), f); - let neg_b1 = -b1; - let neg_b2 = BigInt::from_f32(-f).unwrap(); - assert_eq!(neg_b1, neg_b2); - assert_eq!(neg_b1.to_f32().unwrap(), -f); - } - - check(&BigInt::zero(), 0.0); - check(&BigInt::one(), 1.0); - check(&BigInt::from(u16::MAX), 2.0.powi(16) - 1.0); - check(&BigInt::from(1u64 << 32), 2.0.powi(32)); - check(&BigInt::from_slice(Plus, &[0, 0, 1]), 2.0.powi(64)); - check(&((BigInt::one() << 100) + (BigInt::one() << 123)), - 2.0.powi(100) + 2.0.powi(123)); - check(&(BigInt::one() << 127), 2.0.powi(127)); - check(&(BigInt::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); - - // keeping all 24 digits with the bits at different offsets to the BigDigits - let x: u32 = 0b00000000101111011111011011011101; - let mut f = x as f32; - let mut b = BigInt::from(x); - for _ in 0..64 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 - let mut n: i64 = 0b0000000000111111111111111111111111011111111111111111111111111111; - assert!((n as f64) as f32 != n as f32); - assert_eq!(BigInt::from(n).to_f32(), Some(n as f32)); - n = -n; - assert!((n as f64) as f32 != n as f32); - assert_eq!(BigInt::from(n).to_f32(), Some(n as f32)); - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 25) - 1) as f32; - let mut b = BigInt::from(1u64 << 25); - for _ in 0..64 { - assert_eq!(b.to_f32(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!(BigInt::from_f32(-f32::consts::PI), - Some(BigInt::from(-3i32))); - assert_eq!(BigInt::from_f32(-f32::consts::E), Some(BigInt::from(-2i32))); - assert_eq!(BigInt::from_f32(-0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(-0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(-0.0), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(f32::MIN_POSITIVE / 2.0), - Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(f32::MIN_POSITIVE), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f32(f32::consts::E), Some(BigInt::from(2u32))); - assert_eq!(BigInt::from_f32(f32::consts::PI), Some(BigInt::from(3u32))); - - // special float values - assert_eq!(BigInt::from_f32(f32::NAN), None); - assert_eq!(BigInt::from_f32(f32::INFINITY), None); - assert_eq!(BigInt::from_f32(f32::NEG_INFINITY), None); - - // largest BigInt that will round to a finite f32 value - let big_num = (BigInt::one() << 128) - BigInt::one() - (BigInt::one() << (128 - 25)); - assert_eq!(big_num.to_f32(), Some(f32::MAX)); - assert_eq!((&big_num + BigInt::one()).to_f32(), None); - assert_eq!((-&big_num).to_f32(), Some(f32::MIN)); - assert_eq!(((-&big_num) - BigInt::one()).to_f32(), None); - - assert_eq!(((BigInt::one() << 128) - BigInt::one()).to_f32(), None); - assert_eq!((BigInt::one() << 128).to_f32(), None); - assert_eq!((-((BigInt::one() << 128) - BigInt::one())).to_f32(), None); - assert_eq!((-(BigInt::one() << 128)).to_f32(), None); -} - -#[test] -fn test_convert_f64() { - fn check(b1: &BigInt, f: f64) { - let b2 = BigInt::from_f64(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f64().unwrap(), f); - let neg_b1 = -b1; - let neg_b2 = BigInt::from_f64(-f).unwrap(); - assert_eq!(neg_b1, neg_b2); - assert_eq!(neg_b1.to_f64().unwrap(), -f); - } - - check(&BigInt::zero(), 0.0); - check(&BigInt::one(), 1.0); - check(&BigInt::from(u32::MAX), 2.0.powi(32) - 1.0); - check(&BigInt::from(1u64 << 32), 2.0.powi(32)); - check(&BigInt::from_slice(Plus, &[0, 0, 1]), 2.0.powi(64)); - check(&((BigInt::one() << 100) + (BigInt::one() << 152)), - 2.0.powi(100) + 2.0.powi(152)); - check(&(BigInt::one() << 1023), 2.0.powi(1023)); - check(&(BigInt::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); - - // keeping all 53 digits with the bits at different offsets to the BigDigits - let x: u64 = 0b0000000000011110111110110111111101110111101111011111011011011101; - let mut f = x as f64; - let mut b = BigInt::from(x); - for _ in 0..128 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 54) - 1) as f64; - let mut b = BigInt::from(1u64 << 54); - for _ in 0..128 { - assert_eq!(b.to_f64(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!(BigInt::from_f64(-f64::consts::PI), - Some(BigInt::from(-3i32))); - assert_eq!(BigInt::from_f64(-f64::consts::E), Some(BigInt::from(-2i32))); - assert_eq!(BigInt::from_f64(-0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(-0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(-0.0), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(f64::MIN_POSITIVE / 2.0), - Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(f64::MIN_POSITIVE), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(0.5), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(0.99999), Some(BigInt::zero())); - assert_eq!(BigInt::from_f64(f64::consts::E), Some(BigInt::from(2u32))); - assert_eq!(BigInt::from_f64(f64::consts::PI), Some(BigInt::from(3u32))); - - // special float values - assert_eq!(BigInt::from_f64(f64::NAN), None); - assert_eq!(BigInt::from_f64(f64::INFINITY), None); - assert_eq!(BigInt::from_f64(f64::NEG_INFINITY), None); - - // largest BigInt that will round to a finite f64 value - let big_num = (BigInt::one() << 1024) - BigInt::one() - (BigInt::one() << (1024 - 54)); - assert_eq!(big_num.to_f64(), Some(f64::MAX)); - assert_eq!((&big_num + BigInt::one()).to_f64(), None); - assert_eq!((-&big_num).to_f64(), Some(f64::MIN)); - assert_eq!(((-&big_num) - BigInt::one()).to_f64(), None); - - assert_eq!(((BigInt::one() << 1024) - BigInt::one()).to_f64(), None); - assert_eq!((BigInt::one() << 1024).to_f64(), None); - assert_eq!((-((BigInt::one() << 1024) - BigInt::one())).to_f64(), None); - assert_eq!((-(BigInt::one() << 1024)).to_f64(), 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(vec![1, 2, 3])); - let negative = -&positive; - - check(zero, unsigned_zero); - check(positive, BigUint::new(vec![1, 2, 3])); - - assert_eq!(negative.to_biguint(), None); -} - -#[test] -fn test_convert_from_uint() { - macro_rules! check { - ($ty:ident, $max:expr) => { - assert_eq!(BigInt::from($ty::zero()), BigInt::zero()); - assert_eq!(BigInt::from($ty::one()), BigInt::one()); - assert_eq!(BigInt::from($ty::MAX - $ty::one()), $max - BigInt::one()); - assert_eq!(BigInt::from($ty::MAX), $max); - } - } - - check!(u8, BigInt::from_slice(Plus, &[u8::MAX as BigDigit])); - check!(u16, BigInt::from_slice(Plus, &[u16::MAX as BigDigit])); - check!(u32, BigInt::from_slice(Plus, &[u32::MAX as BigDigit])); - check!(u64, - BigInt::from_slice(Plus, &[u32::MAX as BigDigit, u32::MAX as BigDigit])); - check!(usize, BigInt::from(usize::MAX as u64)); -} - -#[test] -fn test_convert_from_int() { - macro_rules! check { - ($ty:ident, $min:expr, $max:expr) => { - assert_eq!(BigInt::from($ty::MIN), $min); - assert_eq!(BigInt::from($ty::MIN + $ty::one()), $min + BigInt::one()); - assert_eq!(BigInt::from(-$ty::one()), -BigInt::one()); - assert_eq!(BigInt::from($ty::zero()), BigInt::zero()); - assert_eq!(BigInt::from($ty::one()), BigInt::one()); - assert_eq!(BigInt::from($ty::MAX - $ty::one()), $max - BigInt::one()); - assert_eq!(BigInt::from($ty::MAX), $max); - } - } - - check!(i8, - BigInt::from_slice(Minus, &[1 << 7]), - BigInt::from_slice(Plus, &[i8::MAX as BigDigit])); - check!(i16, - BigInt::from_slice(Minus, &[1 << 15]), - BigInt::from_slice(Plus, &[i16::MAX as BigDigit])); - check!(i32, - BigInt::from_slice(Minus, &[1 << 31]), - BigInt::from_slice(Plus, &[i32::MAX as BigDigit])); - check!(i64, - BigInt::from_slice(Minus, &[0, 1 << 31]), - BigInt::from_slice(Plus, &[u32::MAX as BigDigit, i32::MAX as BigDigit])); - check!(isize, - BigInt::from(isize::MIN as i64), - BigInt::from(isize::MAX as i64)); -} - -#[test] -fn test_convert_from_biguint() { - assert_eq!(BigInt::from(BigUint::zero()), BigInt::zero()); - assert_eq!(BigInt::from(BigUint::one()), BigInt::one()); - assert_eq!(BigInt::from(BigUint::from_slice(&[1, 2, 3])), - BigInt::from_slice(Plus, &[1, 2, 3])); -} - -const N1: BigDigit = -1i32 as BigDigit; -const N2: BigDigit = -2i32 as BigDigit; - -const SUM_TRIPLES: &'static [(&'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit])] = &[(&[], &[], &[]), - (&[], &[1], &[1]), - (&[1], &[1], &[2]), - (&[1], &[1, 1], &[2, 1]), - (&[1], &[N1], &[0, 1]), - (&[1], &[N1, N1], &[0, 0, 1]), - (&[N1, N1], &[N1, N1], &[N2, N1, 1]), - (&[1, 1, 1], &[N1, N1], &[0, 1, 2]), - (&[2, 2, 1], &[N1, N2], &[1, 1, 2])]; - -#[test] -fn test_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_op!(a + b == c); - assert_op!(b + a == c); - assert_op!(c + na == b); - assert_op!(c + nb == a); - assert_op!(a + nc == nb); - assert_op!(b + nc == na); - assert_op!(na + nb == nc); - assert_op!(a + na == Zero::zero()); - } -} - -#[test] -fn test_scalar_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_scalar_op!(a + b == c); - assert_scalar_op!(b + a == c); - assert_scalar_op!(c + na == b); - assert_scalar_op!(c + nb == a); - assert_scalar_op!(a + nc == nb); - assert_scalar_op!(b + nc == na); - assert_scalar_op!(na + nb == nc); - assert_scalar_op!(a + na == Zero::zero()); - } -} - -#[test] -fn test_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_op!(c - a == b); - assert_op!(c - b == a); - assert_op!(nb - a == nc); - assert_op!(na - b == nc); - assert_op!(b - na == c); - assert_op!(a - nb == c); - assert_op!(nc - na == nb); - assert_op!(a - a == Zero::zero()); - } -} - -#[test] -fn test_scalar_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_scalar_op!(c - a == b); - assert_scalar_op!(c - b == a); - assert_scalar_op!(nb - a == nc); - assert_scalar_op!(na - b == nc); - assert_scalar_op!(b - na == c); - assert_scalar_op!(a - nb == c); - assert_scalar_op!(nc - na == nb); - assert_scalar_op!(a - a == Zero::zero()); - } -} - -const M: u32 = ::std::u32::MAX; -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], &[N1], &[N1, N1, N1]), - (&[1, 2, 3], &[N1], &[N1, N2, N2, 2]), - (&[1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]), - (&[N1], &[N1], &[1, N2]), - (&[N1, N1], &[N1], &[1, N1, N2]), - (&[N1, N1, N1], &[N1], &[1, N1, N1, N2]), - (&[N1, N1, N1, N1], &[N1], &[1, N1, N1, N1, N2]), - (&[M / 2 + 1], &[2], &[0, 1]), - (&[0, M / 2 + 1], &[2], &[0, 0, 1]), - (&[1, 2], &[1, 2, 3], &[1, 4, 7, 6]), - (&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]), - (&[N1, N1, N1], - &[N1, N1, N1, N1], - &[1, 0, 0, N1, N2, N1, N1]), - (&[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]), - (&[3], &[2], &[1], &[1]), - (&[1, 1], &[2], &[M / 2 + 1], &[1]), - (&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]), - (&[0, 1], &[N1], &[1], &[1]), - (&[N1, N1], &[N2], &[2, 1], &[3])]; - -#[test] -fn test_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_op!(a * b == c); - assert_op!(b * a == c); - assert_op!(na * nb == c); - - assert_op!(na * b == nc); - assert_op!(nb * a == nc); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - assert!(a == &b * &c + &d); - assert!(a == &c * &b + &d); - } -} - -#[test] -fn test_scalar_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let (na, nb, nc) = (-&a, -&b, -&c); - - assert_scalar_op!(a * b == c); - assert_scalar_op!(b * a == c); - assert_scalar_op!(na * nb == c); - - assert_scalar_op!(na * b == nc); - assert_scalar_op!(nb * a == nc); - } -} - -#[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 { - let one: BigInt = One::one(); - check_sub(a, b, d, m); - check_sub(a, &b.neg(), &(d.neg() - &one), &(m - b)); - check_sub(&a.neg(), b, &(d.neg() - &one), &(b - m)); - check_sub(&a.neg(), &b.neg(), d, &m.neg()); - } - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - 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 (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - 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); - - let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone()); - assert_op!(a / b == ans_q); - assert_op!(a % b == 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 (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - 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 (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - if !b.is_zero() { - check(&a, &b, &c, &d); - } - } -} - -#[test] -fn test_scalar_div_rem() { - fn check_sub(a: &BigInt, b: BigDigit, ans_q: &BigInt, ans_r: &BigInt) { - let (q, r) = (a / b, a % b); - if !r.is_zero() { - assert_eq!(r.sign, a.sign); - } - assert!(r.abs() <= From::from(b)); - assert!(*a == b * &q + &r); - assert!(q == *ans_q); - assert!(r == *ans_r); - - let (a, b, ans_q, ans_r) = (a.clone(), b.clone(), ans_q.clone(), ans_r.clone()); - assert_op!(a / b == ans_q); - assert_op!(a % b == ans_r); - - if b <= i32::max_value() as u32 { - let nb = -(b as i32); - assert_op!(a / nb == -ans_q.clone()); - assert_op!(a % nb == ans_r); - } - } - - fn check(a: &BigInt, b: BigDigit, q: &BigInt, r: &BigInt) { - check_sub(a, b, q, r); - check_sub(&a.neg(), b, &q.neg(), &r.neg()); - } - - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - if a_vec.len() == 1 && a_vec[0] != 0 { - let a = a_vec[0]; - check(&c, a, &b, &Zero::zero()); - } - - if b_vec.len() == 1 && b_vec[0] != 0 { - let b = b_vec[0]; - check(&c, b, &a, &Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - if b_vec.len() == 1 && b_vec[0] != 0 { - let b = b_vec[0]; - check(&a, b, &c, &d); - } - } - -} - -#[test] -fn test_checked_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - assert!(a.checked_add(&b).unwrap() == c); - assert!(b.checked_add(&a).unwrap() == c); - assert!(c.checked_add(&(-&a)).unwrap() == b); - assert!(c.checked_add(&(-&b)).unwrap() == a); - assert!(a.checked_add(&(-&c)).unwrap() == (-&b)); - assert!(b.checked_add(&(-&c)).unwrap() == (-&a)); - assert!((-&a).checked_add(&(-&b)).unwrap() == (-&c)); - assert!(a.checked_add(&(-&a)).unwrap() == Zero::zero()); - } -} - -#[test] -fn test_checked_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - assert!(c.checked_sub(&a).unwrap() == b); - assert!(c.checked_sub(&b).unwrap() == a); - assert!((-&b).checked_sub(&a).unwrap() == (-&c)); - assert!((-&a).checked_sub(&b).unwrap() == (-&c)); - assert!(b.checked_sub(&(-&a)).unwrap() == c); - assert!(a.checked_sub(&(-&b)).unwrap() == c); - assert!((-&c).checked_sub(&(-&a)).unwrap() == (-&b)); - assert!(a.checked_sub(&a).unwrap() == Zero::zero()); - } -} - -#[test] -fn test_checked_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - assert!(a.checked_mul(&b).unwrap() == c); - assert!(b.checked_mul(&a).unwrap() == c); - - assert!((-&a).checked_mul(&b).unwrap() == -&c); - assert!((-&b).checked_mul(&a).unwrap() == -&c); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - let d = BigInt::from_slice(Plus, d_vec); - - assert!(a == b.checked_mul(&c).unwrap() + &d); - assert!(a == c.checked_mul(&b).unwrap() + &d); - } -} -#[test] -fn test_checked_div() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigInt::from_slice(Plus, a_vec); - let b = BigInt::from_slice(Plus, b_vec); - let c = BigInt::from_slice(Plus, c_vec); - - if !a.is_zero() { - assert!(c.checked_div(&a).unwrap() == b); - assert!((-&c).checked_div(&(-&a)).unwrap() == b); - assert!((-&c).checked_div(&a).unwrap() == -&b); - } - if !b.is_zero() { - assert!(c.checked_div(&b).unwrap() == a); - assert!((-&c).checked_div(&(-&b)).unwrap() == a); - assert!((-&c).checked_div(&b).unwrap() == -&a); - } - - assert!(c.checked_div(&Zero::zero()).is_none()); - assert!((-&c).checked_div(&Zero::zero()).is_none()); - } -} - -#[test] -fn test_gcd() { - fn check(a: isize, b: isize, c: isize) { - let big_a: BigInt = FromPrimitive::from_isize(a).unwrap(); - let big_b: BigInt = FromPrimitive::from_isize(b).unwrap(); - let big_c: BigInt = FromPrimitive::from_isize(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: isize, b: isize, c: isize) { - let big_a: BigInt = FromPrimitive::from_isize(a).unwrap(); - let big_b: BigInt = FromPrimitive::from_isize(b).unwrap(); - let big_c: BigInt = FromPrimitive::from_isize(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_isize(2).unwrap(); - assert_eq!(one.abs_sub(&-&one), two); -} - -#[test] -fn test_from_str_radix() { - fn check(s: &str, ans: Option) { - let ans = ans.map(|n| { - let x: BigInt = FromPrimitive::from_isize(n).unwrap(); - x - }); - assert_eq!(BigInt::from_str_radix(s, 10).ok(), ans); - } - check("10", Some(10)); - check("1", Some(1)); - check("0", Some(0)); - check("-1", Some(-1)); - check("-10", Some(-10)); - check("+10", Some(10)); - check("--7", None); - check("++5", None); - check("+-9", None); - check("-+3", None); - 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 = format!("1{}", repeat("0").take(36).collect::()).parse().unwrap(); - let _y = x.to_string(); -} - -#[test] -fn test_lower_hex() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:x}", a), "a"); - assert_eq!(format!("{:x}", hello), "-48656c6c6f20776f726c6421"); - assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); -} - -#[test] -fn test_upper_hex() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:X}", a), "A"); - assert_eq!(format!("{:X}", hello), "-48656C6C6F20776F726C6421"); - assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); -} - -#[test] -fn test_binary() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-224055342307539".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:b}", a), "1010"); - assert_eq!(format!("{:b}", hello), - "-110010111100011011110011000101101001100011010011"); - assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); -} - -#[test] -fn test_octal() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:o}", a), "12"); - assert_eq!(format!("{:o}", hello), "-22062554330674403566756233062041"); - assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); -} - -#[test] -fn test_display() { - let a = BigInt::parse_bytes(b"A", 16).unwrap(); - let hello = BigInt::parse_bytes("-22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{}", a), "10"); - assert_eq!(format!("{}", hello), "-22405534230753963835153736737"); - assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); -} - -#[test] -fn test_neg() { - assert!(-BigInt::new(Plus, vec![1, 1, 1]) == BigInt::new(Minus, vec![1, 1, 1])); - assert!(-BigInt::new(Minus, vec![1, 1, 1]) == BigInt::new(Plus, vec![1, 1, 1])); - let zero: BigInt = Zero::zero(); - assert_eq!(-&zero, zero); -} - -#[test] -fn test_rand() { - let mut rng = thread_rng(); - let _n: BigInt = rng.gen_bigint(137); - assert!(rng.gen_bigint(0).is_zero()); -} - -#[test] -fn test_rand_range() { - let mut rng = thread_rng(); - - for _ in 0..10 { - assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_usize(236).unwrap(), - &FromPrimitive::from_usize(237).unwrap()), - FromPrimitive::from_usize(236).unwrap()); - } - - fn check(l: BigInt, u: BigInt) { - let mut rng = thread_rng(); - for _ in 0..1000 { - let n: BigInt = rng.gen_bigint_range(&l, &u); - assert!(n >= l); - assert!(n < u); - } - } - let l: BigInt = FromPrimitive::from_usize(403469000 + 2352).unwrap(); - let u: BigInt = FromPrimitive::from_usize(403469000 + 3513).unwrap(); - check(l.clone(), u.clone()); - check(-l.clone(), u.clone()); - check(-u.clone(), -l.clone()); -} - -#[test] -#[should_panic] -fn test_zero_rand_range() { - thread_rng().gen_bigint_range(&FromPrimitive::from_isize(54).unwrap(), - &FromPrimitive::from_isize(54).unwrap()); -} - -#[test] -#[should_panic] -fn test_negative_rand_range() { - let mut rng = thread_rng(); - let l = FromPrimitive::from_usize(2352).unwrap(); - let u = FromPrimitive::from_usize(3513).unwrap(); - // Switching u and l should fail: - let _n: BigInt = rng.gen_bigint_range(&u, &l); -} diff --git a/bigint/src/tests/biguint.rs b/bigint/src/tests/biguint.rs deleted file mode 100644 index e27cc17..0000000 --- a/bigint/src/tests/biguint.rs +++ /dev/null @@ -1,1760 +0,0 @@ -use integer::Integer; -use {BigDigit, BigUint, ToBigUint, big_digit}; -use {BigInt, RandBigInt, ToBigInt}; -use Sign::Plus; - -use std::cmp::Ordering::{Less, Equal, Greater}; -use std::{f32, f64}; -use std::i64; -use std::iter::repeat; -use std::str::FromStr; -use std::{u8, u16, u32, u64, usize}; - -use rand::thread_rng; -use traits::{Num, Zero, One, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, ToPrimitive, - FromPrimitive, Float}; - - -/// Assert that an op works for all val/ref combinations -macro_rules! assert_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_eq!((&$left) $op (&$right), $expected); - assert_eq!((&$left) $op $right.clone(), $expected); - assert_eq!($left.clone() $op (&$right), $expected); - assert_eq!($left.clone() $op $right.clone(), $expected); - }; -} -/// Assert that an assign-op works for all val/ref combinations -macro_rules! assert_assign_op { - ($left:ident $op:tt $right:ident == $expected:expr) => { - { - let mut tmp12384 = $left.clone(); - assert_eq!({ tmp12384 $op &$right; tmp12384}, $expected); - - let mut tmp12384 = $left.clone(); - assert_eq!({ tmp12384 $op $right.clone(); tmp12384}, $expected); - } - }; -} - -/// Assert that an op works for scalar left or right -macro_rules! assert_scalar_op { - (($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => { - $( - if let Some(left) = $left.$to() { - assert_op!(left $op $right == $expected); - } - if let Some(right) = $right.$to() { - assert_op!($left $op right == $expected); - } - )* - }; - ($left:ident $op:tt $right:ident == $expected:expr) => { - assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize) - $left $op $right == $expected); - }; -} - -#[test] -fn test_from_slice() { - fn check(slice: &[BigDigit], data: &[BigDigit]) { - assert!(BigUint::from_slice(slice).data == 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(&[-1i32 as BigDigit], &[-1i32 as BigDigit]); -} - -#[test] -fn test_assign_from_slice() { - fn check(slice: &[BigDigit], data: &[BigDigit]) { - let mut p = BigUint::from_slice(&[2627_u32, 0_u32, 9182_u32, 42_u32]); - p.assign_from_slice(slice); - assert!(p.data == 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(&[-1i32 as BigDigit], &[-1i32 as BigDigit]); -} - -#[test] -fn test_from_bytes_be() { - fn check(s: &str, result: &str) { - assert_eq!(BigUint::from_bytes_be(s.as_bytes()), - BigUint::parse_bytes(result.as_bytes(), 10).unwrap()); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - assert_eq!(BigUint::from_bytes_be(&[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_be() { - fn check(s: &str, result: &str) { - let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); - assert_eq!(b.to_bytes_be(), s.as_bytes()); - } - check("A", "65"); - check("AA", "16705"); - check("AB", "16706"); - check("Hello world!", "22405534230753963835153736737"); - let b: BigUint = Zero::zero(); - assert_eq!(b.to_bytes_be(), [0]); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_be(), [1, 0, 0, 0, 0, 0, 0, 2, 0]); -} - -#[test] -fn test_from_bytes_le() { - fn check(s: &str, result: &str) { - assert_eq!(BigUint::from_bytes_le(s.as_bytes()), - BigUint::parse_bytes(result.as_bytes(), 10).unwrap()); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - assert_eq!(BigUint::from_bytes_le(&[]), Zero::zero()); -} - -#[test] -fn test_to_bytes_le() { - fn check(s: &str, result: &str) { - let b = BigUint::parse_bytes(result.as_bytes(), 10).unwrap(); - assert_eq!(b.to_bytes_le(), s.as_bytes()); - } - check("A", "65"); - check("AA", "16705"); - check("BA", "16706"); - check("!dlrow olleH", "22405534230753963835153736737"); - let b: BigUint = Zero::zero(); - assert_eq!(b.to_bytes_le(), [0]); - - // Test with leading/trailing zero bytes and a full BigDigit of value 0 - let b = BigUint::from_str_radix("00010000000000000200", 16).unwrap(); - assert_eq!(b.to_bytes_le(), [0, 2, 0, 0, 0, 0, 0, 0, 1]); -} - -#[test] -fn test_cmp() { - let data: [&[_]; 7] = [&[], &[1], &[2], &[!0], &[0, 1], &[2, 1], &[1, 1, 1]]; - let data: Vec = data.iter().map(|v| BigUint::from_slice(*v)).collect(); - for (i, ni) in data.iter().enumerate() { - for (j0, nj) in data[i..].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_hash() { - use hash; - - let a = BigUint::new(vec![]); - let b = BigUint::new(vec![0]); - let c = BigUint::new(vec![1]); - let d = BigUint::new(vec![1, 0, 0, 0, 0, 0]); - let e = BigUint::new(vec![0, 0, 0, 0, 0, 1]); - assert!(hash(&a) == hash(&b)); - assert!(hash(&b) != hash(&c)); - assert!(hash(&c) == hash(&d)); - assert!(hash(&d) != hash(&e)); -} - -const BIT_TESTS: &'static [(&'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit])] = &[// LEFT RIGHT AND OR XOR - (&[], &[], &[], &[], &[]), - (&[1, 0, 1], &[1, 1], &[1], &[1, 1, 1], &[0, 1, 1]), - (&[1, 0, 1], &[0, 1, 1], &[0, 0, 1], &[1, 1, 1], &[1, 1]), - (&[268, 482, 17], - &[964, 54], - &[260, 34], - &[972, 502, 17], - &[712, 468, 17])]; - -#[test] -fn test_bitand() { - for elm in BIT_TESTS { - let (a_vec, b_vec, c_vec, _, _) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a & b == c); - assert_op!(b & a == c); - assert_assign_op!(a &= b == c); - assert_assign_op!(b &= a == c); - } -} - -#[test] -fn test_bitor() { - for elm in BIT_TESTS { - let (a_vec, b_vec, _, c_vec, _) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a | b == c); - assert_op!(b | a == c); - assert_assign_op!(a |= b == c); - assert_assign_op!(b |= a == c); - } -} - -#[test] -fn test_bitxor() { - for elm in BIT_TESTS { - let (a_vec, b_vec, _, _, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a ^ b == c); - assert_op!(b ^ a == c); - assert_op!(a ^ c == b); - assert_op!(c ^ a == b); - assert_op!(b ^ c == a); - assert_op!(c ^ b == a); - assert_assign_op!(a ^= b == c); - assert_assign_op!(b ^= a == c); - assert_assign_op!(a ^= c == b); - assert_assign_op!(c ^= a == b); - assert_assign_op!(b ^= c == a); - assert_assign_op!(c ^= b == a); - } -} - -#[test] -fn test_shl() { - fn check(s: &str, shift: usize, ans: &str) { - let opt_biguint = BigUint::from_str_radix(s, 16).ok(); - let mut bu_assign = opt_biguint.unwrap(); - let bu = (bu_assign.clone() << shift).to_str_radix(16); - assert_eq!(bu, ans); - bu_assign <<= shift; - assert_eq!(bu_assign.to_str_radix(16), 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: usize, ans: &str) { - let opt_biguint = BigUint::from_str_radix(s, 16).ok(); - let mut bu_assign = opt_biguint.unwrap(); - let bu = (bu_assign.clone() >> shift).to_str_radix(16); - assert_eq!(bu, ans); - bu_assign >>= shift; - assert_eq!(bu_assign.to_str_radix(16), 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"); -} - -const N1: BigDigit = -1i32 as BigDigit; -const N2: BigDigit = -2i32 as BigDigit; - -// `DoubleBigDigit` size dependent -#[test] -fn test_convert_i64() { - fn check(b1: BigUint, i: i64) { - let b2: BigUint = FromPrimitive::from_i64(i).unwrap(); - assert_eq!(b1, b2); - assert_eq!(b1.to_i64().unwrap(), i); - } - - check(Zero::zero(), 0); - check(One::one(), 1); - check(i64::MAX.to_biguint().unwrap(), i64::MAX); - - check(BigUint::new(vec![]), 0); - check(BigUint::new(vec![1]), (1 << (0 * big_digit::BITS))); - check(BigUint::new(vec![N1]), (1 << (1 * big_digit::BITS)) - 1); - check(BigUint::new(vec![0, 1]), (1 << (1 * big_digit::BITS))); - check(BigUint::new(vec![N1, N1 >> 1]), i64::MAX); - - assert_eq!(i64::MIN.to_biguint(), None); - assert_eq!(BigUint::new(vec![N1, N1]).to_i64(), None); - assert_eq!(BigUint::new(vec![0, 0, 1]).to_i64(), None); - assert_eq!(BigUint::new(vec![N1, N1, N1]).to_i64(), None); -} - -// `DoubleBigDigit` size dependent -#[test] -fn test_convert_u64() { - fn check(b1: BigUint, u: u64) { - let b2: BigUint = FromPrimitive::from_u64(u).unwrap(); - assert_eq!(b1, b2); - assert_eq!(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(vec![]), 0); - check(BigUint::new(vec![1]), (1 << (0 * big_digit::BITS))); - check(BigUint::new(vec![N1]), (1 << (1 * big_digit::BITS)) - 1); - check(BigUint::new(vec![0, 1]), (1 << (1 * big_digit::BITS))); - check(BigUint::new(vec![N1, N1]), u64::MAX); - - assert_eq!(BigUint::new(vec![0, 0, 1]).to_u64(), None); - assert_eq!(BigUint::new(vec![N1, N1, N1]).to_u64(), None); -} - -#[test] -fn test_convert_f32() { - fn check(b1: &BigUint, f: f32) { - let b2 = BigUint::from_f32(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f32().unwrap(), f); - } - - check(&BigUint::zero(), 0.0); - check(&BigUint::one(), 1.0); - check(&BigUint::from(u16::MAX), 2.0.powi(16) - 1.0); - check(&BigUint::from(1u64 << 32), 2.0.powi(32)); - check(&BigUint::from_slice(&[0, 0, 1]), 2.0.powi(64)); - check(&((BigUint::one() << 100) + (BigUint::one() << 123)), - 2.0.powi(100) + 2.0.powi(123)); - check(&(BigUint::one() << 127), 2.0.powi(127)); - check(&(BigUint::from((1u64 << 24) - 1) << (128 - 24)), f32::MAX); - - // keeping all 24 digits with the bits at different offsets to the BigDigits - let x: u32 = 0b00000000101111011111011011011101; - let mut f = x as f32; - let mut b = BigUint::from(x); - for _ in 0..64 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // this number when rounded to f64 then f32 isn't the same as when rounded straight to f32 - let n: u64 = 0b0000000000111111111111111111111111011111111111111111111111111111; - assert!((n as f64) as f32 != n as f32); - assert_eq!(BigUint::from(n).to_f32(), Some(n as f32)); - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 25) - 1) as f32; - let mut b = BigUint::from(1u64 << 25); - for _ in 0..64 { - assert_eq!(b.to_f32(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!(BigUint::from_f32(-1.0), None); - assert_eq!(BigUint::from_f32(-0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(-0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(-0.0), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(f32::MIN_POSITIVE / 2.0), - Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(f32::MIN_POSITIVE), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f32(f32::consts::E), Some(BigUint::from(2u32))); - assert_eq!(BigUint::from_f32(f32::consts::PI), - Some(BigUint::from(3u32))); - - // special float values - assert_eq!(BigUint::from_f32(f32::NAN), None); - assert_eq!(BigUint::from_f32(f32::INFINITY), None); - assert_eq!(BigUint::from_f32(f32::NEG_INFINITY), None); - assert_eq!(BigUint::from_f32(f32::MIN), None); - - // largest BigUint that will round to a finite f32 value - let big_num = (BigUint::one() << 128) - BigUint::one() - (BigUint::one() << (128 - 25)); - assert_eq!(big_num.to_f32(), Some(f32::MAX)); - assert_eq!((big_num + BigUint::one()).to_f32(), None); - - assert_eq!(((BigUint::one() << 128) - BigUint::one()).to_f32(), None); - assert_eq!((BigUint::one() << 128).to_f32(), None); -} - -#[test] -fn test_convert_f64() { - fn check(b1: &BigUint, f: f64) { - let b2 = BigUint::from_f64(f).unwrap(); - assert_eq!(b1, &b2); - assert_eq!(b1.to_f64().unwrap(), f); - } - - check(&BigUint::zero(), 0.0); - check(&BigUint::one(), 1.0); - check(&BigUint::from(u32::MAX), 2.0.powi(32) - 1.0); - check(&BigUint::from(1u64 << 32), 2.0.powi(32)); - check(&BigUint::from_slice(&[0, 0, 1]), 2.0.powi(64)); - check(&((BigUint::one() << 100) + (BigUint::one() << 152)), - 2.0.powi(100) + 2.0.powi(152)); - check(&(BigUint::one() << 1023), 2.0.powi(1023)); - check(&(BigUint::from((1u64 << 53) - 1) << (1024 - 53)), f64::MAX); - - // keeping all 53 digits with the bits at different offsets to the BigDigits - let x: u64 = 0b0000000000011110111110110111111101110111101111011111011011011101; - let mut f = x as f64; - let mut b = BigUint::from(x); - for _ in 0..128 { - check(&b, f); - f *= 2.0; - b = b << 1; - } - - // test rounding up with the bits at different offsets to the BigDigits - let mut f = ((1u64 << 54) - 1) as f64; - let mut b = BigUint::from(1u64 << 54); - for _ in 0..128 { - assert_eq!(b.to_f64(), Some(f)); - f *= 2.0; - b = b << 1; - } - - // rounding - assert_eq!(BigUint::from_f64(-1.0), None); - assert_eq!(BigUint::from_f64(-0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(-0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(-0.0), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(f64::MIN_POSITIVE / 2.0), - Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(f64::MIN_POSITIVE), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(0.5), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(0.99999), Some(BigUint::zero())); - assert_eq!(BigUint::from_f64(f64::consts::E), Some(BigUint::from(2u32))); - assert_eq!(BigUint::from_f64(f64::consts::PI), - Some(BigUint::from(3u32))); - - // special float values - assert_eq!(BigUint::from_f64(f64::NAN), None); - assert_eq!(BigUint::from_f64(f64::INFINITY), None); - assert_eq!(BigUint::from_f64(f64::NEG_INFINITY), None); - assert_eq!(BigUint::from_f64(f64::MIN), None); - - // largest BigUint that will round to a finite f64 value - let big_num = (BigUint::one() << 1024) - BigUint::one() - (BigUint::one() << (1024 - 54)); - assert_eq!(big_num.to_f64(), Some(f64::MAX)); - assert_eq!((big_num + BigUint::one()).to_f64(), None); - - assert_eq!(((BigInt::one() << 1024) - BigInt::one()).to_f64(), None); - assert_eq!((BigUint::one() << 1024).to_f64(), 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(vec![1, 2, 3]), - BigInt::from_biguint(Plus, BigUint::new(vec![1, 2, 3]))); -} - -#[test] -fn test_convert_from_uint() { - macro_rules! check { - ($ty:ident, $max:expr) => { - assert_eq!(BigUint::from($ty::zero()), BigUint::zero()); - assert_eq!(BigUint::from($ty::one()), BigUint::one()); - assert_eq!(BigUint::from($ty::MAX - $ty::one()), $max - BigUint::one()); - assert_eq!(BigUint::from($ty::MAX), $max); - } - } - - check!(u8, BigUint::from_slice(&[u8::MAX as BigDigit])); - check!(u16, BigUint::from_slice(&[u16::MAX as BigDigit])); - check!(u32, BigUint::from_slice(&[u32::MAX])); - check!(u64, BigUint::from_slice(&[u32::MAX, u32::MAX])); - check!(usize, BigUint::from(usize::MAX as u64)); -} - -const SUM_TRIPLES: &'static [(&'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit])] = &[(&[], &[], &[]), - (&[], &[1], &[1]), - (&[1], &[1], &[2]), - (&[1], &[1, 1], &[2, 1]), - (&[1], &[N1], &[0, 1]), - (&[1], &[N1, N1], &[0, 0, 1]), - (&[N1, N1], &[N1, N1], &[N2, N1, 1]), - (&[1, 1, 1], &[N1, N1], &[0, 1, 2]), - (&[2, 2, 1], &[N1, N2], &[1, 1, 2])]; - -#[test] -fn test_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a + b == c); - assert_op!(b + a == c); - assert_assign_op!(a += b == c); - assert_assign_op!(b += a == c); - } -} - -#[test] -fn test_scalar_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_scalar_op!(a + b == c); - assert_scalar_op!(b + a == c); - } -} - -#[test] -fn test_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(c - a == b); - assert_op!(c - b == a); - assert_assign_op!(c -= a == b); - assert_assign_op!(c -= b == a); - } -} - -#[test] -fn test_scalar_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_scalar_op!(c - a == b); - assert_scalar_op!(c - b == a); - } -} - -#[test] -#[should_panic] -fn test_sub_fail_on_underflow() { - let (a, b): (BigUint, BigUint) = (Zero::zero(), One::one()); - a - b; -} - -const M: u32 = ::std::u32::MAX; -const 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], &[N1], &[N1, N1, N1]), - (&[1, 2, 3], &[N1], &[N1, N2, N2, 2]), - (&[1, 2, 3, 4], &[N1], &[N1, N2, N2, N2, 3]), - (&[N1], &[N1], &[1, N2]), - (&[N1, N1], &[N1], &[1, N1, N2]), - (&[N1, N1, N1], &[N1], &[1, N1, N1, N2]), - (&[N1, N1, N1, N1], &[N1], &[1, N1, N1, N1, N2]), - (&[M / 2 + 1], &[2], &[0, 1]), - (&[0, M / 2 + 1], &[2], &[0, 0, 1]), - (&[1, 2], &[1, 2, 3], &[1, 4, 7, 6]), - (&[N1, N1], &[N1, N1, N1], &[1, 0, N1, N2, N1]), - (&[N1, N1, N1], - &[N1, N1, N1, N1], - &[1, 0, 0, N1, N2, N1, N1]), - (&[0, 0, 1], &[1, 2, 3], &[0, 0, 1, 2, 3]), - (&[0, 0, 1], &[0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])]; - -const DIV_REM_QUADRUPLES: &'static [(&'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit])] = &[(&[1], &[2], &[], &[1]), - (&[3], &[2], &[1], &[1]), - (&[1, 1], &[2], &[M / 2 + 1], &[1]), - (&[1, 1, 1], &[2], &[M / 2 + 1, M / 2 + 1], &[1]), - (&[0, 1], &[N1], &[1], &[1]), - (&[N1, N1], &[N2], &[2, 1], &[3])]; - -#[test] -fn test_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_op!(a * b == c); - assert_op!(b * a == c); - assert_assign_op!(a *= b == c); - assert_assign_op!(b *= a == c); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - assert!(a == &b * &c + &d); - assert!(a == &c * &b + &d); - } -} - -#[test] -fn test_scalar_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert_scalar_op!(a * b == c); - assert_scalar_op!(b * a == c); - } -} - -#[test] -fn test_div_rem() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - if !a.is_zero() { - assert_op!(c / a == b); - assert_op!(c % a == Zero::zero()); - assert_assign_op!(c /= a == b); - assert_assign_op!(c %= a == Zero::zero()); - assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero())); - } - if !b.is_zero() { - assert_op!(c / b == a); - assert_op!(c % b == Zero::zero()); - assert_assign_op!(c /= b == a); - assert_assign_op!(c %= b == Zero::zero()); - assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero())); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - if !b.is_zero() { - assert_op!(a / b == c); - assert_op!(a % b == d); - assert_assign_op!(a /= b == c); - assert_assign_op!(a %= b == d); - assert!(a.div_rem(&b) == (c, d)); - } - } -} - -#[test] -fn test_scalar_div_rem() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - if !a.is_zero() { - assert_scalar_op!(c / a == b); - assert_scalar_op!(c % a == Zero::zero()); - } - - if !b.is_zero() { - assert_scalar_op!(c / b == a); - assert_scalar_op!(c % b == Zero::zero()); - } - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - if !b.is_zero() { - assert_scalar_op!(a / b == c); - assert_scalar_op!(a % b == d); - } - } -} - -#[test] -fn test_checked_add() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert!(a.checked_add(&b).unwrap() == c); - assert!(b.checked_add(&a).unwrap() == c); - } -} - -#[test] -fn test_checked_sub() { - for elm in SUM_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert!(c.checked_sub(&a).unwrap() == b); - assert!(c.checked_sub(&b).unwrap() == a); - - if a > c { - assert!(a.checked_sub(&c).is_none()); - } - if b > c { - assert!(b.checked_sub(&c).is_none()); - } - } -} - -#[test] -fn test_checked_mul() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - assert!(a.checked_mul(&b).unwrap() == c); - assert!(b.checked_mul(&a).unwrap() == c); - } - - for elm in DIV_REM_QUADRUPLES.iter() { - let (a_vec, b_vec, c_vec, d_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - let d = BigUint::from_slice(d_vec); - - assert!(a == b.checked_mul(&c).unwrap() + &d); - assert!(a == c.checked_mul(&b).unwrap() + &d); - } -} - -#[test] -fn test_mul_overflow() { - /* Test for issue #187 - overflow due to mac3 incorrectly sizing temporary */ - let s = "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502232636710047537552105951370000796528760829212940754539968588340162273730474622005920097370111"; - let a: BigUint = s.parse().unwrap(); - let b = a.clone(); - let _ = a.checked_mul(&b); -} - -#[test] -fn test_checked_div() { - for elm in MUL_TRIPLES.iter() { - let (a_vec, b_vec, c_vec) = *elm; - let a = BigUint::from_slice(a_vec); - let b = BigUint::from_slice(b_vec); - let c = BigUint::from_slice(c_vec); - - if !a.is_zero() { - assert!(c.checked_div(&a).unwrap() == b); - } - if !b.is_zero() { - assert!(c.checked_div(&b).unwrap() == a); - } - - assert!(c.checked_div(&Zero::zero()).is_none()); - } -} - -#[test] -fn test_gcd() { - fn check(a: usize, b: usize, c: usize) { - let big_a: BigUint = FromPrimitive::from_usize(a).unwrap(); - let big_b: BigUint = FromPrimitive::from_usize(b).unwrap(); - let big_c: BigUint = FromPrimitive::from_usize(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: usize, b: usize, c: usize) { - let big_a: BigUint = FromPrimitive::from_usize(a).unwrap(); - let big_b: BigUint = FromPrimitive::from_usize(b).unwrap(); - let big_c: BigUint = FromPrimitive::from_usize(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()); -} - -#[test] -fn test_modpow() { - fn check(b: usize, e: usize, m: usize, r: usize) { - let big_b = BigUint::from(b); - let big_e = BigUint::from(e); - let big_m = BigUint::from(m); - let big_r = BigUint::from(r); - - assert_eq!(big_b.modpow(&big_e, &big_m), big_r); - - let even_m = &big_m << 1; - let even_modpow = big_b.modpow(&big_e, &even_m); - assert!(even_modpow < even_m); - assert_eq!(even_modpow % big_m, big_r); - } - - check(1, 0, 11, 1); - check(0, 15, 11, 0); - check(3, 7, 11, 9); - check(5, 117, 19, 1); -} - -#[test] -fn test_modpow_big() { - let b = BigUint::from_str_radix("\ - efac3c0a_0de55551_fee0bfe4_67fa017a_1a898fa1_6ca57cb1\ - ca9e3248_cacc09a9_b99d6abc_38418d0f_82ae4238_d9a68832\ - aadec7c1_ac5fed48_7a56a71b_67ac59d5_afb28022_20d9592d\ - 247c4efc_abbd9b75_586088ee_1dc00dc4_232a8e15_6e8191dd\ - 675b6ae0_c80f5164_752940bc_284b7cee_885c1e10_e495345b\ - 8fbe9cfd_e5233fe1_19459d0b_d64be53c_27de5a02_a829976b\ - 33096862_82dad291_bd38b6a9_be396646_ddaf8039_a2573c39\ - 1b14e8bc_2cb53e48_298c047e_d9879e9c_5a521076_f0e27df3\ - 990e1659_d3d8205b_6443ebc0_9918ebee_6764f668_9f2b2be3\ - b59cbc76_d76d0dfc_d737c3ec_0ccf9c00_ad0554bf_17e776ad\ - b4edf9cc_6ce540be_76229093_5c53893b", 16).unwrap(); - let e = BigUint::from_str_radix("\ - be0e6ea6_08746133_e0fbc1bf_82dba91e_e2b56231_a81888d2\ - a833a1fc_f7ff002a_3c486a13_4f420bf3_a5435be9_1a5c8391\ - 774d6e6c_085d8357_b0c97d4d_2bb33f7c_34c68059_f78d2541\ - eacc8832_426f1816_d3be001e_b69f9242_51c7708e_e10efe98\ - 449c9a4a_b55a0f23_9d797410_515da00d_3ea07970_4478a2ca\ - c3d5043c_bd9be1b4_6dce479d_4302d344_84a939e6_0ab5ada7\ - 12ae34b2_30cc473c_9f8ee69d_2cac5970_29f5bf18_bc8203e4\ - f3e895a2_13c94f1e_24c73d77_e517e801_53661fdd_a2ce9e47\ - a73dd7f8_2f2adb1e_3f136bf7_8ae5f3b8_08730de1_a4eff678\ - e77a06d0_19a522eb_cbefba2a_9caf7736_b157c5c6_2d192591\ - 17946850_2ddb1822_117b68a0_32f7db88", 16).unwrap(); - // This modulus is the prime from the 2048-bit MODP DH group: - // https://tools.ietf.org/html/rfc3526#section-3 - let m = BigUint::from_str_radix("\ - FFFFFFFF_FFFFFFFF_C90FDAA2_2168C234_C4C6628B_80DC1CD1\ - 29024E08_8A67CC74_020BBEA6_3B139B22_514A0879_8E3404DD\ - EF9519B3_CD3A431B_302B0A6D_F25F1437_4FE1356D_6D51C245\ - E485B576_625E7EC6_F44C42E9_A637ED6B_0BFF5CB6_F406B7ED\ - EE386BFB_5A899FA5_AE9F2411_7C4B1FE6_49286651_ECE45B3D\ - C2007CB8_A163BF05_98DA4836_1C55D39A_69163FA8_FD24CF5F\ - 83655D23_DCA3AD96_1C62F356_208552BB_9ED52907_7096966D\ - 670C354E_4ABC9804_F1746C08_CA18217C_32905E46_2E36CE3B\ - E39E772C_180E8603_9B2783A2_EC07A28F_B5C55DF0_6F4C52C9\ - DE2BCBF6_95581718_3995497C_EA956AE5_15D22618_98FA0510\ - 15728E5A_8AACAA68_FFFFFFFF_FFFFFFFF", 16).unwrap(); - let r = BigUint::from_str_radix("\ - a1468311_6e56edc9_7a98228b_5e924776_0dd7836e_caabac13\ - eda5373b_4752aa65_a1454850_40dc770e_30aa8675_6be7d3a8\ - 9d3085e4_da5155cf_b451ef62_54d0da61_cf2b2c87_f495e096\ - 055309f7_77802bbb_37271ba8_1313f1b5_075c75d1_024b6c77\ - fdb56f17_b05bce61_e527ebfd_2ee86860_e9907066_edd526e7\ - 93d289bf_6726b293_41b0de24_eff82424_8dfd374b_4ec59542\ - 35ced2b2_6b195c90_10042ffb_8f58ce21_bc10ec42_64fda779\ - d352d234_3d4eaea6_a86111ad_a37e9555_43ca78ce_2885bed7\ - 5a30d182_f1cf6834_dc5b6e27_1a41ac34_a2e91e11_33363ff0\ - f88a7b04_900227c9_f6e6d06b_7856b4bb_4e354d61_060db6c8\ - 109c4735_6e7db425_7b5d74c7_0b709508", 16).unwrap(); - - assert_eq!(b.modpow(&e, &m), r); - - let even_m = &m << 1; - let even_modpow = b.modpow(&e, &even_m); - assert!(even_modpow < even_m); - assert_eq!(even_modpow % m, r); -} - -fn to_str_pairs() -> Vec<(BigUint, Vec<(u32, String)>)> { - let bits = big_digit::BITS; - vec![(Zero::zero(), - vec![(2, "0".to_string()), (3, "0".to_string())]), - (BigUint::from_slice(&[0xff]), - vec![(2, "11111111".to_string()), - (3, "100110".to_string()), - (4, "3333".to_string()), - (5, "2010".to_string()), - (6, "1103".to_string()), - (7, "513".to_string()), - (8, "377".to_string()), - (9, "313".to_string()), - (10, "255".to_string()), - (11, "212".to_string()), - (12, "193".to_string()), - (13, "168".to_string()), - (14, "143".to_string()), - (15, "120".to_string()), - (16, "ff".to_string())]), - (BigUint::from_slice(&[0xfff]), - vec![(2, "111111111111".to_string()), - (4, "333333".to_string()), - (16, "fff".to_string())]), - (BigUint::from_slice(&[1, 2]), - vec![(2, - format!("10{}1", repeat("0").take(bits - 1).collect::())), - (4, - format!("2{}1", repeat("0").take(bits / 2 - 1).collect::())), - (10, - match bits { - 64 => "36893488147419103233".to_string(), - 32 => "8589934593".to_string(), - 16 => "131073".to_string(), - _ => panic!(), - }), - (16, - format!("2{}1", repeat("0").take(bits / 4 - 1).collect::()))]), - (BigUint::from_slice(&[1, 2, 3]), - vec![(2, - format!("11{}10{}1", - repeat("0").take(bits - 2).collect::(), - repeat("0").take(bits - 1).collect::())), - (4, - format!("3{}2{}1", - repeat("0").take(bits / 2 - 1).collect::(), - repeat("0").take(bits / 2 - 1).collect::())), - (8, - match bits { - 64 => "14000000000000000000004000000000000000000001".to_string(), - 32 => "6000000000100000000001".to_string(), - 16 => "140000400001".to_string(), - _ => panic!(), - }), - (10, - match bits { - 64 => "1020847100762815390427017310442723737601".to_string(), - 32 => "55340232229718589441".to_string(), - 16 => "12885032961".to_string(), - _ => panic!(), - }), - (16, - format!("3{}2{}1", - repeat("0").take(bits / 4 - 1).collect::(), - repeat("0").take(bits / 4 - 1).collect::()))])] -} - -#[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_and_to_radix() { - const GROUND_TRUTH : &'static[(&'static[u8], u32, &'static[u8])] = &[ - (b"0", 42, &[0]), - (b"ffffeeffbb", 2, &[1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), - (b"ffffeeffbb", 3, &[2, 2, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 1, 2, - 0, 0, 0, 0, 1, 0, 0, 2, 2, 0, 1]), - (b"ffffeeffbb", 4, &[3, 2, 3, 2, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, - 3, 3, 3, 3, 3]), - (b"ffffeeffbb", 5, &[0, 4, 3, 3, 1, 4, 2, 4, 1, 4, 4, 2, 3, 0, 0, - 1, 2, 1]), - (b"ffffeeffbb", 6, &[5, 5, 4, 5, 5, 0, 0, 1, 2, 5, 3, 0, 1, 0, 2, 2]), - (b"ffffeeffbb", 7, &[4, 2, 3, 6, 0, 1, 6, 1, 6, 2, 0, 3, 2, 4, 1]), - (b"ffffeeffbb", 8, &[3, 7, 6, 7, 7, 5, 3, 7, 7, 7, 7, 7, 7, 1]), - (b"ffffeeffbb", 9, &[8, 4, 5, 7, 0, 0, 3, 2, 0, 3, 0, 8, 3]), - (b"ffffeeffbb", 10, &[5, 9, 5, 3, 1, 5, 0, 1, 5, 9, 9, 0, 1]), - (b"ffffeeffbb", 11, &[10, 7, 6, 5, 2, 0, 3, 3, 3, 4, 9, 3]), - (b"ffffeeffbb", 12, &[11, 8, 5, 10, 1, 10, 3, 1, 1, 9, 5, 1]), - (b"ffffeeffbb", 13, &[0, 5, 7, 4, 6, 5, 6, 11, 8, 12, 7]), - (b"ffffeeffbb", 14, &[11, 4, 4, 11, 8, 4, 6, 0, 3, 11, 3]), - (b"ffffeeffbb", 15, &[5, 11, 13, 2, 1, 10, 2, 0, 9, 13, 1]), - (b"ffffeeffbb", 16, &[11, 11, 15, 15, 14, 14, 15, 15, 15, 15]), - (b"ffffeeffbb", 17, &[0, 2, 14, 12, 2, 14, 8, 10, 4, 9]), - (b"ffffeeffbb", 18, &[17, 15, 5, 13, 10, 16, 16, 13, 9, 5]), - (b"ffffeeffbb", 19, &[14, 13, 2, 8, 9, 0, 1, 14, 7, 3]), - (b"ffffeeffbb", 20, &[15, 19, 3, 14, 0, 17, 19, 18, 2, 2]), - (b"ffffeeffbb", 21, &[11, 5, 4, 13, 5, 18, 9, 1, 8, 1]), - (b"ffffeeffbb", 22, &[21, 3, 7, 21, 15, 12, 17, 0, 20]), - (b"ffffeeffbb", 23, &[21, 21, 6, 9, 10, 7, 21, 0, 14]), - (b"ffffeeffbb", 24, &[11, 10, 19, 14, 22, 11, 17, 23, 9]), - (b"ffffeeffbb", 25, &[20, 18, 21, 22, 21, 14, 3, 5, 7]), - (b"ffffeeffbb", 26, &[13, 15, 24, 11, 17, 6, 23, 6, 5]), - (b"ffffeeffbb", 27, &[17, 16, 7, 0, 21, 0, 3, 24, 3]), - (b"ffffeeffbb", 28, &[11, 16, 11, 15, 14, 18, 13, 25, 2]), - (b"ffffeeffbb", 29, &[6, 8, 7, 19, 14, 13, 21, 5, 2]), - (b"ffffeeffbb", 30, &[5, 13, 18, 11, 10, 7, 8, 20, 1]), - (b"ffffeeffbb", 31, &[22, 26, 15, 19, 8, 27, 29, 8, 1]), - (b"ffffeeffbb", 32, &[27, 29, 31, 29, 30, 31, 31, 31]), - (b"ffffeeffbb", 33, &[32, 20, 27, 12, 1, 12, 26, 25]), - (b"ffffeeffbb", 34, &[17, 9, 16, 33, 13, 25, 31, 20]), - (b"ffffeeffbb", 35, &[25, 32, 2, 25, 11, 4, 3, 17]), - (b"ffffeeffbb", 36, &[35, 34, 5, 6, 32, 3, 1, 14]), - (b"ffffeeffbb", 37, &[16, 21, 18, 4, 33, 19, 21, 11]), - (b"ffffeeffbb", 38, &[33, 25, 19, 29, 20, 6, 23, 9]), - (b"ffffeeffbb", 39, &[26, 27, 29, 23, 16, 18, 0, 8]), - (b"ffffeeffbb", 40, &[35, 39, 30, 11, 16, 17, 28, 6]), - (b"ffffeeffbb", 41, &[36, 30, 9, 18, 12, 19, 26, 5]), - (b"ffffeeffbb", 42, &[11, 34, 37, 27, 1, 13, 32, 4]), - (b"ffffeeffbb", 43, &[3, 24, 11, 2, 10, 40, 1, 4]), - (b"ffffeeffbb", 44, &[43, 12, 40, 32, 3, 23, 19, 3]), - (b"ffffeeffbb", 45, &[35, 38, 44, 18, 22, 18, 42, 2]), - (b"ffffeeffbb", 46, &[21, 45, 18, 41, 17, 2, 24, 2]), - (b"ffffeeffbb", 47, &[37, 37, 11, 12, 6, 0, 8, 2]), - (b"ffffeeffbb", 48, &[11, 41, 40, 43, 5, 43, 41, 1]), - (b"ffffeeffbb", 49, &[18, 45, 7, 13, 20, 21, 30, 1]), - (b"ffffeeffbb", 50, &[45, 21, 5, 34, 21, 18, 20, 1]), - (b"ffffeeffbb", 51, &[17, 6, 26, 22, 38, 24, 11, 1]), - (b"ffffeeffbb", 52, &[39, 33, 38, 30, 46, 31, 3, 1]), - (b"ffffeeffbb", 53, &[31, 7, 44, 23, 9, 32, 49]), - (b"ffffeeffbb", 54, &[17, 35, 8, 37, 31, 18, 44]), - (b"ffffeeffbb", 55, &[10, 52, 9, 48, 36, 39, 39]), - (b"ffffeeffbb", 56, &[11, 50, 51, 22, 25, 36, 35]), - (b"ffffeeffbb", 57, &[14, 55, 12, 43, 20, 3, 32]), - (b"ffffeeffbb", 58, &[35, 18, 45, 56, 9, 51, 28]), - (b"ffffeeffbb", 59, &[51, 28, 20, 26, 55, 3, 26]), - (b"ffffeeffbb", 60, &[35, 6, 27, 46, 58, 33, 23]), - (b"ffffeeffbb", 61, &[58, 7, 6, 54, 49, 20, 21]), - (b"ffffeeffbb", 62, &[53, 59, 3, 14, 10, 22, 19]), - (b"ffffeeffbb", 63, &[53, 50, 23, 4, 56, 36, 17]), - (b"ffffeeffbb", 64, &[59, 62, 47, 59, 63, 63, 15]), - (b"ffffeeffbb", 65, &[0, 53, 39, 4, 40, 37, 14]), - (b"ffffeeffbb", 66, &[65, 59, 39, 1, 64, 19, 13]), - (b"ffffeeffbb", 67, &[35, 14, 19, 16, 25, 10, 12]), - (b"ffffeeffbb", 68, &[51, 38, 63, 50, 15, 8, 11]), - (b"ffffeeffbb", 69, &[44, 45, 18, 58, 68, 12, 10]), - (b"ffffeeffbb", 70, &[25, 51, 0, 60, 13, 24, 9]), - (b"ffffeeffbb", 71, &[54, 30, 9, 65, 28, 41, 8]), - (b"ffffeeffbb", 72, &[35, 35, 55, 54, 17, 64, 7]), - (b"ffffeeffbb", 73, &[34, 4, 48, 40, 27, 19, 7]), - (b"ffffeeffbb", 74, &[53, 47, 4, 56, 36, 51, 6]), - (b"ffffeeffbb", 75, &[20, 56, 10, 72, 24, 13, 6]), - (b"ffffeeffbb", 76, &[71, 31, 52, 60, 48, 53, 5]), - (b"ffffeeffbb", 77, &[32, 73, 14, 63, 15, 21, 5]), - (b"ffffeeffbb", 78, &[65, 13, 17, 32, 64, 68, 4]), - (b"ffffeeffbb", 79, &[37, 56, 2, 56, 25, 41, 4]), - (b"ffffeeffbb", 80, &[75, 59, 37, 41, 43, 15, 4]), - (b"ffffeeffbb", 81, &[44, 68, 0, 21, 27, 72, 3]), - (b"ffffeeffbb", 82, &[77, 35, 2, 74, 46, 50, 3]), - (b"ffffeeffbb", 83, &[52, 51, 19, 76, 10, 30, 3]), - (b"ffffeeffbb", 84, &[11, 80, 19, 19, 76, 10, 3]), - (b"ffffeeffbb", 85, &[0, 82, 20, 14, 68, 77, 2]), - (b"ffffeeffbb", 86, &[3, 12, 78, 37, 62, 61, 2]), - (b"ffffeeffbb", 87, &[35, 12, 20, 8, 52, 46, 2]), - (b"ffffeeffbb", 88, &[43, 6, 54, 42, 30, 32, 2]), - (b"ffffeeffbb", 89, &[49, 52, 85, 21, 80, 18, 2]), - (b"ffffeeffbb", 90, &[35, 64, 78, 24, 18, 6, 2]), - (b"ffffeeffbb", 91, &[39, 17, 83, 63, 17, 85, 1]), - (b"ffffeeffbb", 92, &[67, 22, 85, 79, 75, 74, 1]), - (b"ffffeeffbb", 93, &[53, 60, 39, 29, 4, 65, 1]), - (b"ffffeeffbb", 94, &[37, 89, 2, 72, 76, 55, 1]), - (b"ffffeeffbb", 95, &[90, 74, 89, 9, 9, 47, 1]), - (b"ffffeeffbb", 96, &[59, 20, 46, 35, 81, 38, 1]), - (b"ffffeeffbb", 97, &[94, 87, 60, 71, 3, 31, 1]), - (b"ffffeeffbb", 98, &[67, 22, 63, 50, 62, 23, 1]), - (b"ffffeeffbb", 99, &[98, 6, 69, 12, 61, 16, 1]), - (b"ffffeeffbb", 100, &[95, 35, 51, 10, 95, 9, 1]), - (b"ffffeeffbb", 101, &[87, 27, 7, 8, 62, 3, 1]), - (b"ffffeeffbb", 102, &[17, 3, 32, 79, 59, 99]), - (b"ffffeeffbb", 103, &[30, 22, 90, 0, 87, 94]), - (b"ffffeeffbb", 104, &[91, 68, 87, 68, 38, 90]), - (b"ffffeeffbb", 105, &[95, 80, 54, 73, 15, 86]), - (b"ffffeeffbb", 106, &[31, 30, 24, 16, 17, 82]), - (b"ffffeeffbb", 107, &[51, 50, 10, 12, 42, 78]), - (b"ffffeeffbb", 108, &[71, 71, 96, 78, 89, 74]), - (b"ffffeeffbb", 109, &[33, 18, 93, 22, 50, 71]), - (b"ffffeeffbb", 110, &[65, 53, 57, 88, 29, 68]), - (b"ffffeeffbb", 111, &[53, 93, 67, 90, 27, 65]), - (b"ffffeeffbb", 112, &[11, 109, 96, 65, 43, 62]), - (b"ffffeeffbb", 113, &[27, 23, 106, 56, 76, 59]), - (b"ffffeeffbb", 114, &[71, 84, 31, 112, 11, 57]), - (b"ffffeeffbb", 115, &[90, 22, 1, 56, 76, 54]), - (b"ffffeeffbb", 116, &[35, 38, 98, 57, 40, 52]), - (b"ffffeeffbb", 117, &[26, 113, 115, 62, 17, 50]), - (b"ffffeeffbb", 118, &[51, 14, 5, 18, 7, 48]), - (b"ffffeeffbb", 119, &[102, 31, 110, 108, 8, 46]), - (b"ffffeeffbb", 120, &[35, 93, 96, 50, 22, 44]), - (b"ffffeeffbb", 121, &[87, 61, 2, 36, 47, 42]), - (b"ffffeeffbb", 122, &[119, 64, 1, 22, 83, 40]), - (b"ffffeeffbb", 123, &[77, 119, 32, 90, 6, 39]), - (b"ffffeeffbb", 124, &[115, 122, 31, 79, 62, 37]), - (b"ffffeeffbb", 125, &[95, 108, 47, 74, 3, 36]), - (b"ffffeeffbb", 126, &[53, 25, 116, 39, 78, 34]), - (b"ffffeeffbb", 127, &[22, 23, 125, 67, 35, 33]), - (b"ffffeeffbb", 128, &[59, 127, 59, 127, 127, 31]), - (b"ffffeeffbb", 129, &[89, 36, 1, 59, 100, 30]), - (b"ffffeeffbb", 130, &[65, 91, 123, 89, 79, 29]), - (b"ffffeeffbb", 131, &[58, 72, 39, 63, 65, 28]), - (b"ffffeeffbb", 132, &[131, 62, 92, 82, 57, 27]), - (b"ffffeeffbb", 133, &[109, 31, 51, 123, 55, 26]), - (b"ffffeeffbb", 134, &[35, 74, 21, 27, 60, 25]), - (b"ffffeeffbb", 135, &[125, 132, 49, 37, 70, 24]), - (b"ffffeeffbb", 136, &[51, 121, 117, 133, 85, 23]), - (b"ffffeeffbb", 137, &[113, 60, 135, 22, 107, 22]), - (b"ffffeeffbb", 138, &[113, 91, 73, 93, 133, 21]), - (b"ffffeeffbb", 139, &[114, 75, 102, 51, 26, 21]), - (b"ffffeeffbb", 140, &[95, 25, 35, 16, 62, 20]), - (b"ffffeeffbb", 141, &[131, 137, 16, 110, 102, 19]), - (b"ffffeeffbb", 142, &[125, 121, 108, 34, 6, 19]), - (b"ffffeeffbb", 143, &[65, 78, 138, 55, 55, 18]), - (b"ffffeeffbb", 144, &[107, 125, 121, 15, 109, 17]), - (b"ffffeeffbb", 145, &[35, 13, 122, 42, 22, 17]), - (b"ffffeeffbb", 146, &[107, 38, 103, 123, 83, 16]), - (b"ffffeeffbb", 147, &[116, 96, 71, 98, 2, 16]), - (b"ffffeeffbb", 148, &[127, 23, 75, 99, 71, 15]), - (b"ffffeeffbb", 149, &[136, 110, 53, 114, 144, 14]), - (b"ffffeeffbb", 150, &[95, 140, 133, 130, 71, 14]), - (b"ffffeeffbb", 151, &[15, 50, 29, 137, 0, 14]), - (b"ffffeeffbb", 152, &[147, 15, 89, 121, 83, 13]), - (b"ffffeeffbb", 153, &[17, 87, 93, 72, 17, 13]), - (b"ffffeeffbb", 154, &[109, 113, 3, 133, 106, 12]), - (b"ffffeeffbb", 155, &[115, 141, 120, 139, 44, 12]), - (b"ffffeeffbb", 156, &[143, 45, 4, 82, 140, 11]), - (b"ffffeeffbb", 157, &[149, 92, 15, 106, 82, 11]), - (b"ffffeeffbb", 158, &[37, 107, 79, 46, 26, 11]), - (b"ffffeeffbb", 159, &[137, 37, 146, 51, 130, 10]), - (b"ffffeeffbb", 160, &[155, 69, 29, 115, 77, 10]), - (b"ffffeeffbb", 161, &[67, 98, 46, 68, 26, 10]), - (b"ffffeeffbb", 162, &[125, 155, 60, 63, 138, 9]), - (b"ffffeeffbb", 163, &[96, 43, 118, 93, 90, 9]), - (b"ffffeeffbb", 164, &[159, 99, 123, 152, 43, 9]), - (b"ffffeeffbb", 165, &[65, 17, 1, 69, 163, 8]), - (b"ffffeeffbb", 166, &[135, 108, 25, 165, 119, 8]), - (b"ffffeeffbb", 167, &[165, 116, 164, 103, 77, 8]), - (b"ffffeeffbb", 168, &[11, 166, 67, 44, 36, 8]), - (b"ffffeeffbb", 169, &[65, 59, 71, 149, 164, 7]), - (b"ffffeeffbb", 170, &[85, 83, 26, 76, 126, 7]), - (b"ffffeeffbb", 171, &[71, 132, 140, 157, 88, 7]), - (b"ffffeeffbb", 172, &[3, 6, 127, 47, 52, 7]), - (b"ffffeeffbb", 173, &[122, 66, 53, 83, 16, 7]), - (b"ffffeeffbb", 174, &[35, 6, 5, 88, 155, 6]), - (b"ffffeeffbb", 175, &[95, 20, 84, 56, 122, 6]), - (b"ffffeeffbb", 176, &[43, 91, 57, 159, 89, 6]), - (b"ffffeeffbb", 177, &[110, 127, 54, 40, 58, 6]), - (b"ffffeeffbb", 178, &[49, 115, 43, 47, 27, 6]), - (b"ffffeeffbb", 179, &[130, 91, 4, 178, 175, 5]), - (b"ffffeeffbb", 180, &[35, 122, 109, 70, 147, 5]), - (b"ffffeeffbb", 181, &[94, 94, 4, 79, 119, 5]), - (b"ffffeeffbb", 182, &[39, 54, 66, 19, 92, 5]), - (b"ffffeeffbb", 183, &[119, 2, 143, 69, 65, 5]), - (b"ffffeeffbb", 184, &[67, 57, 90, 44, 39, 5]), - (b"ffffeeffbb", 185, &[90, 63, 141, 123, 13, 5]), - (b"ffffeeffbb", 186, &[53, 123, 172, 119, 174, 4]), - (b"ffffeeffbb", 187, &[153, 21, 68, 28, 151, 4]), - (b"ffffeeffbb", 188, &[131, 138, 94, 32, 128, 4]), - (b"ffffeeffbb", 189, &[179, 121, 156, 130, 105, 4]), - (b"ffffeeffbb", 190, &[185, 179, 164, 131, 83, 4]), - (b"ffffeeffbb", 191, &[118, 123, 37, 31, 62, 4]), - (b"ffffeeffbb", 192, &[59, 106, 83, 16, 41, 4]), - (b"ffffeeffbb", 193, &[57, 37, 47, 86, 20, 4]), - (b"ffffeeffbb", 194, &[191, 140, 63, 45, 0, 4]), - (b"ffffeeffbb", 195, &[65, 169, 83, 84, 175, 3]), - (b"ffffeeffbb", 196, &[67, 158, 64, 6, 157, 3]), - (b"ffffeeffbb", 197, &[121, 26, 167, 3, 139, 3]), - (b"ffffeeffbb", 198, &[197, 151, 165, 75, 121, 3]), - (b"ffffeeffbb", 199, &[55, 175, 36, 22, 104, 3]), - (b"ffffeeffbb", 200, &[195, 167, 162, 38, 87, 3]), - (b"ffffeeffbb", 201, &[35, 27, 136, 124, 70, 3]), - (b"ffffeeffbb", 202, &[87, 64, 153, 76, 54, 3]), - (b"ffffeeffbb", 203, &[151, 191, 14, 94, 38, 3]), - (b"ffffeeffbb", 204, &[119, 103, 135, 175, 22, 3]), - (b"ffffeeffbb", 205, &[200, 79, 123, 115, 7, 3]), - (b"ffffeeffbb", 206, &[133, 165, 202, 115, 198, 2]), - (b"ffffeeffbb", 207, &[44, 153, 193, 175, 184, 2]), - (b"ffffeeffbb", 208, &[91, 190, 125, 86, 171, 2]), - (b"ffffeeffbb", 209, &[109, 151, 34, 53, 158, 2]), - (b"ffffeeffbb", 210, &[95, 40, 171, 74, 145, 2]), - (b"ffffeeffbb", 211, &[84, 195, 162, 150, 132, 2]), - (b"ffffeeffbb", 212, &[31, 15, 59, 68, 120, 2]), - (b"ffffeeffbb", 213, &[125, 57, 127, 36, 108, 2]), - (b"ffffeeffbb", 214, &[51, 132, 2, 55, 96, 2]), - (b"ffffeeffbb", 215, &[175, 133, 177, 122, 84, 2]), - (b"ffffeeffbb", 216, &[179, 35, 78, 23, 73, 2]), - (b"ffffeeffbb", 217, &[53, 101, 208, 186, 61, 2]), - (b"ffffeeffbb", 218, &[33, 9, 214, 179, 50, 2]), - (b"ffffeeffbb", 219, &[107, 147, 175, 217, 39, 2]), - (b"ffffeeffbb", 220, &[175, 81, 179, 79, 29, 2]), - (b"ffffeeffbb", 221, &[0, 76, 95, 204, 18, 2]), - (b"ffffeeffbb", 222, &[53, 213, 16, 150, 8, 2]), - (b"ffffeeffbb", 223, &[158, 161, 42, 136, 221, 1]), - (b"ffffeeffbb", 224, &[123, 54, 52, 162, 212, 1]), - (b"ffffeeffbb", 225, &[170, 43, 151, 2, 204, 1]), - (b"ffffeeffbb", 226, &[27, 68, 224, 105, 195, 1]), - (b"ffffeeffbb", 227, &[45, 69, 157, 20, 187, 1]), - (b"ffffeeffbb", 228, &[71, 213, 64, 199, 178, 1]), - (b"ffffeeffbb", 229, &[129, 203, 66, 186, 170, 1]), - (b"ffffeeffbb", 230, &[205, 183, 57, 208, 162, 1]), - (b"ffffeeffbb", 231, &[32, 50, 164, 33, 155, 1]), - (b"ffffeeffbb", 232, &[35, 135, 53, 123, 147, 1]), - (b"ffffeeffbb", 233, &[209, 47, 89, 13, 140, 1]), - (b"ffffeeffbb", 234, &[143, 56, 175, 168, 132, 1]), - (b"ffffeeffbb", 235, &[225, 157, 216, 121, 125, 1]), - (b"ffffeeffbb", 236, &[51, 66, 119, 105, 118, 1]), - (b"ffffeeffbb", 237, &[116, 150, 26, 119, 111, 1]), - (b"ffffeeffbb", 238, &[221, 15, 87, 162, 104, 1]), - (b"ffffeeffbb", 239, &[234, 155, 214, 234, 97, 1]), - (b"ffffeeffbb", 240, &[155, 46, 84, 96, 91, 1]), - (b"ffffeeffbb", 241, &[187, 48, 90, 225, 84, 1]), - (b"ffffeeffbb", 242, &[87, 212, 151, 140, 78, 1]), - (b"ffffeeffbb", 243, &[206, 22, 189, 81, 72, 1]), - (b"ffffeeffbb", 244, &[119, 93, 122, 48, 66, 1]), - (b"ffffeeffbb", 245, &[165, 224, 117, 40, 60, 1]), - (b"ffffeeffbb", 246, &[77, 121, 100, 57, 54, 1]), - (b"ffffeeffbb", 247, &[52, 128, 242, 98, 48, 1]), - (b"ffffeeffbb", 248, &[115, 247, 224, 164, 42, 1]), - (b"ffffeeffbb", 249, &[218, 127, 223, 5, 37, 1]), - (b"ffffeeffbb", 250, &[95, 54, 168, 118, 31, 1]), - (b"ffffeeffbb", 251, &[121, 204, 240, 3, 26, 1]), - (b"ffffeeffbb", 252, &[179, 138, 123, 162, 20, 1]), - (b"ffffeeffbb", 253, &[21, 50, 1, 91, 15, 1]), - (b"ffffeeffbb", 254, &[149, 11, 63, 40, 10, 1]), - (b"ffffeeffbb", 255, &[170, 225, 247, 9, 5, 1]), - (b"ffffeeffbb", 256, &[187, 255, 238, 255, 255]), - ]; - - for &(bigint, radix, inbaseradix_le) in GROUND_TRUTH.iter() { - let bigint = BigUint::parse_bytes(bigint, 16).unwrap(); - // to_radix_le - assert_eq!(bigint.to_radix_le(radix), inbaseradix_le); - // to_radix_be - let mut inbase_be = bigint.to_radix_be(radix); - inbase_be.reverse(); // now le - assert_eq!(inbase_be, inbaseradix_le); - // from_radix_le - assert_eq!(BigUint::from_radix_le(inbaseradix_le, radix).unwrap(), bigint); - // from_radix_be - let mut inbaseradix_be = Vec::from(inbaseradix_le); - inbaseradix_be.reverse(); - assert_eq!(BigUint::from_radix_be(&inbaseradix_be, radix).unwrap(), bigint); - } - - assert!(BigUint::from_radix_le(&[10,100,10], 50).is_none()); -} - -#[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, &BigUint::from_str_radix(str, *radix).unwrap()); - } - } - - let zed = BigUint::from_str_radix("Z", 10).ok(); - assert_eq!(zed, None); - let blank = BigUint::from_str_radix("_", 2).ok(); - assert_eq!(blank, None); - let blank_one = BigUint::from_str_radix("_1", 2).ok(); - assert_eq!(blank_one, None); - let plus_one = BigUint::from_str_radix("+1", 10).ok(); - assert_eq!(plus_one, Some(BigUint::from_slice(&[1]))); - let plus_plus_one = BigUint::from_str_radix("++1", 10).ok(); - assert_eq!(plus_plus_one, None); - let minus_one = BigUint::from_str_radix("-1", 10).ok(); - assert_eq!(minus_one, None); - let zero_plus_two = BigUint::from_str_radix("0+2", 10).ok(); - assert_eq!(zero_plus_two, None); - let three = BigUint::from_str_radix("1_1", 2).ok(); - assert_eq!(three, Some(BigUint::from_slice(&[3]))); - let ff = BigUint::from_str_radix("1111_1111", 2).ok(); - assert_eq!(ff, Some(BigUint::from_slice(&[0xff]))); -} - -#[test] -fn test_all_str_radix() { - use std::ascii::AsciiExt; - - let n = BigUint::new((0..10).collect()); - for radix in 2..37 { - let s = n.to_str_radix(radix); - let x = BigUint::from_str_radix(&s, radix); - assert_eq!(x.unwrap(), n); - - let s = s.to_ascii_uppercase(); - let x = BigUint::from_str_radix(&s, radix); - assert_eq!(x.unwrap(), n); - } -} - -#[test] -fn test_lower_hex() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:x}", a), "a"); - assert_eq!(format!("{:x}", hello), "48656c6c6f20776f726c6421"); - assert_eq!(format!("{:♥>+#8x}", a), "♥♥♥♥+0xa"); -} - -#[test] -fn test_upper_hex() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:X}", a), "A"); - assert_eq!(format!("{:X}", hello), "48656C6C6F20776F726C6421"); - assert_eq!(format!("{:♥>+#8X}", a), "♥♥♥♥+0xA"); -} - -#[test] -fn test_binary() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("224055342307539".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:b}", a), "1010"); - assert_eq!(format!("{:b}", hello), - "110010111100011011110011000101101001100011010011"); - assert_eq!(format!("{:♥>+#8b}", a), "♥+0b1010"); -} - -#[test] -fn test_octal() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{:o}", a), "12"); - assert_eq!(format!("{:o}", hello), "22062554330674403566756233062041"); - assert_eq!(format!("{:♥>+#8o}", a), "♥♥♥+0o12"); -} - -#[test] -fn test_display() { - let a = BigUint::parse_bytes(b"A", 16).unwrap(); - let hello = BigUint::parse_bytes("22405534230753963835153736737".as_bytes(), 10).unwrap(); - - assert_eq!(format!("{}", a), "10"); - assert_eq!(format!("{}", hello), "22405534230753963835153736737"); - assert_eq!(format!("{:♥>+#8}", a), "♥♥♥♥♥+10"); -} - -#[test] -fn test_factor() { - fn factor(n: usize) -> BigUint { - let mut f: BigUint = One::one(); - for i in 2..n + 1 { - // FIXME(#5992): assignment operator overloads - // f *= FromPrimitive::from_usize(i); - let bu: BigUint = FromPrimitive::from_usize(i).unwrap(); - f = f * bu; - } - return f; - } - - fn check(n: usize, s: &str) { - let n = factor(n); - let ans = match BigUint::from_str_radix(s, 10) { - Ok(x) => x, - Err(_) => panic!(), - }; - assert_eq!(n, ans); - } - - check(3, "6"); - check(10, "3628800"); - check(20, "2432902008176640000"); - check(30, "265252859812191058636308480000000"); -} - -#[test] -fn test_bits() { - assert_eq!(BigUint::new(vec![0, 0, 0, 0]).bits(), 0); - let n: BigUint = FromPrimitive::from_usize(0).unwrap(); - assert_eq!(n.bits(), 0); - let n: BigUint = FromPrimitive::from_usize(1).unwrap(); - assert_eq!(n.bits(), 1); - let n: BigUint = FromPrimitive::from_usize(3).unwrap(); - assert_eq!(n.bits(), 2); - let n: BigUint = BigUint::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 = thread_rng(); - let _n: BigUint = rng.gen_biguint(137); - assert!(rng.gen_biguint(0).is_zero()); -} - -#[test] -fn test_rand_range() { - let mut rng = thread_rng(); - - for _ in 0..10 { - assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_usize(236).unwrap(), - &FromPrimitive::from_usize(237).unwrap()), - FromPrimitive::from_usize(236).unwrap()); - } - - let l = FromPrimitive::from_usize(403469000 + 2352).unwrap(); - let u = FromPrimitive::from_usize(403469000 + 3513).unwrap(); - for _ in 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_panic] -fn test_zero_rand_range() { - thread_rng().gen_biguint_range(&FromPrimitive::from_usize(54).unwrap(), - &FromPrimitive::from_usize(54).unwrap()); -} - -#[test] -#[should_panic] -fn test_negative_rand_range() { - let mut rng = thread_rng(); - let l = FromPrimitive::from_usize(2352).unwrap(); - let u = FromPrimitive::from_usize(3513).unwrap(); - // Switching u and l should fail: - let _n: BigUint = rng.gen_biguint_range(&u, &l); -} - -fn test_mul_divide_torture_count(count: usize) { - use rand::{SeedableRng, StdRng, Rng}; - - let bits_max = 1 << 12; - let seed: &[_] = &[1, 2, 3, 4]; - let mut rng: StdRng = SeedableRng::from_seed(seed); - - for _ in 0..count { - // Test with numbers of random sizes: - let xbits = rng.gen_range(0, bits_max); - let ybits = rng.gen_range(0, bits_max); - - let x = rng.gen_biguint(xbits); - let y = rng.gen_biguint(ybits); - - if x.is_zero() || y.is_zero() { - continue; - } - - let prod = &x * &y; - assert_eq!(&prod / &x, y); - assert_eq!(&prod / &y, x); - } -} - -#[test] -fn test_mul_divide_torture() { - test_mul_divide_torture_count(1000); -} - -#[test] -#[ignore] -fn test_mul_divide_torture_long() { - test_mul_divide_torture_count(1000000); -} diff --git a/ci/.gitignore b/ci/.gitignore deleted file mode 100644 index 4cb44b1..0000000 --- a/ci/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/deploy diff --git a/ci/deploy.enc b/ci/deploy.enc deleted file mode 100644 index 720d001bc2fbc4dffbd4bcee2bf23e3a3b40bf34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1680 zcmV;B25 zycl-urwQUu^5#e73sF#XLWb_@&8VrwZ?_Ab7fHd{LZO@sD#?d5s_~|2zf-dfiw>*` zlix!>4=>;_)y+nW=|^<}EADj8Xg&r864>ok8+143Dg zacK)h@waROS!#6PC)Y(HK1+rNqhU7Tr2;Zj4&PrVqW6oGU5ZJc;6v?y+Z888632E&Qr7LLb);FMi-r}$u%bDG(BT7*kt@4v@)%$|*&5YyH%A#1t-CYMLx**qvR7YgoxxjnRU<^Vzf z8MkU5M1p>xp%(}t3|Y4j#bRz@vh{vsz>VpFPz7P81Mft&dyV-3a9u(Nd5qfN9YwnE zcDEU~Qo{1gm#Y0-rw_>cDH);qEKmZv=;u=Y{=NbIe}_U5WxaNmchT2t&4K72V*^LS zr%Z}yDXpPM%%oH1e)rclDC%d(Jv(&R^!~l5B7>3Cm~@e_gVe4eyF`&EP)0TkHqU*;ZyDsvLUaWiRjR85Xfv5y z>50WBg~KuPbZB;(5;zS9B~j4aRKF1ei5;ti2(LaKkROBBrM%_a{$ZL~lQKTysoI^M zVM)vC59adE?foL%;`iDyTJs)8<=hO{y2%~)m6cX$yTh>^u^_kVwIDJBg}q8=oshvJ1KNsKjTk6Bs$K!E4oua zP}Cp#6WE8T+y^$Ftw$_%#M>_4Oy-8f;y?dEFWbOcuzZ--JOxFIFiJ4=y&lc)MC|uQ zt2bU3se=IQNR7&!zn02FraC~SHsnJ1rv-^b3v^;_hDFhz-AlXBoCH(4E&z=tb3Q&n zoj>x;^LloXprGQH>U0Mg8ut7ok~PL`7?l zRYVF+4cGrvD$AO|FQ1s8T-X|}R0}aEJF&b~uQ-X-PSSd=S}GxCS>f>@(E5 zvmb}vOZV8Za`gTVSxtq_7DJ(&OYfRr6)JAHEBLAkuiJBycTVk*Am*VnVLsV$8V^Mb zd=PN(vEmOE^`1G8)eGUc*gQ!`dL}RyXM&Kkb9yA!n9Y85rKt{MVjD4K^uqBu1adTr zbE`wXvlZT<_HWG#&pAH36MU31lxNMj9XsfZb_U`y+$_-@$}06OTUEJn!@8Kv+3Rdk z$GnCa{GU7!Am~;hs|r;&_KEX diff --git a/ci/deploy.sh b/ci/deploy.sh deleted file mode 100755 index 02372e2..0000000 --- a/ci/deploy.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -set -ex - -cp doc/* target/doc/ -pip install ghp-import --user -$HOME/.local/bin/ghp-import -n target/doc - -openssl aes-256-cbc -K $encrypted_9e86330b283d_key -iv $encrypted_9e86330b283d_iv -in ./ci/deploy.enc -out ./ci/deploy -d -chmod 600 ./ci/deploy -ssh-add ./ci/deploy -git push -qf ssh://git@github.com/${TRAVIS_REPO_SLUG}.git gh-pages diff --git a/ci/rustup.sh b/ci/rustup.sh index b415aa2..16483d4 100755 --- a/ci/rustup.sh +++ b/ci/rustup.sh @@ -1,18 +1,12 @@ #!/bin/sh # Use rustup to locally run the same suite of tests as .travis.yml. -# (You should first install/update 1.8.0, 1.15.0, beta, and nightly.) +# (You should first install/update 1.8.0, stable, beta, and nightly.) set -ex export TRAVIS_RUST_VERSION -for TRAVIS_RUST_VERSION in 1.8.0 1.15.0 beta nightly; do +for TRAVIS_RUST_VERSION in 1.8.0 stable beta nightly; do run="rustup run $TRAVIS_RUST_VERSION" - if [ "$TRAVIS_RUST_VERSION" = 1.8.0 ]; then - # libc 0.2.34 started using #[deprecated] - $run cargo generate-lockfile - $run cargo update --package libc --precise 0.2.33 || : - fi $run cargo build --verbose $run $PWD/ci/test_full.sh - $run cargo doc done diff --git a/ci/test_full.sh b/ci/test_full.sh index 0d4969c..c64610f 100755 --- a/ci/test_full.sh +++ b/ci/test_full.sh @@ -2,49 +2,10 @@ set -ex -echo Testing num on rustc ${TRAVIS_RUST_VERSION} +echo Testing num-traits on rustc ${TRAVIS_RUST_VERSION} -# All of these packages should build and test everywhere. -for package in bigint complex integer iter rational traits; do - if [ "$TRAVIS_RUST_VERSION" = 1.8.0 ]; then - # libc 0.2.34 started using #[deprecated] - cargo generate-lockfile --manifest-path $package/Cargo.toml - cargo update --manifest-path $package/Cargo.toml --package libc --precise 0.2.33 || : - fi - cargo build --manifest-path $package/Cargo.toml - cargo test --manifest-path $package/Cargo.toml -done +# num-integer should build and test everywhere. +cargo build --verbose +cargo test --verbose -# They all should build with minimal features too -for package in bigint complex integer iter rational traits; do - cargo build --manifest-path $package/Cargo.toml --no-default-features - cargo test --manifest-path $package/Cargo.toml --no-default-features -done - -# Each isolated feature should also work everywhere. -for feature in '' bigint rational complex; do - cargo build --verbose --no-default-features --features="$feature" - cargo test --verbose --no-default-features --features="$feature" -done - -# Build test for the serde feature -cargo build --verbose --features "serde" - -# Downgrade serde and build test the 0.7.0 channel as well -cargo update -p serde --precise 0.7.0 -cargo build --verbose --features "serde" - - -if [ "$TRAVIS_RUST_VERSION" = 1.8.0 ]; then exit; fi - -# num-derive should build on 1.15.0+ -cargo build --verbose --manifest-path=derive/Cargo.toml - - -if [ "$TRAVIS_RUST_VERSION" != nightly ]; then exit; fi - -# num-derive testing requires compiletest_rs, which requires nightly -cargo test --verbose --manifest-path=derive/Cargo.toml - -# benchmarks only work on nightly -cargo bench --verbose +# We have no features to test... diff --git a/complex/Cargo.toml b/complex/Cargo.toml deleted file mode 100644 index 97eadfe..0000000 --- a/complex/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -description = "Complex numbers implementation for Rust" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics"] -categories = [ "algorithms", "data-structures", "science" ] -license = "MIT/Apache-2.0" -name = "num-complex" -repository = "https://github.com/rust-num/num" -version = "0.1.41" - -[dependencies] - -[dependencies.num-traits] -optional = false -path = "../traits" -version = "0.1.39" - -[dependencies.rustc-serialize] -optional = true -version = "0.3.19" - -[dependencies.serde] -optional = true -version = ">= 0.7.0, < 0.9.0" - -[features] -default = ["rustc-serialize"] -unstable = [] diff --git a/complex/LICENSE-APACHE b/complex/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/complex/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/complex/LICENSE-MIT b/complex/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/complex/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/complex/src/lib.rs b/complex/src/lib.rs deleted file mode 100644 index 70416c7..0000000 --- a/complex/src/lib.rs +++ /dev/null @@ -1,1899 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Complex numbers. -#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://rust-num.github.io/num/favicon.ico", - html_root_url = "https://rust-num.github.io/num/", - html_playground_url = "http://play.integer32.com/")] - -extern crate num_traits as traits; - -#[cfg(feature = "rustc-serialize")] -extern crate rustc_serialize; - -#[cfg(feature = "serde")] -extern crate serde; - -use std::error::Error; -use std::fmt; -#[cfg(test)] -use std::hash; -use std::ops::{Add, Div, Mul, Neg, Sub, Rem}; -use std::str::FromStr; - -use traits::{Zero, One, Num, Float}; - -// FIXME #1284: handle complex NaN & infinity etc. This -// probably doesn't map to C's _Complex correctly. - -/// A complex number in Cartesian form. -/// -/// ## Representation and Foreign Function Interface Compatibility -/// -/// `Complex` is memory layout compatible with an array `[T; 2]`. -/// -/// Note that `Complex` where F is a floating point type is **only** memory -/// layout compatible with C's complex types, **not** necessarily calling -/// convention compatible. This means that for FFI you can only pass -/// `Complex` behind a pointer, not as a value. -/// -/// ## Examples -/// -/// Example of extern function declaration. -/// -/// ``` -/// use num_complex::Complex; -/// use std::os::raw::c_int; -/// -/// extern "C" { -/// fn zaxpy_(n: *const c_int, alpha: *const Complex, -/// x: *const Complex, incx: *const c_int, -/// y: *mut Complex, incy: *const c_int); -/// } -/// ``` -#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)] -#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] -#[repr(C)] -pub struct Complex { - /// Real portion of the complex number - pub re: T, - /// Imaginary portion of the complex number - pub im: T -} - -pub type Complex32 = Complex; -pub type Complex64 = Complex; - -impl Complex { - /// Create a new Complex - #[inline] - pub fn new(re: T, im: T) -> Complex { - Complex { re: re, im: im } - } - - /// Returns imaginary unit - #[inline] - pub fn i() -> Complex { - Self::new(T::zero(), T::one()) - } - - /// 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.clone() * self.re.clone() + self.im.clone() * self.im.clone() - } - - /// Multiplies `self` by the scalar `t`. - #[inline] - pub fn scale(&self, t: T) -> Complex { - Complex::new(self.re.clone() * t.clone(), self.im.clone() * t) - } - - /// Divides `self` by the scalar `t`. - #[inline] - pub fn unscale(&self, t: T) -> Complex { - Complex::new(self.re.clone() / t.clone(), self.im.clone() / t) - } -} - -impl> Complex { - /// Returns the complex conjugate. i.e. `re - i im` - #[inline] - pub fn conj(&self) -> Complex { - Complex::new(self.re.clone(), -self.im.clone()) - } - - /// Returns `1/self` - #[inline] - pub fn inv(&self) -> Complex { - let norm_sqr = self.norm_sqr(); - Complex::new(self.re.clone() / norm_sqr.clone(), - -self.im.clone() / norm_sqr) - } -} - -impl Complex { - /// Calculate |self| - #[inline] - pub fn norm(&self) -> T { - self.re.hypot(self.im) - } - /// 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) -> Complex { - Complex::new(*r * theta.cos(), *r * theta.sin()) - } - - /// Computes `e^(self)`, where `e` is the base of the natural logarithm. - #[inline] - pub fn exp(&self) -> Complex { - // formula: e^(a + bi) = e^a (cos(b) + i*sin(b)) - // = from_polar(e^a, b) - Complex::from_polar(&self.re.exp(), &self.im) - } - - /// Computes the principal value of natural logarithm of `self`. - /// - /// This function has one branch cut: - /// - /// * `(-∞, 0]`, continuous from above. - /// - /// The branch satisfies `-π ≤ arg(ln(z)) ≤ π`. - #[inline] - pub fn ln(&self) -> Complex { - // formula: ln(z) = ln|z| + i*arg(z) - let (r, theta) = self.to_polar(); - Complex::new(r.ln(), theta) - } - - /// Computes the principal value of the square root of `self`. - /// - /// This function has one branch cut: - /// - /// * `(-∞, 0)`, continuous from above. - /// - /// The branch satisfies `-π/2 ≤ arg(sqrt(z)) ≤ π/2`. - #[inline] - pub fn sqrt(&self) -> Complex { - // formula: sqrt(r e^(it)) = sqrt(r) e^(it/2) - let two = T::one() + T::one(); - let (r, theta) = self.to_polar(); - Complex::from_polar(&(r.sqrt()), &(theta/two)) - } - - /// Raises `self` to a floating point power. - #[inline] - pub fn powf(&self, exp: T) -> Complex { - // formula: x^y = (ρ e^(i θ))^y = ρ^y e^(i θ y) - // = from_polar(ρ^y, θ y) - let (r, theta) = self.to_polar(); - Complex::from_polar(&r.powf(exp), &(theta*exp)) - } - - /// Returns the logarithm of `self` with respect to an arbitrary base. - #[inline] - pub fn log(&self, base: T) -> Complex { - // formula: log_y(x) = log_y(ρ e^(i θ)) - // = log_y(ρ) + log_y(e^(i θ)) = log_y(ρ) + ln(e^(i θ)) / ln(y) - // = log_y(ρ) + i θ / ln(y) - let (r, theta) = self.to_polar(); - Complex::new(r.log(base), theta / base.ln()) - } - - /// Raises `self` to a complex power. - #[inline] - pub fn powc(&self, exp: Complex) -> Complex { - // formula: x^y = (a + i b)^(c + i d) - // = (ρ e^(i θ))^c (ρ e^(i θ))^(i d) - // where ρ=|x| and θ=arg(x) - // = ρ^c e^(−d θ) e^(i c θ) ρ^(i d) - // = p^c e^(−d θ) (cos(c θ) - // + i sin(c θ)) (cos(d ln(ρ)) + i sin(d ln(ρ))) - // = p^c e^(−d θ) ( - // cos(c θ) cos(d ln(ρ)) − sin(c θ) sin(d ln(ρ)) - // + i(cos(c θ) sin(d ln(ρ)) + sin(c θ) cos(d ln(ρ)))) - // = p^c e^(−d θ) (cos(c θ + d ln(ρ)) + i sin(c θ + d ln(ρ))) - // = from_polar(p^c e^(−d θ), c θ + d ln(ρ)) - let (r, theta) = self.to_polar(); - Complex::from_polar( - &(r.powf(exp.re) * (-exp.im * theta).exp()), - &(exp.re * theta + exp.im * r.ln())) - } - - /// Raises a floating point number to the complex power `self`. - #[inline] - pub fn expf(&self, base: T) -> Complex { - // formula: x^(a+bi) = x^a x^bi = x^a e^(b ln(x) i) - // = from_polar(x^a, b ln(x)) - Complex::from_polar(&base.powf(self.re), &(self.im * base.ln())) - } - - /// Computes the sine of `self`. - #[inline] - pub fn sin(&self) -> Complex { - // formula: sin(a + bi) = sin(a)cosh(b) + i*cos(a)sinh(b) - Complex::new(self.re.sin() * self.im.cosh(), self.re.cos() * self.im.sinh()) - } - - /// Computes the cosine of `self`. - #[inline] - pub fn cos(&self) -> Complex { - // formula: cos(a + bi) = cos(a)cosh(b) - i*sin(a)sinh(b) - Complex::new(self.re.cos() * self.im.cosh(), -self.re.sin() * self.im.sinh()) - } - - /// Computes the tangent of `self`. - #[inline] - pub fn tan(&self) -> Complex { - // formula: tan(a + bi) = (sin(2a) + i*sinh(2b))/(cos(2a) + cosh(2b)) - let (two_re, two_im) = (self.re + self.re, self.im + self.im); - Complex::new(two_re.sin(), two_im.sinh()).unscale(two_re.cos() + two_im.cosh()) - } - - /// Computes the principal value of the inverse sine of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞, -1)`, continuous from above. - /// * `(1, ∞)`, continuous from below. - /// - /// The branch satisfies `-π/2 ≤ Re(asin(z)) ≤ π/2`. - #[inline] - pub fn asin(&self) -> Complex { - // formula: arcsin(z) = -i ln(sqrt(1-z^2) + iz) - let i = Complex::::i(); - -i*((Complex::::one() - self*self).sqrt() + i*self).ln() - } - - /// Computes the principal value of the inverse cosine of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞, -1)`, continuous from above. - /// * `(1, ∞)`, continuous from below. - /// - /// The branch satisfies `0 ≤ Re(acos(z)) ≤ π`. - #[inline] - pub fn acos(&self) -> Complex { - // formula: arccos(z) = -i ln(i sqrt(1-z^2) + z) - let i = Complex::::i(); - -i*(i*(Complex::::one() - self*self).sqrt() + self).ln() - } - - /// Computes the principal value of the inverse tangent of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞i, -i]`, continuous from the left. - /// * `[i, ∞i)`, continuous from the right. - /// - /// The branch satisfies `-π/2 ≤ Re(atan(z)) ≤ π/2`. - #[inline] - pub fn atan(&self) -> Complex { - // formula: arctan(z) = (ln(1+iz) - ln(1-iz))/(2i) - let i = Complex::::i(); - let one = Complex::::one(); - let two = one + one; - if *self == i { - return Complex::new(T::zero(), T::infinity()); - } - else if *self == -i { - return Complex::new(T::zero(), -T::infinity()); - } - ((one + i * self).ln() - (one - i * self).ln()) / (two * i) - } - - /// Computes the hyperbolic sine of `self`. - #[inline] - pub fn sinh(&self) -> Complex { - // formula: sinh(a + bi) = sinh(a)cos(b) + i*cosh(a)sin(b) - Complex::new(self.re.sinh() * self.im.cos(), self.re.cosh() * self.im.sin()) - } - - /// Computes the hyperbolic cosine of `self`. - #[inline] - pub fn cosh(&self) -> Complex { - // formula: cosh(a + bi) = cosh(a)cos(b) + i*sinh(a)sin(b) - Complex::new(self.re.cosh() * self.im.cos(), self.re.sinh() * self.im.sin()) - } - - /// Computes the hyperbolic tangent of `self`. - #[inline] - pub fn tanh(&self) -> Complex { - // formula: tanh(a + bi) = (sinh(2a) + i*sin(2b))/(cosh(2a) + cos(2b)) - let (two_re, two_im) = (self.re + self.re, self.im + self.im); - Complex::new(two_re.sinh(), two_im.sin()).unscale(two_re.cosh() + two_im.cos()) - } - - /// Computes the principal value of inverse hyperbolic sine of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞i, -i)`, continuous from the left. - /// * `(i, ∞i)`, continuous from the right. - /// - /// The branch satisfies `-π/2 ≤ Im(asinh(z)) ≤ π/2`. - #[inline] - pub fn asinh(&self) -> Complex { - // formula: arcsinh(z) = ln(z + sqrt(1+z^2)) - let one = Complex::::one(); - (self + (one + self * self).sqrt()).ln() - } - - /// Computes the principal value of inverse hyperbolic cosine of `self`. - /// - /// This function has one branch cut: - /// - /// * `(-∞, 1)`, continuous from above. - /// - /// The branch satisfies `-π ≤ Im(acosh(z)) ≤ π` and `0 ≤ Re(acosh(z)) < ∞`. - #[inline] - pub fn acosh(&self) -> Complex { - // formula: arccosh(z) = 2 ln(sqrt((z+1)/2) + sqrt((z-1)/2)) - let one = Complex::one(); - let two = one + one; - two * (((self + one)/two).sqrt() + ((self - one)/two).sqrt()).ln() - } - - /// Computes the principal value of inverse hyperbolic tangent of `self`. - /// - /// This function has two branch cuts: - /// - /// * `(-∞, -1]`, continuous from above. - /// * `[1, ∞)`, continuous from below. - /// - /// The branch satisfies `-π/2 ≤ Im(atanh(z)) ≤ π/2`. - #[inline] - pub fn atanh(&self) -> Complex { - // formula: arctanh(z) = (ln(1+z) - ln(1-z))/2 - let one = Complex::one(); - let two = one + one; - if *self == one { - return Complex::new(T::infinity(), T::zero()); - } - else if *self == -one { - return Complex::new(-T::infinity(), T::zero()); - } - ((one + self).ln() - (one - self).ln()) / two - } - - /// Checks if the given complex number is NaN - #[inline] - pub fn is_nan(self) -> bool { - self.re.is_nan() || self.im.is_nan() - } - - /// Checks if the given complex number is infinite - #[inline] - pub fn is_infinite(self) -> bool { - !self.is_nan() && (self.re.is_infinite() || self.im.is_infinite()) - } - - /// Checks if the given complex number is finite - #[inline] - pub fn is_finite(self) -> bool { - self.re.is_finite() && self.im.is_finite() - } - - /// Checks if the given complex number is normal - #[inline] - pub fn is_normal(self) -> bool { - self.re.is_normal() && self.im.is_normal() - } -} - -impl From for Complex { - #[inline] - fn from(re: T) -> Complex { - Complex { re: re, im: T::zero() } - } -} - -impl<'a, T: Clone + Num> From<&'a T> for Complex { - #[inline] - fn from(re: &T) -> Complex { - From::from(re.clone()) - } -} - -macro_rules! forward_ref_ref_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, 'b, T: Clone + Num> $imp<&'b Complex> for &'a Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &Complex) -> Complex { - self.clone().$method(other.clone()) - } - } - } -} - -macro_rules! forward_ref_val_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T: Clone + Num> $imp> for &'a Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: Complex) -> Complex { - self.clone().$method(other) - } - } - } -} - -macro_rules! forward_val_ref_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T: Clone + Num> $imp<&'a Complex> for Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &Complex) -> Complex { - self.$method(other.clone()) - } - } - } -} - -macro_rules! forward_all_binop { - (impl $imp:ident, $method:ident) => { - forward_ref_ref_binop!(impl $imp, $method); - forward_ref_val_binop!(impl $imp, $method); - forward_val_ref_binop!(impl $imp, $method); - }; -} - -/* arithmetic */ -forward_all_binop!(impl Add, add); - -// (a + i b) + (c + i d) == (a + c) + i (b + d) -impl Add> for Complex { - type Output = Complex; - - #[inline] - fn add(self, other: Complex) -> Complex { - Complex::new(self.re + other.re, self.im + other.im) - } -} - -forward_all_binop!(impl Sub, sub); - -// (a + i b) - (c + i d) == (a - c) + i (b - d) -impl Sub> for Complex { - type Output = Complex; - - #[inline] - fn sub(self, other: Complex) -> Complex { - Complex::new(self.re - other.re, self.im - other.im) - } -} - -forward_all_binop!(impl Mul, mul); - -// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c) -impl Mul> for Complex { - type Output = Complex; - - #[inline] - fn mul(self, other: Complex) -> Complex { - let re = self.re.clone() * other.re.clone() - self.im.clone() * other.im.clone(); - let im = self.re * other.im + self.im * other.re; - Complex::new(re, im) - } -} - -forward_all_binop!(impl Div, div); - -// (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 Div> for Complex { - type Output = Complex; - - #[inline] - fn div(self, other: Complex) -> Complex { - let norm_sqr = other.norm_sqr(); - let re = self.re.clone() * other.re.clone() + self.im.clone() * other.im.clone(); - let im = self.im * other.re - self.re * other.im; - Complex::new(re / norm_sqr.clone(), im / norm_sqr) - } -} - -forward_all_binop!(impl Rem, rem); - -// Attempts to identify the gaussian integer whose product with `modulus` -// is closest to `self`. -impl Rem> for Complex { - type Output = Complex; - - #[inline] - fn rem(self, modulus: Complex) -> Self { - let Complex { re, im } = self.clone() / modulus.clone(); - // This is the gaussian integer corresponding to the true ratio - // rounded towards zero. - let (re0, im0) = (re.clone() - re % T::one(), im.clone() - im % T::one()); - self - modulus * Complex::new(re0, im0) - } -} - -// Op Assign - -mod opassign { - use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; - - use traits::NumAssign; - - use Complex; - - impl AddAssign for Complex { - fn add_assign(&mut self, other: Complex) { - self.re += other.re; - self.im += other.im; - } - } - - impl SubAssign for Complex { - fn sub_assign(&mut self, other: Complex) { - self.re -= other.re; - self.im -= other.im; - } - } - - impl MulAssign for Complex { - fn mul_assign(&mut self, other: Complex) { - *self = self.clone() * other; - } - } - - impl DivAssign for Complex { - fn div_assign(&mut self, other: Complex) { - *self = self.clone() / other; - } - } - - impl RemAssign for Complex { - fn rem_assign(&mut self, other: Complex) { - *self = self.clone() % other; - } - } - - impl AddAssign for Complex { - fn add_assign(&mut self, other: T) { - self.re += other; - } - } - - impl SubAssign for Complex { - fn sub_assign(&mut self, other: T) { - self.re -= other; - } - } - - impl MulAssign for Complex { - fn mul_assign(&mut self, other: T) { - self.re *= other.clone(); - self.im *= other; - } - } - - impl DivAssign for Complex { - fn div_assign(&mut self, other: T) { - self.re /= other.clone(); - self.im /= other; - } - } - - impl RemAssign for Complex { - fn rem_assign(&mut self, other: T) { - *self = self.clone() % other; - } - } - - macro_rules! forward_op_assign { - (impl $imp:ident, $method:ident) => { - impl<'a, T: Clone + NumAssign> $imp<&'a Complex> for Complex { - #[inline] - fn $method(&mut self, other: &Complex) { - self.$method(other.clone()) - } - } - impl<'a, T: Clone + NumAssign> $imp<&'a T> for Complex { - #[inline] - fn $method(&mut self, other: &T) { - self.$method(other.clone()) - } - } - } - } - - forward_op_assign!(impl AddAssign, add_assign); - forward_op_assign!(impl SubAssign, sub_assign); - forward_op_assign!(impl MulAssign, mul_assign); - forward_op_assign!(impl DivAssign, div_assign); - - impl<'a, T: Clone + NumAssign> RemAssign<&'a Complex> for Complex { - #[inline] - fn rem_assign(&mut self, other: &Complex) { - self.rem_assign(other.clone()) - } - } - impl<'a, T: Clone + NumAssign> RemAssign<&'a T> for Complex { - #[inline] - fn rem_assign(&mut self, other: &T) { - self.rem_assign(other.clone()) - } - } -} - -impl> Neg for Complex { - type Output = Complex; - - #[inline] - fn neg(self) -> Complex { - Complex::new(-self.re, -self.im) - } -} - -impl<'a, T: Clone + Num + Neg> Neg for &'a Complex { - type Output = Complex; - - #[inline] - fn neg(self) -> Complex { - -self.clone() - } -} - -macro_rules! real_arithmetic { - (@forward $imp:ident::$method:ident for $($real:ident),*) => ( - impl<'a, T: Clone + Num> $imp<&'a T> for Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &T) -> Complex { - self.$method(other.clone()) - } - } - impl<'a, T: Clone + Num> $imp for &'a Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: T) -> Complex { - self.clone().$method(other) - } - } - impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Complex { - type Output = Complex; - - #[inline] - fn $method(self, other: &T) -> Complex { - self.clone().$method(other.clone()) - } - } - $( - impl<'a> $imp<&'a Complex<$real>> for $real { - type Output = Complex<$real>; - - #[inline] - fn $method(self, other: &Complex<$real>) -> Complex<$real> { - self.$method(other.clone()) - } - } - impl<'a> $imp> for &'a $real { - type Output = Complex<$real>; - - #[inline] - fn $method(self, other: Complex<$real>) -> Complex<$real> { - self.clone().$method(other) - } - } - impl<'a, 'b> $imp<&'a Complex<$real>> for &'b $real { - type Output = Complex<$real>; - - #[inline] - fn $method(self, other: &Complex<$real>) -> Complex<$real> { - self.clone().$method(other.clone()) - } - } - )* - ); - ($($real:ident),*) => ( - real_arithmetic!(@forward Add::add for $($real),*); - real_arithmetic!(@forward Sub::sub for $($real),*); - real_arithmetic!(@forward Mul::mul for $($real),*); - real_arithmetic!(@forward Div::div for $($real),*); - real_arithmetic!(@forward Rem::rem for $($real),*); - - $( - impl Add> for $real { - type Output = Complex<$real>; - - #[inline] - fn add(self, other: Complex<$real>) -> Complex<$real> { - Complex::new(self + other.re, other.im) - } - } - - impl Sub> for $real { - type Output = Complex<$real>; - - #[inline] - fn sub(self, other: Complex<$real>) -> Complex<$real> { - Complex::new(self - other.re, $real::zero() - other.im) - } - } - - impl Mul> for $real { - type Output = Complex<$real>; - - #[inline] - fn mul(self, other: Complex<$real>) -> Complex<$real> { - Complex::new(self * other.re, self * other.im) - } - } - - impl Div> for $real { - type Output = Complex<$real>; - - #[inline] - fn div(self, other: Complex<$real>) -> Complex<$real> { - // a / (c + i d) == [a * (c - i d)] / (c*c + d*d) - let norm_sqr = other.norm_sqr(); - Complex::new(self * other.re / norm_sqr.clone(), - $real::zero() - self * other.im / norm_sqr) - } - } - - impl Rem> for $real { - type Output = Complex<$real>; - - #[inline] - fn rem(self, other: Complex<$real>) -> Complex<$real> { - Complex::new(self, Self::zero()) % other - } - } - )* - ); -} - -impl Add for Complex { - type Output = Complex; - - #[inline] - fn add(self, other: T) -> Complex { - Complex::new(self.re + other, self.im) - } -} - -impl Sub for Complex { - type Output = Complex; - - #[inline] - fn sub(self, other: T) -> Complex { - Complex::new(self.re - other, self.im) - } -} - -impl Mul for Complex { - type Output = Complex; - - #[inline] - fn mul(self, other: T) -> Complex { - Complex::new(self.re * other.clone(), self.im * other) - } -} - -impl Div for Complex { - type Output = Complex; - - #[inline] - fn div(self, other: T) -> Complex { - Complex::new(self.re / other.clone(), self.im / other) - } -} - -impl Rem for Complex { - type Output = Complex; - - #[inline] - fn rem(self, other: T) -> Complex { - self % Complex::new(other, T::zero()) - } -} - -real_arithmetic!(usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64); - -/* constants */ -impl Zero for Complex { - #[inline] - fn zero() -> Complex { - Complex::new(Zero::zero(), Zero::zero()) - } - - #[inline] - fn is_zero(&self) -> bool { - self.re.is_zero() && self.im.is_zero() - } -} - -impl One for Complex { - #[inline] - fn one() -> Complex { - Complex::new(One::one(), Zero::zero()) - } -} - -macro_rules! write_complex { - ($f:ident, $t:expr, $prefix:expr, $re:expr, $im:expr, $T:ident) => {{ - let abs_re = if $re < Zero::zero() { $T::zero() - $re.clone() } else { $re.clone() }; - let abs_im = if $im < Zero::zero() { $T::zero() - $im.clone() } else { $im.clone() }; - - let real: String; - let imag: String; - - if let Some(prec) = $f.precision() { - real = format!(concat!("{:.1$", $t, "}"), abs_re, prec); - imag = format!(concat!("{:.1$", $t, "}"), abs_im, prec); - } - else { - real = format!(concat!("{:", $t, "}"), abs_re); - imag = format!(concat!("{:", $t, "}"), abs_im); - } - - let prefix = if $f.alternate() { $prefix } else { "" }; - let sign = if $re < Zero::zero() { - "-" - } else if $f.sign_plus() { - "+" - } else { - "" - }; - - let complex = if $im < Zero::zero() { - format!("{}{pre}{re}-{pre}{im}i", sign, re=real, im=imag, pre=prefix) - } - else { - format!("{}{pre}{re}+{pre}{im}i", sign, re=real, im=imag, pre=prefix) - }; - - if let Some(width) = $f.width() { - write!($f, "{0: >1$}", complex, width) - } - else { - write!($f, "{}", complex) - } - }} -} - -/* string conversions */ -impl fmt::Display for Complex where - T: fmt::Display + Num + PartialOrd + Clone -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_complex!(f, "", "", self.re, self.im, T) - } -} - -impl fmt::LowerExp for Complex where - T: fmt::LowerExp + Num + PartialOrd + Clone -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_complex!(f, "e", "", self.re, self.im, T) - } -} - -impl fmt::UpperExp for Complex where - T: fmt::UpperExp + Num + PartialOrd + Clone -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_complex!(f, "E", "", self.re, self.im, T) - } -} - -impl fmt::LowerHex for Complex where - T: fmt::LowerHex + Num + PartialOrd + Clone -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_complex!(f, "x", "0x", self.re, self.im, T) - } -} - -impl fmt::UpperHex for Complex where - T: fmt::UpperHex + Num + PartialOrd + Clone -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_complex!(f, "X", "0x", self.re, self.im, T) - } -} - -impl fmt::Octal for Complex where - T: fmt::Octal + Num + PartialOrd + Clone -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_complex!(f, "o", "0o", self.re, self.im, T) - } -} - -impl fmt::Binary for Complex where - T: fmt::Binary + Num + PartialOrd + Clone -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write_complex!(f, "b", "0b", self.re, self.im, T) - } -} - -fn from_str_generic(s: &str, from: F) -> Result, ParseComplexError> - where F: Fn(&str) -> Result, T: Clone + Num -{ - let imag = match s.rfind('j') { - None => 'i', - _ => 'j' - }; - - let mut b = String::with_capacity(s.len()); - let mut first = true; - - let char_indices = s.char_indices(); - let mut pc = ' '; - let mut split_index = s.len(); - - for (i, cc) in char_indices { - if cc == '+' && pc != 'e' && pc != 'E' && i > 0 { - // ignore '+' if part of an exponent - if first { - split_index = i; - first = false; - } - // don't carry '+' over into b - pc = ' '; - continue; - } else if cc == '-' && pc != 'e' && pc != 'E' && i > 0 { - // ignore '-' if part of an exponent or begins the string - if first { - split_index = i; - first = false; - } - // DO carry '-' over into b - } - - if pc == '-' && cc == ' ' && !first { - // ignore whitespace between minus sign and next number - continue; - } - - if !first { - b.push(cc); - } - pc = cc; - } - - // split off real and imaginary parts, trim whitespace - let (a, _) = s.split_at(split_index); - let a = a.trim_right(); - let mut b = b.trim_left(); - // input was either pure real or pure imaginary - if b.is_empty() { - b = match a.ends_with(imag) { - false => "0i", - true => "0" - }; - } - - let re; - let im; - if a.ends_with(imag) { - im = a; re = b; - } else if b.ends_with(imag) { - re = a; im = b; - } else { - return Err(ParseComplexError::new()); - } - - // parse re - let re = try!(from(re).map_err(ParseComplexError::from_error)); - - // pop imaginary unit off - let mut im = &im[..im.len()-1]; - // handle im == "i" or im == "-i" - if im.is_empty() || im == "+" { - im = "1"; - } else if im == "-" { - im = "-1"; - } - - // parse im - let im = try!(from(im).map_err(ParseComplexError::from_error)); - - Ok(Complex::new(re, im)) -} - -impl FromStr for Complex where - T: FromStr + Num + Clone -{ - type Err = ParseComplexError; - - /// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T` - fn from_str(s: &str) -> Result - { - from_str_generic(s, T::from_str) - } -} - -impl Num for Complex { - type FromStrRadixErr = ParseComplexError; - - /// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T` - fn from_str_radix(s: &str, radix: u32) -> Result - { - from_str_generic(s, |x| -> Result { - T::from_str_radix(x, radix) }) - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for Complex - where T: serde::Serialize -{ - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where - S: serde::Serializer - { - (&self.re, &self.im).serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl serde::Deserialize for Complex where - T: serde::Deserialize + Num + Clone -{ - fn deserialize(deserializer: &mut D) -> Result where - D: serde::Deserializer, - { - let (re, im) = try!(serde::Deserialize::deserialize(deserializer)); - Ok(Complex::new(re, im)) - } -} - -#[derive(Debug, PartialEq)] -pub struct ParseComplexError -{ - kind: ComplexErrorKind, -} - -#[derive(Debug, PartialEq)] -enum ComplexErrorKind -{ - ParseError(E), - ExprError -} - -impl ParseComplexError -{ - fn new() -> Self { - ParseComplexError { - kind: ComplexErrorKind::ExprError, - } - } - - fn from_error(error: E) -> Self { - ParseComplexError { - kind: ComplexErrorKind::ParseError(error), - } - } -} - -impl Error for ParseComplexError -{ - fn description(&self) -> &str { - match self.kind { - ComplexErrorKind::ParseError(ref e) => e.description(), - ComplexErrorKind::ExprError => "invalid or unsupported complex expression" - } - } -} - -impl fmt::Display for ParseComplexError -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -#[cfg(test)] -fn hash(x: &T) -> u64 { - use std::hash::{BuildHasher, Hasher}; - use std::collections::hash_map::RandomState; - let mut hasher = ::Hasher::new(); - x.hash(&mut hasher); - hasher.finish() -} - -#[cfg(test)] -mod test { - #![allow(non_upper_case_globals)] - - use super::{Complex64, Complex}; - use std::f64; - use std::str::FromStr; - - use traits::{Zero, One, Float, Num}; - - pub const _0_0i : Complex64 = Complex { re: 0.0, im: 0.0 }; - pub const _1_0i : Complex64 = Complex { re: 1.0, im: 0.0 }; - pub const _1_1i : Complex64 = Complex { re: 1.0, im: 1.0 }; - pub const _0_1i : Complex64 = Complex { re: 0.0, im: 1.0 }; - pub const _neg1_1i : Complex64 = Complex { re: -1.0, im: 1.0 }; - pub const _05_05i : Complex64 = Complex { re: 0.5, im: 0.5 }; - pub const all_consts : [Complex64; 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i]; - pub const _4_2i : Complex64 = Complex { re: 4.0, im: 2.0 }; - - #[test] - fn test_consts() { - // check our constants are what Complex::new creates - fn test(c : Complex64, r : f64, i: f64) { - assert_eq!(c, Complex::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] - #[cfg_attr(target_arch = "x86", ignore)] - // 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(), Complex::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_panic] - fn test_divide_by_zero_natural() { - let n = Complex::new(2, 3); - let d = Complex::new(0, 0); - let _x = n / d; - } - - #[test] - fn test_inv_zero() { - // FIXME #20: should this really fail, or just NaN? - assert!(_0_0i.inv().is_nan()); - } - - #[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 * f64::consts::PI); - test(_neg1_1i, 0.75 * f64::consts::PI); - test(_05_05i, 0.25 * f64::consts::PI); - } - - #[test] - fn test_polar_conv() { - fn test(c: Complex64) { - let (r, theta) = c.to_polar(); - assert!((c - Complex::from_polar(&r, &theta)).norm() < 1e-6); - } - for &c in all_consts.iter() { test(c); } - } - - fn close(a: Complex64, b: Complex64) -> bool { - close_to_tol(a, b, 1e-10) - } - - fn close_to_tol(a: Complex64, b: Complex64, tol: f64) -> bool { - // returns true if a and b are reasonably close - (a == b) || (a-b).norm() < tol - } - - #[test] - fn test_exp() { - assert!(close(_1_0i.exp(), _1_0i.scale(f64::consts::E))); - assert!(close(_0_0i.exp(), _1_0i)); - assert!(close(_0_1i.exp(), Complex::new(1.0.cos(), 1.0.sin()))); - assert!(close(_05_05i.exp()*_05_05i.exp(), _1_1i.exp())); - assert!(close(_0_1i.scale(-f64::consts::PI).exp(), _1_0i.scale(-1.0))); - for &c in all_consts.iter() { - // e^conj(z) = conj(e^z) - assert!(close(c.conj().exp(), c.exp().conj())); - // e^(z + 2 pi i) = e^z - assert!(close(c.exp(), (c + _0_1i.scale(f64::consts::PI*2.0)).exp())); - } - } - - #[test] - fn test_ln() { - assert!(close(_1_0i.ln(), _0_0i)); - assert!(close(_0_1i.ln(), _0_1i.scale(f64::consts::PI/2.0))); - assert!(close(_0_0i.ln(), Complex::new(f64::neg_infinity(), 0.0))); - assert!(close((_neg1_1i * _05_05i).ln(), _neg1_1i.ln() + _05_05i.ln())); - for &c in all_consts.iter() { - // ln(conj(z() = conj(ln(z)) - assert!(close(c.conj().ln(), c.ln().conj())); - // for this branch, -pi <= arg(ln(z)) <= pi - assert!(-f64::consts::PI <= c.ln().arg() && c.ln().arg() <= f64::consts::PI); - } - } - - #[test] - fn test_powc() - { - let a = Complex::new(2.0, -3.0); - let b = Complex::new(3.0, 0.0); - assert!(close(a.powc(b), a.powf(b.re))); - assert!(close(b.powc(a), a.expf(b.re))); - let c = Complex::new(1.0 / 3.0, 0.1); - assert!(close_to_tol(a.powc(c), Complex::new(1.65826, -0.33502), 1e-5)); - } - - #[test] - fn test_powf() - { - let c = Complex::new(2.0, -1.0); - let r = c.powf(3.5); - assert!(close_to_tol(r, Complex::new(-0.8684746, -16.695934), 1e-5)); - } - - #[test] - fn test_log() - { - let c = Complex::new(2.0, -1.0); - let r = c.log(10.0); - assert!(close_to_tol(r, Complex::new(0.349485, -0.20135958), 1e-5)); - } - - #[test] - fn test_some_expf_cases() - { - let c = Complex::new(2.0, -1.0); - let r = c.expf(10.0); - assert!(close_to_tol(r, Complex::new(-66.82015, -74.39803), 1e-5)); - - let c = Complex::new(5.0, -2.0); - let r = c.expf(3.4); - assert!(close_to_tol(r, Complex::new(-349.25, -290.63), 1e-2)); - - let c = Complex::new(-1.5, 2.0 / 3.0); - let r = c.expf(1.0 / 3.0); - assert!(close_to_tol(r, Complex::new(3.8637, -3.4745), 1e-2)); - } - - #[test] - fn test_sqrt() { - assert!(close(_0_0i.sqrt(), _0_0i)); - assert!(close(_1_0i.sqrt(), _1_0i)); - assert!(close(Complex::new(-1.0, 0.0).sqrt(), _0_1i)); - assert!(close(Complex::new(-1.0, -0.0).sqrt(), _0_1i.scale(-1.0))); - assert!(close(_0_1i.sqrt(), _05_05i.scale(2.0.sqrt()))); - for &c in all_consts.iter() { - // sqrt(conj(z() = conj(sqrt(z)) - assert!(close(c.conj().sqrt(), c.sqrt().conj())); - // for this branch, -pi/2 <= arg(sqrt(z)) <= pi/2 - assert!(-f64::consts::PI/2.0 <= c.sqrt().arg() && c.sqrt().arg() <= f64::consts::PI/2.0); - // sqrt(z) * sqrt(z) = z - assert!(close(c.sqrt()*c.sqrt(), c)); - } - } - - #[test] - fn test_sin() { - assert!(close(_0_0i.sin(), _0_0i)); - assert!(close(_1_0i.scale(f64::consts::PI*2.0).sin(), _0_0i)); - assert!(close(_0_1i.sin(), _0_1i.scale(1.0.sinh()))); - for &c in all_consts.iter() { - // sin(conj(z)) = conj(sin(z)) - assert!(close(c.conj().sin(), c.sin().conj())); - // sin(-z) = -sin(z) - assert!(close(c.scale(-1.0).sin(), c.sin().scale(-1.0))); - } - } - - #[test] - fn test_cos() { - assert!(close(_0_0i.cos(), _1_0i)); - assert!(close(_1_0i.scale(f64::consts::PI*2.0).cos(), _1_0i)); - assert!(close(_0_1i.cos(), _1_0i.scale(1.0.cosh()))); - for &c in all_consts.iter() { - // cos(conj(z)) = conj(cos(z)) - assert!(close(c.conj().cos(), c.cos().conj())); - // cos(-z) = cos(z) - assert!(close(c.scale(-1.0).cos(), c.cos())); - } - } - - #[test] - fn test_tan() { - assert!(close(_0_0i.tan(), _0_0i)); - assert!(close(_1_0i.scale(f64::consts::PI/4.0).tan(), _1_0i)); - assert!(close(_1_0i.scale(f64::consts::PI).tan(), _0_0i)); - for &c in all_consts.iter() { - // tan(conj(z)) = conj(tan(z)) - assert!(close(c.conj().tan(), c.tan().conj())); - // tan(-z) = -tan(z) - assert!(close(c.scale(-1.0).tan(), c.tan().scale(-1.0))); - } - } - - #[test] - fn test_asin() { - assert!(close(_0_0i.asin(), _0_0i)); - assert!(close(_1_0i.asin(), _1_0i.scale(f64::consts::PI/2.0))); - assert!(close(_1_0i.scale(-1.0).asin(), _1_0i.scale(-f64::consts::PI/2.0))); - assert!(close(_0_1i.asin(), _0_1i.scale((1.0 + 2.0.sqrt()).ln()))); - for &c in all_consts.iter() { - // asin(conj(z)) = conj(asin(z)) - assert!(close(c.conj().asin(), c.asin().conj())); - // asin(-z) = -asin(z) - assert!(close(c.scale(-1.0).asin(), c.asin().scale(-1.0))); - // for this branch, -pi/2 <= asin(z).re <= pi/2 - assert!(-f64::consts::PI/2.0 <= c.asin().re && c.asin().re <= f64::consts::PI/2.0); - } - } - - #[test] - fn test_acos() { - assert!(close(_0_0i.acos(), _1_0i.scale(f64::consts::PI/2.0))); - assert!(close(_1_0i.acos(), _0_0i)); - assert!(close(_1_0i.scale(-1.0).acos(), _1_0i.scale(f64::consts::PI))); - assert!(close(_0_1i.acos(), Complex::new(f64::consts::PI/2.0, (2.0.sqrt() - 1.0).ln()))); - for &c in all_consts.iter() { - // acos(conj(z)) = conj(acos(z)) - assert!(close(c.conj().acos(), c.acos().conj())); - // for this branch, 0 <= acos(z).re <= pi - assert!(0.0 <= c.acos().re && c.acos().re <= f64::consts::PI); - } - } - - #[test] - fn test_atan() { - assert!(close(_0_0i.atan(), _0_0i)); - assert!(close(_1_0i.atan(), _1_0i.scale(f64::consts::PI/4.0))); - assert!(close(_1_0i.scale(-1.0).atan(), _1_0i.scale(-f64::consts::PI/4.0))); - assert!(close(_0_1i.atan(), Complex::new(0.0, f64::infinity()))); - for &c in all_consts.iter() { - // atan(conj(z)) = conj(atan(z)) - assert!(close(c.conj().atan(), c.atan().conj())); - // atan(-z) = -atan(z) - assert!(close(c.scale(-1.0).atan(), c.atan().scale(-1.0))); - // for this branch, -pi/2 <= atan(z).re <= pi/2 - assert!(-f64::consts::PI/2.0 <= c.atan().re && c.atan().re <= f64::consts::PI/2.0); - } - } - - #[test] - fn test_sinh() { - assert!(close(_0_0i.sinh(), _0_0i)); - assert!(close(_1_0i.sinh(), _1_0i.scale((f64::consts::E - 1.0/f64::consts::E)/2.0))); - assert!(close(_0_1i.sinh(), _0_1i.scale(1.0.sin()))); - for &c in all_consts.iter() { - // sinh(conj(z)) = conj(sinh(z)) - assert!(close(c.conj().sinh(), c.sinh().conj())); - // sinh(-z) = -sinh(z) - assert!(close(c.scale(-1.0).sinh(), c.sinh().scale(-1.0))); - } - } - - #[test] - fn test_cosh() { - assert!(close(_0_0i.cosh(), _1_0i)); - assert!(close(_1_0i.cosh(), _1_0i.scale((f64::consts::E + 1.0/f64::consts::E)/2.0))); - assert!(close(_0_1i.cosh(), _1_0i.scale(1.0.cos()))); - for &c in all_consts.iter() { - // cosh(conj(z)) = conj(cosh(z)) - assert!(close(c.conj().cosh(), c.cosh().conj())); - // cosh(-z) = cosh(z) - assert!(close(c.scale(-1.0).cosh(), c.cosh())); - } - } - - #[test] - fn test_tanh() { - assert!(close(_0_0i.tanh(), _0_0i)); - assert!(close(_1_0i.tanh(), _1_0i.scale((f64::consts::E.powi(2) - 1.0)/(f64::consts::E.powi(2) + 1.0)))); - assert!(close(_0_1i.tanh(), _0_1i.scale(1.0.tan()))); - for &c in all_consts.iter() { - // tanh(conj(z)) = conj(tanh(z)) - assert!(close(c.conj().tanh(), c.conj().tanh())); - // tanh(-z) = -tanh(z) - assert!(close(c.scale(-1.0).tanh(), c.tanh().scale(-1.0))); - } - } - - #[test] - fn test_asinh() { - assert!(close(_0_0i.asinh(), _0_0i)); - assert!(close(_1_0i.asinh(), _1_0i.scale(1.0 + 2.0.sqrt()).ln())); - assert!(close(_0_1i.asinh(), _0_1i.scale(f64::consts::PI/2.0))); - assert!(close(_0_1i.asinh().scale(-1.0), _0_1i.scale(-f64::consts::PI/2.0))); - for &c in all_consts.iter() { - // asinh(conj(z)) = conj(asinh(z)) - assert!(close(c.conj().asinh(), c.conj().asinh())); - // asinh(-z) = -asinh(z) - assert!(close(c.scale(-1.0).asinh(), c.asinh().scale(-1.0))); - // for this branch, -pi/2 <= asinh(z).im <= pi/2 - assert!(-f64::consts::PI/2.0 <= c.asinh().im && c.asinh().im <= f64::consts::PI/2.0); - } - } - - #[test] - fn test_acosh() { - assert!(close(_0_0i.acosh(), _0_1i.scale(f64::consts::PI/2.0))); - assert!(close(_1_0i.acosh(), _0_0i)); - assert!(close(_1_0i.scale(-1.0).acosh(), _0_1i.scale(f64::consts::PI))); - for &c in all_consts.iter() { - // acosh(conj(z)) = conj(acosh(z)) - assert!(close(c.conj().acosh(), c.conj().acosh())); - // for this branch, -pi <= acosh(z).im <= pi and 0 <= acosh(z).re - assert!(-f64::consts::PI <= c.acosh().im && c.acosh().im <= f64::consts::PI && 0.0 <= c.cosh().re); - } - } - - #[test] - fn test_atanh() { - assert!(close(_0_0i.atanh(), _0_0i)); - assert!(close(_0_1i.atanh(), _0_1i.scale(f64::consts::PI/4.0))); - assert!(close(_1_0i.atanh(), Complex::new(f64::infinity(), 0.0))); - for &c in all_consts.iter() { - // atanh(conj(z)) = conj(atanh(z)) - assert!(close(c.conj().atanh(), c.conj().atanh())); - // atanh(-z) = -atanh(z) - assert!(close(c.scale(-1.0).atanh(), c.atanh().scale(-1.0))); - // for this branch, -pi/2 <= atanh(z).im <= pi/2 - assert!(-f64::consts::PI/2.0 <= c.atanh().im && c.atanh().im <= f64::consts::PI/2.0); - } - } - - #[test] - fn test_exp_ln() { - for &c in all_consts.iter() { - // e^ln(z) = z - assert!(close(c.ln().exp(), c)); - } - } - - #[test] - fn test_trig_to_hyperbolic() { - for &c in all_consts.iter() { - // sin(iz) = i sinh(z) - assert!(close((_0_1i * c).sin(), _0_1i * c.sinh())); - // cos(iz) = cosh(z) - assert!(close((_0_1i * c).cos(), c.cosh())); - // tan(iz) = i tanh(z) - assert!(close((_0_1i * c).tan(), _0_1i * c.tanh())); - } - } - - #[test] - fn test_trig_identities() { - for &c in all_consts.iter() { - // tan(z) = sin(z)/cos(z) - assert!(close(c.tan(), c.sin()/c.cos())); - // sin(z)^2 + cos(z)^2 = 1 - assert!(close(c.sin()*c.sin() + c.cos()*c.cos(), _1_0i)); - - // sin(asin(z)) = z - assert!(close(c.asin().sin(), c)); - // cos(acos(z)) = z - assert!(close(c.acos().cos(), c)); - // tan(atan(z)) = z - // i and -i are branch points - if c != _0_1i && c != _0_1i.scale(-1.0) { - assert!(close(c.atan().tan(), c)); - } - - // sin(z) = (e^(iz) - e^(-iz))/(2i) - assert!(close(((_0_1i*c).exp() - (_0_1i*c).exp().inv())/_0_1i.scale(2.0), c.sin())); - // cos(z) = (e^(iz) + e^(-iz))/2 - assert!(close(((_0_1i*c).exp() + (_0_1i*c).exp().inv()).unscale(2.0), c.cos())); - // tan(z) = i (1 - e^(2iz))/(1 + e^(2iz)) - assert!(close(_0_1i * (_1_0i - (_0_1i*c).scale(2.0).exp())/(_1_0i + (_0_1i*c).scale(2.0).exp()), c.tan())); - } - } - - #[test] - fn test_hyperbolic_identites() { - for &c in all_consts.iter() { - // tanh(z) = sinh(z)/cosh(z) - assert!(close(c.tanh(), c.sinh()/c.cosh())); - // cosh(z)^2 - sinh(z)^2 = 1 - assert!(close(c.cosh()*c.cosh() - c.sinh()*c.sinh(), _1_0i)); - - // sinh(asinh(z)) = z - assert!(close(c.asinh().sinh(), c)); - // cosh(acosh(z)) = z - assert!(close(c.acosh().cosh(), c)); - // tanh(atanh(z)) = z - // 1 and -1 are branch points - if c != _1_0i && c != _1_0i.scale(-1.0) { - assert!(close(c.atanh().tanh(), c)); - } - - // sinh(z) = (e^z - e^(-z))/2 - assert!(close((c.exp() - c.exp().inv()).unscale(2.0), c.sinh())); - // cosh(z) = (e^z + e^(-z))/2 - assert!(close((c.exp() + c.exp().inv()).unscale(2.0), c.cosh())); - // tanh(z) = ( e^(2z) - 1)/(e^(2z) + 1) - assert!(close((c.scale(2.0).exp() - _1_0i)/(c.scale(2.0).exp() + _1_0i), c.tanh())); - } - } - - // Test both a + b and a += b - macro_rules! test_a_op_b { - ($a:ident + $b:expr, $answer:expr) => { - assert_eq!($a + $b, $answer); - assert_eq!({ let mut x = $a; x += $b; x}, $answer); - }; - ($a:ident - $b:expr, $answer:expr) => { - assert_eq!($a - $b, $answer); - assert_eq!({ let mut x = $a; x -= $b; x}, $answer); - }; - ($a:ident * $b:expr, $answer:expr) => { - assert_eq!($a * $b, $answer); - assert_eq!({ let mut x = $a; x *= $b; x}, $answer); - }; - ($a:ident / $b:expr, $answer:expr) => { - assert_eq!($a / $b, $answer); - assert_eq!({ let mut x = $a; x /= $b; x}, $answer); - }; - ($a:ident % $b:expr, $answer:expr) => { - assert_eq!($a % $b, $answer); - assert_eq!({ let mut x = $a; x %= $b; x}, $answer); - } - } - - // Test both a + b and a + &b - macro_rules! test_op { - ($a:ident $op:tt $b:expr, $answer:expr) => { - test_a_op_b!($a $op $b, $answer); - test_a_op_b!($a $op &$b, $answer); - } - } - - mod complex_arithmetic { - use super::{_0_0i, _1_0i, _1_1i, _0_1i, _neg1_1i, _05_05i, _4_2i, all_consts}; - use traits::Zero; - - #[test] - fn test_add() { - test_op!(_05_05i + _05_05i, _1_1i); - test_op!(_0_1i + _1_0i, _1_1i); - test_op!(_1_0i + _neg1_1i, _0_1i); - - for &c in all_consts.iter() { - test_op!(_0_0i + c, c); - test_op!(c + _0_0i, c); - } - } - - #[test] - fn test_sub() { - test_op!(_05_05i - _05_05i, _0_0i); - test_op!(_0_1i - _1_0i, _neg1_1i); - test_op!(_0_1i - _neg1_1i, _1_0i); - - for &c in all_consts.iter() { - test_op!(c - _0_0i, c); - test_op!(c - c, _0_0i); - } - } - - #[test] - fn test_mul() { - test_op!(_05_05i * _05_05i, _0_1i.unscale(2.0)); - test_op!(_1_1i * _0_1i, _neg1_1i); - - // i^2 & i^4 - test_op!(_0_1i * _0_1i, -_1_0i); - assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i); - - for &c in all_consts.iter() { - test_op!(c * _1_0i, c); - test_op!(_1_0i * c, c); - } - } - - #[test] - fn test_div() { - test_op!(_neg1_1i / _0_1i, _1_1i); - for &c in all_consts.iter() { - if c != Zero::zero() { - test_op!(c / c, _1_0i); - } - } - } - - #[test] - fn test_rem() { - test_op!(_neg1_1i % _0_1i, _0_0i); - test_op!(_4_2i % _0_1i, _0_0i); - test_op!(_05_05i % _0_1i, _05_05i); - test_op!(_05_05i % _1_1i, _05_05i); - assert_eq!((_4_2i + _05_05i) % _0_1i, _05_05i); - assert_eq!((_4_2i + _05_05i) % _1_1i, _05_05i); - } - - #[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); - } - } - } - - mod real_arithmetic { - use super::super::Complex; - use super::{_4_2i, _neg1_1i}; - - #[test] - fn test_add() { - test_op!(_4_2i + 0.5, Complex::new(4.5, 2.0)); - assert_eq!(0.5 + _4_2i, Complex::new(4.5, 2.0)); - } - - #[test] - fn test_sub() { - test_op!(_4_2i - 0.5, Complex::new(3.5, 2.0)); - assert_eq!(0.5 - _4_2i, Complex::new(-3.5, -2.0)); - } - - #[test] - fn test_mul() { - assert_eq!(_4_2i * 0.5, Complex::new(2.0, 1.0)); - assert_eq!(0.5 * _4_2i, Complex::new(2.0, 1.0)); - } - - #[test] - fn test_div() { - assert_eq!(_4_2i / 0.5, Complex::new(8.0, 4.0)); - assert_eq!(0.5 / _4_2i, Complex::new(0.1, -0.05)); - } - - #[test] - fn test_rem() { - assert_eq!(_4_2i % 2.0, Complex::new(0.0, 0.0)); - assert_eq!(_4_2i % 3.0, Complex::new(1.0, 2.0)); - assert_eq!(3.0 % _4_2i, Complex::new(3.0, 0.0)); - assert_eq!(_neg1_1i % 2.0, _neg1_1i); - assert_eq!(-_4_2i % 3.0, Complex::new(-1.0, -2.0)); - } - } - - #[test] - fn test_to_string() { - fn test(c : Complex64, s: String) { - assert_eq!(c.to_string(), s); - } - test(_0_0i, "0+0i".to_string()); - test(_1_0i, "1+0i".to_string()); - test(_0_1i, "0+1i".to_string()); - test(_1_1i, "1+1i".to_string()); - test(_neg1_1i, "-1+1i".to_string()); - test(-_neg1_1i, "1-1i".to_string()); - test(_05_05i, "0.5+0.5i".to_string()); - } - - #[test] - fn test_string_formatting() { - let a = Complex::new(1.23456, 123.456); - assert_eq!(format!("{}", a), "1.23456+123.456i"); - assert_eq!(format!("{:.2}", a), "1.23+123.46i"); - assert_eq!(format!("{:.2e}", a), "1.23e0+1.23e2i"); - assert_eq!(format!("{:+20.2E}", a), " +1.23E0+1.23E2i"); - - let b = Complex::new(0x80, 0xff); - assert_eq!(format!("{:X}", b), "80+FFi"); - assert_eq!(format!("{:#x}", b), "0x80+0xffi"); - assert_eq!(format!("{:+#b}", b), "+0b10000000+0b11111111i"); - assert_eq!(format!("{:+#16o}", b), " +0o200+0o377i"); - - let c = Complex::new(-10, -10000); - assert_eq!(format!("{}", c), "-10-10000i"); - assert_eq!(format!("{:16}", c), " -10-10000i"); - } - - #[test] - fn test_hash() { - let a = Complex::new(0i32, 0i32); - let b = Complex::new(1i32, 0i32); - let c = Complex::new(0i32, 1i32); - assert!(::hash(&a) != ::hash(&b)); - assert!(::hash(&b) != ::hash(&c)); - assert!(::hash(&c) != ::hash(&a)); - } - - #[test] - fn test_hashset() { - use std::collections::HashSet; - let a = Complex::new(0i32, 0i32); - let b = Complex::new(1i32, 0i32); - let c = Complex::new(0i32, 1i32); - - let set: HashSet<_> = [a, b, c].iter().cloned().collect(); - assert!(set.contains(&a)); - assert!(set.contains(&b)); - assert!(set.contains(&c)); - assert!(!set.contains(&(a + b + c))); - } - - #[test] - fn test_is_nan() { - assert!(!_1_1i.is_nan()); - let a = Complex::new(f64::NAN, f64::NAN); - assert!(a.is_nan()); - } - - #[test] - fn test_is_nan_special_cases() { - let a = Complex::new(0f64, f64::NAN); - let b = Complex::new(f64::NAN, 0f64); - assert!(a.is_nan()); - assert!(b.is_nan()); - } - - #[test] - fn test_is_infinite() { - let a = Complex::new(2f64, f64::INFINITY); - assert!(a.is_infinite()); - } - - #[test] - fn test_is_finite() { - assert!(_1_1i.is_finite()) - } - - #[test] - fn test_is_normal() { - let a = Complex::new(0f64, f64::NAN); - let b = Complex::new(2f64, f64::INFINITY); - assert!(!a.is_normal()); - assert!(!b.is_normal()); - assert!(_1_1i.is_normal()); - } - - #[test] - fn test_from_str() { - fn test(z: Complex64, s: &str) { - assert_eq!(FromStr::from_str(s), Ok(z)); - } - test(_0_0i, "0 + 0i"); - test(_0_0i, "0+0j"); - test(_0_0i, "0 - 0j"); - test(_0_0i, "0-0i"); - test(_0_0i, "0i + 0"); - test(_0_0i, "0"); - test(_0_0i, "-0"); - test(_0_0i, "0i"); - test(_0_0i, "0j"); - test(_0_0i, "+0j"); - test(_0_0i, "-0i"); - - test(_1_0i, "1 + 0i"); - test(_1_0i, "1+0j"); - test(_1_0i, "1 - 0j"); - test(_1_0i, "+1-0i"); - test(_1_0i, "-0j+1"); - test(_1_0i, "1"); - - test(_1_1i, "1 + i"); - test(_1_1i, "1+j"); - test(_1_1i, "1 + 1j"); - test(_1_1i, "1+1i"); - test(_1_1i, "i + 1"); - test(_1_1i, "1i+1"); - test(_1_1i, "+j+1"); - - test(_0_1i, "0 + i"); - test(_0_1i, "0+j"); - test(_0_1i, "-0 + j"); - test(_0_1i, "-0+i"); - test(_0_1i, "0 + 1i"); - test(_0_1i, "0+1j"); - test(_0_1i, "-0 + 1j"); - test(_0_1i, "-0+1i"); - test(_0_1i, "j + 0"); - test(_0_1i, "i"); - test(_0_1i, "j"); - test(_0_1i, "1j"); - - test(_neg1_1i, "-1 + i"); - test(_neg1_1i, "-1+j"); - test(_neg1_1i, "-1 + 1j"); - test(_neg1_1i, "-1+1i"); - test(_neg1_1i, "1i-1"); - test(_neg1_1i, "j + -1"); - - test(_05_05i, "0.5 + 0.5i"); - test(_05_05i, "0.5+0.5j"); - test(_05_05i, "5e-1+0.5j"); - test(_05_05i, "5E-1 + 0.5j"); - test(_05_05i, "5E-1i + 0.5"); - test(_05_05i, "0.05e+1j + 50E-2"); - } - - #[test] - fn test_from_str_radix() { - fn test(z: Complex64, s: &str, radix: u32) { - let res: Result::FromStrRadixErr> - = Num::from_str_radix(s, radix); - assert_eq!(res.unwrap(), z) - } - test(_4_2i, "4+2i", 10); - test(Complex::new(15.0, 32.0), "F+20i", 16); - test(Complex::new(15.0, 32.0), "1111+100000i", 2); - test(Complex::new(-15.0, -32.0), "-F-20i", 16); - test(Complex::new(-15.0, -32.0), "-1111-100000i", 2); - } - - #[test] - fn test_from_str_fail() { - fn test(s: &str) { - let complex: Result = FromStr::from_str(s); - assert!(complex.is_err()); - } - test("foo"); - test("6E"); - test("0 + 2.718"); - test("1 - -2i"); - test("314e-2ij"); - test("4.3j - i"); - test("1i - 2i"); - test("+ 1 - 3.0i"); - } -} diff --git a/derive/Cargo.toml b/derive/Cargo.toml deleted file mode 100644 index 2a17ce0..0000000 --- a/derive/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -description = "Numeric syntax extensions" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics"] -categories = [ "science" ] -license = "MIT/Apache-2.0" -name = "num-derive" -repository = "https://github.com/rust-num/num" -version = "0.1.41" - -[dependencies] -quote = "0.1.3" -syn = "0.7.0" - -[dev-dependencies] -compiletest_rs = "0.2.5" - -[dev-dependencies.num] -path = ".." -version = "0.1" - -[lib] -name = "num_derive" -proc-macro = true -test = false diff --git a/derive/LICENSE-APACHE b/derive/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/derive/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/derive/LICENSE-MIT b/derive/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/derive/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/derive/src/lib.rs b/derive/src/lib.rs deleted file mode 100644 index e75fa06..0000000 --- a/derive/src/lib.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2012-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![crate_type = "proc-macro"] - -extern crate syn; -#[macro_use] -extern crate quote; -extern crate proc_macro; - -use proc_macro::TokenStream; - -use syn::Body::Enum; -use syn::VariantData::Unit; - -#[proc_macro_derive(FromPrimitive)] -pub fn from_primitive(input: TokenStream) -> TokenStream { - let source = input.to_string(); - - let ast = syn::parse_macro_input(&source).unwrap(); - let name = &ast.ident; - - let variants = match ast.body { - Enum(ref variants) => variants, - _ => panic!("`FromPrimitive` can be applied only to the enums, {} is not an enum", name) - }; - - let mut idx = 0; - let variants: Vec<_> = variants.iter() - .map(|variant| { - let ident = &variant.ident; - match variant.data { - Unit => (), - _ => { - panic!("`FromPrimitive` can be applied only to unitary enums, {}::{} is either struct or tuple", name, ident) - }, - } - if let Some(val) = variant.discriminant { - idx = val.value; - } - let tt = quote!(#idx => Some(#name::#ident)); - idx += 1; - tt - }) - .collect(); - - let res = quote! { - impl ::num::traits::FromPrimitive for #name { - fn from_i64(n: i64) -> Option { - Self::from_u64(n as u64) - } - - fn from_u64(n: u64) -> Option { - match n { - #(variants,)* - _ => None, - } - } - } - }; - - res.to_string().parse().unwrap() -} - -#[proc_macro_derive(ToPrimitive)] -pub fn to_primitive(input: TokenStream) -> TokenStream { - let source = input.to_string(); - - let ast = syn::parse_macro_input(&source).unwrap(); - let name = &ast.ident; - - let variants = match ast.body { - Enum(ref variants) => variants, - _ => panic!("`ToPrimitive` can be applied only to the enums, {} is not an enum", name) - }; - - let mut idx = 0; - let variants: Vec<_> = variants.iter() - .map(|variant| { - let ident = &variant.ident; - match variant.data { - Unit => (), - _ => { - panic!("`ToPrimitive` can be applied only to unitary enums, {}::{} is either struct or tuple", name, ident) - }, - } - if let Some(val) = variant.discriminant { - idx = val.value; - } - let tt = quote!(#name::#ident => #idx); - idx += 1; - tt - }) - .collect(); - - let res = quote! { - impl ::num::traits::ToPrimitive for #name { - fn to_i64(&self) -> Option { - self.to_u64().map(|x| x as i64) - } - - fn to_u64(&self) -> Option { - Some(match *self { - #(variants,)* - }) - } - } - }; - - res.to_string().parse().unwrap() -} diff --git a/derive/tests/compile-fail/from-primitive/derive_on_struct.rs b/derive/tests/compile-fail/from-primitive/derive_on_struct.rs deleted file mode 100644 index 0145618..0000000 --- a/derive/tests/compile-fail/from-primitive/derive_on_struct.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate num; -#[macro_use] -extern crate num_derive; - -#[derive(Debug, PartialEq, FromPrimitive)] //~ ERROR -struct Color { - r: u8, - g: u8, - b: u8, -} - -fn main() {} diff --git a/derive/tests/compile-fail/from-primitive/enum_with_associated_data.rs b/derive/tests/compile-fail/from-primitive/enum_with_associated_data.rs deleted file mode 100644 index ca6f34d..0000000 --- a/derive/tests/compile-fail/from-primitive/enum_with_associated_data.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate num; -#[macro_use] -extern crate num_derive; - -#[derive(Debug, PartialEq, FromPrimitive)] //~ ERROR -enum Color { - Rgb(u8, u8, u8), - Hsv(u8, u8, u8), -} - -fn main() {} diff --git a/derive/tests/compile-fail/to-primitive/derive_on_struct.rs b/derive/tests/compile-fail/to-primitive/derive_on_struct.rs deleted file mode 100644 index 23088d0..0000000 --- a/derive/tests/compile-fail/to-primitive/derive_on_struct.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate num; -#[macro_use] -extern crate num_derive; - -#[derive(Debug, PartialEq, ToPrimitive)] //~ ERROR -struct Color { - r: u8, - g: u8, - b: u8, -} - -fn main() {} diff --git a/derive/tests/compile-fail/to-primitive/enum_with_associated_data.rs b/derive/tests/compile-fail/to-primitive/enum_with_associated_data.rs deleted file mode 100644 index 08df949..0000000 --- a/derive/tests/compile-fail/to-primitive/enum_with_associated_data.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate num; -#[macro_use] -extern crate num_derive; - -#[derive(Debug, PartialEq, ToPrimitive)] //~ ERROR -enum Color { - Rgb(u8, u8, u8), - Hsv(u8, u8, u8), -} - -fn main() {} diff --git a/derive/tests/compiletest.rs b/derive/tests/compiletest.rs deleted file mode 100644 index 27c212b..0000000 --- a/derive/tests/compiletest.rs +++ /dev/null @@ -1,25 +0,0 @@ -extern crate compiletest_rs as compiletest; - -use std::path::PathBuf; -use std::env::var; - -fn run_mode(mode: &'static str) { - let mut config = compiletest::default_config(); - - let cfg_mode = mode.parse().ok().expect("Invalid mode"); - - config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned()); - if let Ok(name) = var::<&str>("TESTNAME") { - let s : String = name.to_owned(); - config.filter = Some(s) - } - config.mode = cfg_mode; - config.src_base = PathBuf::from(format!("tests/{}", mode)); - - compiletest::run_tests(&config); -} - -#[test] -fn compile_test() { - run_mode("compile-fail"); -} diff --git a/derive/tests/empty_enum.rs b/derive/tests/empty_enum.rs deleted file mode 100644 index 6fb4a43..0000000 --- a/derive/tests/empty_enum.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate num; -#[macro_use] -extern crate num_derive; - -#[derive(Debug, PartialEq, FromPrimitive, ToPrimitive)] -enum Color {} - -#[test] -fn test_empty_enum() { - let v: [Option; 1] = [num::FromPrimitive::from_u64(0)]; - - assert_eq!(v, [None]); -} diff --git a/derive/tests/trivial.rs b/derive/tests/trivial.rs deleted file mode 100644 index 4e8d26c..0000000 --- a/derive/tests/trivial.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2013-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate num; -#[macro_use] -extern crate num_derive; - -#[derive(Debug, PartialEq, FromPrimitive, ToPrimitive)] -enum Color { - Red, - Blue, - Green, -} - -#[test] -fn test_from_primitive_for_trivial_case() { - let v: [Option; 4] = [num::FromPrimitive::from_u64(0), - num::FromPrimitive::from_u64(1), - num::FromPrimitive::from_u64(2), - num::FromPrimitive::from_u64(3)]; - - assert_eq!(v, - [Some(Color::Red), Some(Color::Blue), Some(Color::Green), None]); -} - -#[test] -fn test_to_primitive_for_trivial_case() { - let v: [Option; 3] = [num::ToPrimitive::to_u64(&Color::Red), - num::ToPrimitive::to_u64(&Color::Blue), - num::ToPrimitive::to_u64(&Color::Green)]; - - assert_eq!(v, [Some(0), Some(1), Some(2)]); -} - -#[test] -fn test_reflexive_for_trivial_case() { - let before: [u64; 3] = [0, 1, 2]; - let after: Vec> = before.iter() - .map(|&x| -> Option { num::FromPrimitive::from_u64(x) }) - .map(|x| x.and_then(|x| num::ToPrimitive::to_u64(&x))) - .collect(); - let before = before.into_iter().cloned().map(Some).collect::>(); - - assert_eq!(before, after); -} diff --git a/derive/tests/with_custom_values.rs b/derive/tests/with_custom_values.rs deleted file mode 100644 index a83ea5b..0000000 --- a/derive/tests/with_custom_values.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013-2015 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate num; -#[macro_use] -extern crate num_derive; - -#[derive(Debug, PartialEq, FromPrimitive)] -enum Color { - Red, - Blue = 5, - Green, -} - -#[test] -fn test_from_primitive_for_enum_with_custom_value() { - let v: [Option; 4] = [num::FromPrimitive::from_u64(0), - num::FromPrimitive::from_u64(5), - num::FromPrimitive::from_u64(6), - num::FromPrimitive::from_u64(3)]; - - assert_eq!(v, - [Some(Color::Red), Some(Color::Blue), Some(Color::Green), None]); -} diff --git a/doc/favicon.ico b/doc/favicon.ico deleted file mode 100644 index b8ad23769ac8d06eb5973bfb3d2acbf385240f98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23229 zcmeHvc|28H|Nn80c^;Zf$(*SSWu`JD(V;RG>6p@BE^{)JxkzQmP>~SI(4dfxF(slB z5)PR%L}d!)x0ZYM{hrRHTlcx&;g8>bJ@5Nj>$5(?d#%0p+H0?)2Zf?QQKG7KHQB}0m;J^5csADJ;Ux=>OHY2a((G>5y2ee}sw(wi6T`3%ZKV`TrFyPF# zt&A6CYgvuX>mI3Y4iczsT`%x-^H<4K|4iTE5A( zW;pTj)bS=iyy&B$FLZTz6sqXlO(QRPaGH6uCn|hQsGKO}S@_hL9R`fA>g_4(3L74) z=Mhj5{S+k^;9h$yrFNWoZS_9MkBle@w7uv}e0VO(;)O~BN_s=I~%uGO3%LKPp+NC_VOjyiikz7Wk2r6 z?y}oVo2#KHaFYG54CD?V{U0f#D6deJ(I;O>8=(|PlNQygb8S{K1o10}pnz1B`0*i@@Sg+EVqi&Sp>fWfI-G0X^^q3yS z7IcPUOtbmMGonZH6ft-&(L(KE8mn4Qj0<&B11j?I=GmZA?qTQH-`$art_&Zcb9PQo zG0QgY8$X9r!P{{pK4q7mw;k*Tp%SM}MKtFE!;oThbJs zORbMuJC$t^=d_P``$YQNa31F8=u<4JeOjkJXsPq;bqM%)JjBVO(}HWxT)Rh0-c{gn z)s)>SmgjB)Iwm;tBNMrrXVw+p@v^sZ)Ft3>#T*Zt!bf;^-!%`}l4o64g0Xbh#d+fl z2nP4|PddH*ek-}Q0c%SyjhRbgaoiL|-QXf1VQPD@dt&7L({KlR{m6%oT=&oTJT&!_ zqpV87@R;29lTpQt3>x!spW?3)0~*VR#*xSQUCx*uV3n7fe$wEeA0}3G+4S6;(^0D` zr{_vBu6S!+@gUJay@HLKba{5S=}%;PZa=_?b>+@?bQjTpYVa zQxR2AD(!hy-&dB4S(rSj(hw07+1Qn;gE+|6Q9Y^juK`zGqWNJ z&Q^uw#K`wwZkX?3cAhLei_KHfQec)?Md3f{;wR~`UEqSt`N6B!Z$F8RW=ANwbDs~r z9d73)pocEO%%8w_5 zINB&w?%vVRYAXt;d^GeG+pC5*!RrJ@hx!kH$F8pGV2z6vMI}+Zz_j=_-}Y+vtS&s} z5|Sj{l*eyb>EY=7MEUIjOLt4X%i(4Zwzi+15&oh&Zcf-w$S^4hp$&C86_Mf=*|U$( zg6BxUoJ6;lRep1(I5?gif4^i<%cSZI%@n2jY3*T?dR6_aLsP3t;xP9qL_)4Q7NmUT zcfxqwt`PIF=Bo%l$u%>U&`urbD>LB5sS^7%t=R;#T|An@F=Ap88RN*@G=hfA|#>lbNTDBHD3Z^a}2)@(uJa2 z1pM(erS6|p2vxGNB0;N$`3hoF6)o{1iLdGkMO*LEi99`+`Le6t^4^89vUuyuAG2;OiPC>^h?*>zPN>H#OS^pWzyR5Y+sBDTF%C4V`Te#=bIs?Ji;C($TzLB zoV=gS1zsem65Qvnqh35J5}$C!@)TapH(NXLpNt+qG-;`Hktse>dlxMq9cF$-B8Xe& zVGUO0*$ws!w|MAyP`Tlwj`LhewJltkeOhnInQ2D%Y&(7$FWx=6PgzY4c4Hc49@koR zlAxG3%O`waMu66LeJCb#??>w=3qH-y;(~mSFjMrEDcj?8xVi0j1ehM^HTI8CyY`Hy z%)Q=)uJ{GNrTERxgQ#||W*xn3|0?#VASWgZi#;56egl`+`_-=S&~2%OiFZxTehUO(tOY$aNH^|NWHbP;A^jVcUNCvoA-d}y$1dY zzHxp1_nEv51-mYPH7mO(fSI%`xAu1u&u=IbO~;f3O?~}TD9h4*#$welW;aVU6<)@2 zvg?k#QIaO5_M?49caCmK&J65$G=$lFSFOiYfZIyKoi8i(>o(k@T!}O8*ldOLwf5r) z&-LCj3bV;e7iC`2+<9GWx95HR&;;ycXuaC~o105|Jm#45W-0HN9QZ&j@Fr70PPOmG zrqJa@< z2HvsFF=t{30z9;=;SiP3`fQ(GM;He3cdL*W=p06eca&dD5apWqHHu+8Yg}j^}?nbJe$b zK`eWZ=x3#ociv6U$Fm=DSbFG5?lnFh9@3jjJ1^*x$?>ow{A6L+&PPLbX2o4;H`7^+ z`&i@mcBJRVRnbb4(06r}@^2TtBk29}|sh_~cUeIQofh+od5^Y_A?ZI&k_# zZhC5qH%04)W1SE3gJN~vrG+8+uf0m|H`Szq*Ba&0W$ zK63L-sne||uRCfq$WHUC?|jert;(lYWxEd#UHWGR+@_38SHe}9n_|7gxOduJ;P|Rh zQ<#I&TX{sEM)qp((-Bsy3+`5LJ~OG+eXvSPj^Lmugi7S)8^wE!bYXx!-G;a z*63s5t^zq$;azq88_ljh*WVCI`<0zJJ+Z(_bK1qo%*o(c%leIIk1#5H;6696yBAbW zROWQDBws4J5^}|w30EYfK>f5KFZLKSN;J4EAu`SSa>F&HFOAM8mAn0}X3kr9Dp>nT zD+DWQ)#}Y_>*p7xZW+A9!|r9yC*P8w4qgxkCB+pyQVaC4wg!@V*gfA_^tP!m9dC%n zUCb+%quVTGQ;p5;pu_4lRJv)Zh8|JfMH#1iq|(xIvN&DAbnUwVt+iFwi9HX{ijuv0 zhou%yNg9=owzZ`XWIkbHT=BVThvq)}5>PCS;2r!RFF%H|Jg7hv3x%Vv*DHT} zUHu?1Fi^3*aNesqHa~o1Ab+B|KrB$A=h5!fLB$6z$(^jsS^H{;5oI|koHuJMdBd5# zCRE*YO|a4#j>`cb9@I?MYU5i}g2#NCTf#eQ+rY$MpA`Ej($udZ=X<6OPwZj48nODvHWt_U=_#x2<5Vbm+aSf_Jk@ z{`J$9H?7m&GLm zE_%10XB50$&w|SwOPe`~RoPByW!2Nbl~^XxLs+mhE8V-oTr_vfaavD?9BV(1ql1+N zLVlVfs1=)I4p1xdm-{W~577B^?aEa#d=fI~ET|r>x6@zioncM*3N`f1x;LRVxBh98sF}~*6f|XRp|$CVXg5b$ta6odify782stoPy)kjV{wsceTYVk& zr4nAsEbUWTTu~fqgR6iqX243q=z77~cpZ*Mr#hb1Q?5%4%Mr4`aIw zzt`d4VtbP;-Dev^v9=8Qsm_^b2Zug&{p0d+RVvL^G++1k91J(kXKhs$FLrH8)4n%i zgc&xuoLe1Uy4u&w_-2v{%gi-XKjn&y8~Jypbi4K&SmziY+tXm){ld)a$rnQc);-H* z^$0`O#fPmMJdfu_So1Qx#KE(A0uj;zQY#%n}T%5Y*^Z4le<^p;`!}&Xk`0^ zoo9Dv8EO;uqiXNA=*qD?pgDK1N2^9LhR*8C5w46d1;YYPg^Rc@@W?YbMATDRZfwt@ zJw-DTBY)00gHR^@=^^b*=%#aawyRuLiL|ff+}F1AfM$j)N6}gCHC`8ejImcJ?|;s| zIkCUeaL$E5i@PVwc&t(w&%e!P>cFL&b(`oT&E|dfNbGeJo!T_JYkyk>*8r>6c<-brx&Z+8#s2NR7~kKJ{HeuIe8^Fb`$gN^?B$L zpXQRtEJ@WJo;4>D>7VL0RZN!-d8%|625X)bemwG30#Ajv%}Z2?)_Ttx{Ap9Z?>?o+ znqe~q`115EYhFh+zn8sa;<{GAS#|ave!u198G+=~ROz)fFL~m77;$ujM?=k1el6SCab~{;X6L@krdJ2VWrtk4_ z8uTt>v`Fbwbz@;|kI&ipuCvixAAOrE726ae#JqbdyYiWEOV{~xx@LEe#^&yE`&Qtm z6t0;ZmSUZBu|0WellM?@{6^&%O>u|3+=q2Mxhz-Lc-rJ@dNpfXy359S&SuZwm#Wz* z{JPDM$3BGhqxgEw-dS-RCQn%@T*Ip;6FjWQ4`rMnPQhF0~*~*If`S%=C238dNibP{LQBgiHBP%ym?vk zW~WtSDR15K_?)i&SwzHWe50j%!MU;r->=-13k|`#3B=<#@}li-ispMn6?W8k^e$BB zSPeufJkfgW(QwR&LJ~7CNcZNG&3a$|_gKm53e9~I>w8qIDD}6CNEG=rYuM>*zc3WS z(T18)&o_vfJVda{OO&|qI-K!5wp~Fgsrp9mtsYgaO9aO~N7>ScR+bJ4TDl+9e=u6l zwX3Z${A^CaH=*9qNbuh5WV|>m+}tr@Upf?w-?lkPM$GaOdruJKHAQ)Cv-2%^+ty+jx)D8lvH$C53ab(BT(Bok5&{vR#};~-ytXd z>juN8y7%QBc;m2lE(lHIEThn;*k%tOl@-=6zdLjDpygpD7<{Q;^IW^>GZF>o!UF@7@v6jp(-<9 zZmmSR*rooeci9O+ZcWdgquMud4EK69x8&38ssgJ&w=t(Vey&$VhyvCOx{Z&!wmE_KL&i6bd2gJbEt`s<12KxdkG4^=|v8e;P=9 zdjLI?!l6_heuA;)xWF)&xdp97%5BMK1e4NJxs7>*l)b=$nrYP7u%mmMWKC97YX4z< zvynBTZkt`W$K!D?hFWE3Me`@v+EIjlwkM%|y1&ji*OqB;IZ=-OOAguaQ`PFWJ^h zGdG%vhKoQ!*b=CxthDum+YETs*9SVI=S0OD^Ve|lSg#PFdiz4NRU&}Tr+MzeJB!Pj z0Z$L0UkGhz9N+L#nKFRmVPFqO^aT4cpXMs7F5~1-uOwXSbAe%pu)f>HOj$9Pk0kTc z1uJW{mgfqj6?F5`>$*2zKl>tWyd%7VMx}n2W2>o79b2iv&&(#` zxf)~qVR{o~>5#<4bpD5L342#uV1JmUP$h$RqH1nFf2FI%acliZ$YlAuUJqK)LQa?c z6!$mT4k);DH&P|9nzi2WS>%8P^8>~~mDoY2ikt@grtsOzHv;N<1YF+N&V?v4ygKQa zb@k$~{56JFl%kvgmA8?CeEHoVu3}W4kA#a|hsOzU>3a3{j<+wm^eRW?+w%(d{JKSE(kx^NH6M!5)n~ge|);7U{jM^piaeO77TbB zML9p&dHsMn9lbLq;rNKQUp9l9W(+e0K}(+cRK(MXY2^V-i*<_sebf30>fCz%{dDw4 zqYVw;qzW`_@RZP2)_Uh@E>D#qln{KQdjI*Nv_0$@>D4(KTm(#UG+}OXPB_9g-0-^A zX4Y*n4Y48lN+!LZ-bh5cga{d3$W(qVr*4XieILjWK|gqOebji0#nys|k2Jz7x$5+c z!`oS|&Ai@6v%8TyGu05AKBKzon2lf7iR?tpcLqw_-jM;A(xchD`$Y?xrI{00-i;X_ z+*p3U3>^K@SVZ+bl}P+xx!IF1+i%aPmPh#stGXU0oPC~;j@F!n)$A2>t7pyTm|HYE z`>mf+8q^iLHG#(~R;Kz=^Lh%j}}(Fzh^UYmm!OdbCT5DKve=lQr+zjA_tuoJ#q$ck|cOD5-#? zf_XMOw~MCr+3L)%N5H33Wdh})mCvjDwd(q^Y<%;4e78+aP-1&`67FzDFk5$xs^QD< za}jrQFi9aU)A~l)#Z4g`J8wUZU0FN8h)X->r+J>~t%A*`riAP%)2s&0YrX2miQsu^ z&N^&&ZR=;DYh&8?uP4*FT;^e&H4(e?HKg_IXStTu^&wc>>f&=*=L^{hm!4iQ>kf;zMrNgr8hFGc6zg zu^KHZc=a{b7TvF}eIjaa=~1>WZ-F68k6m@*RIg>i)Vh^>j2E=#)GlmJuH8@7+BB-g z#AGns3%-Edx#BLR(?-lRFkElvv9_jgSM4@FxYKLw8{5@s%?QH!&>h7xO83^OELt4n z5vXch9Wz@L)^&4rydVchPf6Ou-3w7o11oGB4q3N$RwI^n_9LZ=)qa51)O53^D$t^6+GDQy+`lMrp$-OknTlY^0Xe-(mz5Kwm zhP$jsD^A3Ge(#C{at>VK%oO9J`4O+<@+bXwhkmZJ+I>eb7VC_^t}$^`6iXFh;Wfw= zIv8QslCL`SLOrW%?cVSdMID?MH%h$SXIhorg^vZ&mXq93e;Kac)z%I zJZmZvUv4=WBH#CzhUZ}Zkvxi=D&5)@+YCm)9F!`M?vYK1ye0A|kSXTnp(Jm%8BUiN zQzExG=UpKuTH10_hE5i821mrs54z!X;u_#DwV@hx+_ny%1WqJWf1+byz24y zl0jR4ZH|!OIV+_qU#sR33Cqd(LhcXroQah4YUOIDTR#r+n&CS=v(yu(1iJ@BvAs@` zyPr-K0CwOIp%}i3zZ75Q-cpiqVUW{zJ{U^-gr@S zgS8=Q8IIBe3A86KdA?ZfT-kGZRh*-R0pn$YV`eJ{_w~-`n^q^1ZIxo|3)Vk(vSEF- z)(_>y79`Nu6m&IF3|nn;=c}2bD0V$EY{p#hl@y(cLe2DjtX}Lh{Nq}>_s`lMqR6!JuS~ymb8Nr(qY+kJG)1OO z_w!-zW)7K@mY0>7?W|iWWv5Rvv}2UkB*a~NS9oK;v4C0$3!6yu3!7t8l@IA=iad5U zVQtx6c0KJsw?e(oc=epQQcQ}B?o*G7N``>u&)GJYwDZClg+xZC)>f)0t1|@ZNz1&$ z7JiV+$#*_8jw@k#G{jdrxh!C`}G(teoo)wb8ITM&z@?Eja?1D zF*anpD&|yHYrJM%4Zrdi)%;M?jx}Z+bywdUv!FP+Zl1a1;{3bv>wTABKib61RzDWF zE2Lp%D9^DilFiv}Gu@3J)bo_7RJN-KZ+m#3V<-muSXnFcP7_1E=0u5a^W%G#NH-F}IW^_V?$=shKfneNqg`gZGSMV)fkvi}md-|&b%!&+(cW=D2 zvYZ^Ca~u&%v}<8jjB#!K+Ihrs^C!dFaEsHt{bN=B=uk#~@Wnr7qm+8lWj}4wVW}+T*IFwToOa((RZ6#ujC{raUjyhW%vozZdX%~68vcU`qq>}lN@ ztvM~7qt?#}jF(V4ZeqOd8pi0=OohMUxZxXTtBS>#(J6WtyHNAnQ`s$|`Br0%{Vp4L zFN`_t(0R|=_LX9+v$U9{y(%dwf4=GNivnp;i%4Nf)JW8ga;}~xoVg}-qLLPKa;vbU$o-m8#NZq%(d6gw_%iS&MCW+adJzOes)PhzV!r#Fx-9pcpyi~ zwpGW|FSPS>am|JwVs2_|)OgRz#3Z$8`C`QaP4%%yslo?z9)Ta`QM%e#t=k&7p!J{( ze(^`)0N~I1%Uuf#3#k8(|NSvo?*9Cao{vw^2|yk30p)yv0+PBqv_b0si6oyh|0EXR zq6Q!UeSus7Fb6ONpaftHut0=paft6K=}Qql9d<}#uogQ{``~i2eHo(Id=h>MJ)fP+@U{= z1!KbUng2%q0mK~t2Iu8s1pJ%)0bhRrI6lV!ZUHQpcOJA=0GtAV^FRuKj|f;c0Pq7S z2Y|NA#mNJ0Fc-|}zg%B_b^Z|JkmpJPdP{(Q0N54{ux7bjFyKT8VhNO}HhCd~U)3rn__`ZVoM*e61qLp42fNp3Bd&o@*+9A9V33Z^&1c03XU-mYC#~+D_ND#9I02$|{WEW_sfEgHRQ`|1(vj7h!vpc z1|Ypxkee}VMtCC<>Oh+^06G5=pgRNb=l99a_#^R_k{|{t7t(SWXrqA~;04OE0OC9PpX>%lnIH3(wF<&!IGk`inph--+vB{bxLgZR?;d2?U7xPN4fspGkCZe+S<| z(8i0H+l8bZa$A9LfH4t39lSvMK@$6EP;Mfr|19@^+6Lzf6_LYJVovh@{<&5myb($C z699hX^X)(7^{f6@AqRK?4yHu@ zUTToDe2Kh}%kO-@|Lpt(p3}g8MEc7Yd0&@ugfRgM0hYUWzjJ;9&qz)K1OO~`u2c;4 zY)kR@Cpr)duA3zQiiJq=>gCpwIwZsHY$MQ0A{3m@-k@G z0U!X7bBA>Ya(kryEB6%If*5}}2O`S_-|=!tT%r#K=x&hM1(CKBZDc_^^j(TKqWd?_ zZ~Z|I*oVJ6KYs>nJOMTXBmqDU@Jtz*7m=W>2mozf03aO6WgcjQxnNFz@_r-rUmbtM zo;YT3E|TY4u3ka(f%l^OH~a!fb1ql@hy2eFd2|8!ck}8!uz_p2Fu)|ha{YvQ7z@UP z<^Rs#j|4${xVBOPz<1owIKejfJInW9uww-_FeZ%s!#eYCjz4)UkgE>>?nw>;knUUI z9vuSdA9>xE=mUNK$9_LufJ)sgue+W!+kMqn*;bi@%!}> z{ej;=|0{n#K>j@c|N4J@8~rzr1q=_r!-(>`{~z^!`$hR3N9_;WzoSr#l7K?dz&awY zv5Zr}I(p0eRwzUKzjp&UkM{q*bqkOv|L-U$Sr!(?q2yawm;rJeg_=Qu9WjvOP|iTf zwB!Z)_@ZU!aNH>70B^<7Q8C7pJxex5l#*A^0xcqC z7yt!80uitbbqc>62pEEqTEyS^fVhkRuK?hlG!p=>zeNDZJMcbH2iu?xv}OFexPO-) z#DM4Z767UM$eRDF68b=2`2W(gA+`qy$#2z_ggfU>OFmfJ0$q((3IPjjreM~<9jywi=9oQTPfct3p z-H7b5VXOplTk`zC2HtNt=A`|G=Tx=;@EyPS8zp%h(mJq#&&L>m0|5LML;3+@!q|V# zhb8jE`GVL(3HPUPEb0Irk>**h4D4XPs{vr&VLr&4G^PdOOPU|pz-J83S<<<7AF=s6 z31cp01L7giCgcEP!yJpxCSnhLfet>iq&$DAjKl!G`~dJ=`d9p3k@6+xhwH|#`2Jvn zeA?w|~x_djzZdPI`8!7|j7UO-0! z@R{5W)J*`^0+6l?NS-i~_!PhfuIEVGCL}(zA<-|k6LoM+fLIN1iQER%`;i!+Y){q> zb5W4wCtYt~4sOJEsr+QI5YFV%6^Q}tc>&DH{1V9WlRkH=5Z`~8AD)+y|LzIDc}Y2v z<|iNjE5KG1a`=b&VIEJU51_09kPm?5Cm(;(`8NRUt^s@_86U)NQ9?cG1#H=u;z{EF z71%@ri~u09Navpd(8Ff}ww(olB>t2F&&6^G9scA-2r{ z*+MMCXKI>Q{(-}<=!l#cfbB_uSgCEq_po(Dkt54n&z@Vk;2j|apfki|T(I4IyhNKB*- z?3UVpbOHTF#O7Be@Yw(WeUbj)LHVcq4c*8VgbOH+8-Av z!}$i!d}aWU+))1Q{);5Wa{JG55a%L*9st}|z_V32Zy}Ez05Jfh&p6Br`wjc^%ll6f z9+AKg##nAnN`N*^q77+ZNqv5M|4ot~&IbzsIA_V@!+JXa=^m5R2KqqXKlhtRTtt%3 zKSWP1K@9k8!f}Rc6!I(=fif~Kuncp;xV}QbGStccU`$d0ZOi~S z07&O5eCI)s>YxoXi7UMK&=>g)AHEw;1Bd{iiGXFOL-wN3_RkogjO2yS4L@mY(lTrV zfHsiN4cG=G>@UI(?zOLxK@`+E0pNUuZKV5gWULVXrQ}xN1J|#m+K_REZN30-eMRgV zKp6+H8sIfi51&g907qiI3rKi>riguk`)0%+t{;%^0}>q`+QAFxrU0NX#8;w@)E|jM zDi1F@|KShc9ncqYfHuMar2fUAz77EX22uh5ZRP=>4%)&x^i3p|n}Mt%mSG$G=4%9i zYYws=LA?|}AOI{wU()*rb<1G}v;_e`KFB;;oX?3rfVPYC zhd6Ge^LGNY1ptVUj1}xJ diff --git a/doc/rust-logo-128x128-blk-v2.png b/doc/rust-logo-128x128-blk-v2.png deleted file mode 100644 index 74b4bd695045ebc52c21af95301adc9311ca881c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5758 zcmV-^7J=!BP)rlOar#xVHcKR}urj-85WU}*d52ce!FO;4x1(Dd{rLvS^kzaz+Qg+43&c`E^ z2A4h%FgKT)L-C6=0SiO%&803L%dQ&ad>le)iUzvAtx3hUp3qiqE4OmtpW{`0v8nBU z+vNFwgO#K7`BHl6Lk5HT&J zd0%5WX?GeMO2>h@YkR3UyYLB!%U`9zGx2pv`bl*gj{l2(jn1Mg!nL1jDhv@mJF-Z) z67J}KBA8uxsR*X=Sf`PpG*`ff8oxRCuGi#KZ;di+0mQR!BHISEExW1CGQBlHFEkNU z(hzW6fL~TqN}IfE{LRuTaMO61)5uVoEy2s0>}~aTd9vJ#3c3NFB;T~tqib}0T!03k zRgt=rZq*e6NSNg`GPKSp8t`0%sVfTb6iOXlX|k6#hX|N!eoNB^SLi}PkbuM0isxjy z)5uUb6|B7};Xr|h82+jxduUULfQwjMPa@4>-q38f5EGn6hWupPwaF{BhvVvGa)^K@ zX|>ns>X7FY7!n%W4tV3VU&m`b2j6q4zfYf_ujx$xnS4s6M$Tce%Fe$?pCG$c!>Hop z#?j*z!PbLgoZbtiBT7$|)|75(J=<@U1f0m=D|O^qtPFkyy`D~>hq97Bm~?7zZ;%T} z8~GfW&%P^pLJ%^7Od!{jl`1wwhao}S-B~I$U^|6yiKp9x6@U^ z9zfH$!pSPMb+)nuLoTjXL7Lv!-A_+SN{tY*DG~mHtPe-SxM*{NK7?`^%<$xScZYA$WuF!hmCsQ!r$to142By6i zR=<@Ur#d=6p?*&(k|W8E5R4!7oD1TUpQKR0^3WRd4*U)$s}T6UY~iUid|pbuC%>g% ztS(Jv{65eSeo$>r$QQ{oi4?F`D;Px6XYictg4f9s*3A!1gwGnUOKM4zj3oDxHRQj^ z)Y|ewE+M-TDG+UftD4PDC(A&81g*Sp;M-cjZ~8nL?KCKmQDj*X1=ym1{JWE7Aak*; z{PEuWO-_RYxhatXum${RZk_%8)>(zw`RU#nOvckw=~mI%iMqS$*5^2V5b!xEwgCDJ zTbMI7p7Q)p_h$REg5zp|-_AR`mgVQ~06z}?UGfE|j{^Au`M($iEN4Y^r1A<~=1JAJ z`wxo2C|lL}v1#}W{7t0I>BE4FcoWu6k?{)(aAXKz50K7!5&Fq3(ZaKFm0!|oM+J=BV z@cK=A9~X7g-jtW|b@($CC^*T$$Dp^o)=L6%<&j$_46L;SbQL22`rOa~tt7n-U&#{u zrBn*$=(BWw3$nw8%B@${-o)(ZZ)1sp`u9C_BX{9LQYiRE=sd2qs>8n3-LH1%w~21I ztbb@XnQ3RO$HycRaDXy~M)FV%-k}Fq4cy1xI69TwNMFU^`75a#dJJF$s%t(C zO=(0;O{Cyx>kMPSd0sp5jidvQBe+tnpA)`sp6&7sP>T5-_n9h5ZNQ&MAoRC?1S zUIq3Ye!N21VA6<+UJFO+tZsLB1pbsr4x}#URq3-=OBt2YCcG|Y1SkUtWJINUb&rBG zpsSU%v+c(8TM+_Qgy=F0F4Xz#D41Qz{dpYv0KRGe6%Fv&6Z|O1X#LGZEP9`_bMKC0 zad85`o{6gtEsuJnaxd_p{OkP0ygl`}j?L-42?UVpls-yIX3%3=@E-o8MZhDLc5KI8 z>^oFjUZCQtme-31_B8W<4!ej~04VQ0qrMRgVt(O4+&6VTLd&ndbOe#GeesUXSm8$RWFTOJ5A{O=@B~*BwBR%g{)Lt!v@)3hHyZ** zxF1zXz(ewi&saJbnid~%HyCdu2KkX0F5w6_Km}OFe~knMt1Ge|(d^I-Q!dR?A1qMBEgLCH$8m~@I` zW8)`UHbBK@M1VUKy^N}Z|AM||e|L50m-VcHzQJ9N?H;VQ0wR`I0p$`?MAw@W^XbE% z0CkUaK#dWsPTH#&jo!~a1+7J8A^J)Luecm((N=Q*l;AIhrc8VpOZodcg6!$NZw7@Vt9Sv>Q1PKh1suQvr~p@K?GQ;-*;lb75_c3#v~b4b$4kE6`N;8FRN# z#pMG&P^?dpfyv{l%ee{k!B&RhKZZ|Bx#7Y_K@ZVzS4AuGk4)P>V(<+C{3?!(=VV#> z^uj~n1wk!JR1DGnF6JDOSb% zGeWo~$o;(HkpumGK(A{V1Y=-nC# zSe8n_Tgc9lEOVr)03X!-J|2+lI6Q>7w*=6QM|gK-0;(?k(<-X1i|(kAg4UFjUS_|k z?lAwRDe!=RMd_F9es>|>NJ&p!kUK0UxQ&L&22?!0(=Y)2nw9XJ2 zM3(Y;LRC{?#sj*@fXW1*j0j+vzpVxWev_EO0cevocA$EKQUfS_dpb6;PCiAKvAQqY z%4mO@6dFdrK(wt|0@#`RC#29Se>Htj^~t>*g=!f!QmtS819hLdap+ACyvAd zmfrO>=s=Kg{WUT8ngY+(i}l!5ouN^*i&#^iK6^z*)aEsifWNPSfN#gH_R%g0SicNt zFMQmEM*;!M%p^D#<0cdu57Q}ru0n=?T6K1(R7Jo5^mYvtTok%?Jlc>pf|x5)MSy7= zV%tcYOghMrXj52VD*#qvXfMO7JbIUa84&_T z*PWsilgpg&Z*n|lg*z7&DvhK49A;0Ef!=${pG?33Xk*=JMh4_^(g#2boSwqpeZ56C zg^UP2kbrxWf*G-v;IX>XjO5Q1hCSEw5}D5qZClr(M+J!O4fGE9WCE_PJ54Be3BCpT zflTPS;?Rl&ankMu_ohDFz&-3yJ9OkjQu}N!0Cwh-k z{>TgmtNVpHyYBan4ValaIP!;j({2$(+F}ZF2VPAcB@-(>E#}f=Xa}7~J6*9u3+hc5 zsK;>v^dEKAeqM+W(~0J}9quu55TxfIwmjO7VZlrs{&F+{{S*4<4CGw&FNjtg9~jNf zIlrfLSZ+>5FUHCro*U)MDG#pwxxoQso6rGX8KMNd&8DXMSzttMm!+>?SapE5?ZbnU z-c_vTt5M?kVwXMrivlzfeW=x6zFJ_dE9AGZ>~`--0@{wQMdzV0XlN*Q7SV4!IaESt zq50^yT>Z4%=JZNHL#)BFH_)%y`0p7gVDUrI3RC(yD1B)D?786cYTGe#J-aMEudb4m zw?RA5M~POrS9TRa|CVs4577(gH4DD+{&;~w!GWx+r2=%Y?xPtT=ly7DPK*xZDlcQ} zg@86xX!bzVcj(EOHG=T{%<3PYe$dPjW65No9OJYM*vG$eG7l&~-4zMY-7*KN=O61`#I`)1j!(y@ljGTzM0}?fVGLU$?Ln?9Cp(w9{d0?T7RNXl z2W!ggYCU#%Ym)Kvp$oJXpNfumPe-TY>39~oh#p(_R$4i!S}3&YV#F!osZFVjGo6eB z`i%tpXejpgN(1C4H-7w+Z>5!GAoF=`%0YVoA}U1iW+a>U$?V+eWExm$Z;|&sJ`_LI zHh#!j;e@l>PEio>Dyv13f$;E4ijXX~ z)1$sxGlVn+IcQ_M3rB`Bv`(txE_9%iVL;!|2KK@b;a7|Mf#0X5^HlrgJ6Q$xjGdYx zlzr^H@e-ap>;Rq3n{uW}I?l;3pxboH8__2<{6cPrr~+y}6ADQ!^v%vG_vV|)Q`JQ( za8DalZWWmtjG?EX`=vXg`U>A;Q&1TM2J@QSPK(-3G$A*XNk{H2xSwZ?vptlbofYsq zJ^i#DRxK;6D>uuL!b1`8*^M4#Q=P;28TznX2U~#AZQ6O=>}^Ne0lW*3#`Et`9Okk4 z?6%d-uk`gFA9$<0JLwfzj1{n0MTqeWY*A}@eu<`|QML8%*%iOcZPE7Kq-RKwmC=KC z|Lx!ke5bq0+BV@uC#w(~o?q&(rZ9wr8d>J~8En^y% z2znU%-$b*zNVnsnRnr>n~(ysag2rk-8fK73;m5*i>~l;9b}t zQ}yxS#iX^df3QGjgtk=z2bAl9Bq3+RPpi$90mEnHh=R=zKNKnEvBos^FE+f{UU+Ar zEodh)7J-))&=7~3uG}HG<~P;c$vXo4o$glI!1YW7{J zD9;i!RSHsE(xB`27I`%rpE6d4-(xi|mf66RwXOsx{JgT!i&sSD8cr7J-NLi% zT3|NiA>VWRl^ zwH5xSEz5vNcWCqFXGBN$dQ~;_^F8y#*}t=G0_mnXOTUitSBgJnJj3a~p>T9zV$3!y zu`0$gJXjL5ksX=G7&pk+A!NCw>`M|T?$3X_n;iTp`d`V`o4;5i<3pQt9IxY>*jcj8 z@c#DxcsVHqgM$ymU-NbO%^{PyNdN!jgQ56lze}k42l=i#eB47}N?|*bK2`Mp2a}$;#7RWswg3PC07*qoM6N<$g8zmuE&u=k diff --git a/integer/Cargo.toml b/integer/Cargo.toml deleted file mode 100644 index 5a928b4..0000000 --- a/integer/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -description = "Integer traits and functions" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics"] -categories = [ "algorithms", "science" ] -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num" -name = "num-integer" -version = "0.1.35" - -[dependencies.num-traits] -path = "../traits" -version = "0.1.32" diff --git a/integer/LICENSE-APACHE b/integer/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/integer/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/integer/LICENSE-MIT b/integer/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/integer/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/integer/src/lib.rs b/integer/src/lib.rs deleted file mode 100644 index 4d85a39..0000000 --- a/integer/src/lib.rs +++ /dev/null @@ -1,988 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Integer trait and functions. -#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://rust-num.github.io/num/favicon.ico", - html_root_url = "https://rust-num.github.io/num/", - html_playground_url = "http://play.integer32.com/")] - -extern crate num_traits as traits; - -use std::ops::Add; - -use traits::{Num, Signed}; - -pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { - /// Floored integer division. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert!(( 8).div_floor(& 3) == 2); - /// assert!(( 8).div_floor(&-3) == -3); - /// assert!((-8).div_floor(& 3) == -3); - /// assert!((-8).div_floor(&-3) == 2); - /// - /// assert!(( 1).div_floor(& 2) == 0); - /// assert!(( 1).div_floor(&-2) == -1); - /// assert!((-1).div_floor(& 2) == -1); - /// assert!((-1).div_floor(&-2) == 0); - /// ~~~ - fn div_floor(&self, other: &Self) -> Self; - - /// Floored integer modulo, satisfying: - /// - /// ~~~ - /// # use num_integer::Integer; - /// # let n = 1; let d = 1; - /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n) - /// ~~~ - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert!(( 8).mod_floor(& 3) == 2); - /// assert!(( 8).mod_floor(&-3) == -1); - /// assert!((-8).mod_floor(& 3) == 1); - /// assert!((-8).mod_floor(&-3) == -2); - /// - /// assert!(( 1).mod_floor(& 2) == 1); - /// assert!(( 1).mod_floor(&-2) == -1); - /// assert!((-1).mod_floor(& 2) == 1); - /// assert!((-1).mod_floor(&-2) == -1); - /// ~~~ - fn mod_floor(&self, other: &Self) -> Self; - - /// Greatest Common Divisor (GCD). - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(6.gcd(&8), 2); - /// assert_eq!(7.gcd(&3), 1); - /// ~~~ - fn gcd(&self, other: &Self) -> Self; - - /// Lowest Common Multiple (LCM). - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(7.lcm(&3), 21); - /// assert_eq!(2.lcm(&4), 4); - /// ~~~ - fn lcm(&self, other: &Self) -> Self; - - /// Deprecated, use `is_multiple_of` instead. - fn divides(&self, other: &Self) -> bool; - - /// Returns `true` if `other` is a multiple of `self`. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(9.is_multiple_of(&3), true); - /// assert_eq!(3.is_multiple_of(&9), false); - /// ~~~ - fn is_multiple_of(&self, other: &Self) -> bool; - - /// Returns `true` if the number is even. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(3.is_even(), false); - /// assert_eq!(4.is_even(), true); - /// ~~~ - fn is_even(&self) -> bool; - - /// Returns `true` if the number is odd. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(3.is_odd(), true); - /// assert_eq!(4.is_odd(), false); - /// ~~~ - fn is_odd(&self) -> bool; - - /// Simultaneous truncated integer division and modulus. - /// Returns `(quotient, remainder)`. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(( 8).div_rem( &3), ( 2, 2)); - /// assert_eq!(( 8).div_rem(&-3), (-2, 2)); - /// assert_eq!((-8).div_rem( &3), (-2, -2)); - /// assert_eq!((-8).div_rem(&-3), ( 2, -2)); - /// - /// assert_eq!(( 1).div_rem( &2), ( 0, 1)); - /// assert_eq!(( 1).div_rem(&-2), ( 0, 1)); - /// assert_eq!((-1).div_rem( &2), ( 0, -1)); - /// assert_eq!((-1).div_rem(&-2), ( 0, -1)); - /// ~~~ - #[inline] - fn div_rem(&self, other: &Self) -> (Self, Self); - - /// Simultaneous floored integer division and modulus. - /// Returns `(quotient, remainder)`. - /// - /// # Examples - /// - /// ~~~ - /// # use num_integer::Integer; - /// assert_eq!(( 8).div_mod_floor( &3), ( 2, 2)); - /// assert_eq!(( 8).div_mod_floor(&-3), (-3, -1)); - /// assert_eq!((-8).div_mod_floor( &3), (-3, 1)); - /// assert_eq!((-8).div_mod_floor(&-3), ( 2, -2)); - /// - /// assert_eq!(( 1).div_mod_floor( &2), ( 0, 1)); - /// assert_eq!(( 1).div_mod_floor(&-2), (-1, -1)); - /// assert_eq!((-1).div_mod_floor( &2), (-1, 1)); - /// assert_eq!((-1).div_mod_floor(&-2), ( 0, -1)); - /// ~~~ - fn div_mod_floor(&self, other: &Self) -> (Self, Self) { - (self.div_floor(other), self.mod_floor(other)) - } -} - -/// Simultaneous integer division and modulus -#[inline] -pub fn div_rem(x: T, y: T) -> (T, T) { - x.div_rem(&y) -} -/// Floored integer division -#[inline] -pub fn div_floor(x: T, y: T) -> T { - x.div_floor(&y) -} -/// Floored integer modulus -#[inline] -pub fn mod_floor(x: T, y: T) -> T { - x.mod_floor(&y) -} -/// Simultaneous floored integer division and modulus -#[inline] -pub fn div_mod_floor(x: T, y: T) -> (T, T) { - x.div_mod_floor(&y) -} - -/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The -/// result is always positive. -#[inline(always)] -pub fn gcd(x: T, y: T) -> T { - x.gcd(&y) -} -/// Calculates the Lowest Common Multiple (LCM) of the number and `other`. -#[inline(always)] -pub fn lcm(x: T, y: T) -> T { - x.lcm(&y) -} - -macro_rules! impl_integer_for_isize { - ($T:ty, $test_mod:ident) => ( - impl Integer for $T { - /// Floored integer division - #[inline] - fn div_floor(&self, other: &Self) -> Self { - // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, - // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - match self.div_rem(other) { - (d, r) if (r > 0 && *other < 0) - || (r < 0 && *other > 0) => d - 1, - (d, _) => d, - } - } - - /// Floored integer modulo - #[inline] - fn mod_floor(&self, other: &Self) -> Self { - // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, - // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - match *self % *other { - r if (r > 0 && *other < 0) - || (r < 0 && *other > 0) => r + *other, - r => r, - } - } - - /// Calculates `div_floor` and `mod_floor` simultaneously - #[inline] - fn div_mod_floor(&self, other: &Self) -> (Self, Self) { - // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, - // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) - match self.div_rem(other) { - (d, r) if (r > 0 && *other < 0) - || (r < 0 && *other > 0) => (d - 1, r + *other), - (d, r) => (d, r), - } - } - - /// Calculates the Greatest Common Divisor (GCD) of the number and - /// `other`. The result is always positive. - #[inline] - fn gcd(&self, other: &Self) -> Self { - // Use Stein's algorithm - let mut m = *self; - let mut n = *other; - if m == 0 || n == 0 { return (m | n).abs() } - - // find common factors of 2 - let shift = (m | n).trailing_zeros(); - - // The algorithm needs positive numbers, but the minimum value - // can't be represented as a positive one. - // It's also a power of two, so the gcd can be - // calculated by bitshifting in that case - - // Assuming two's complement, the number created by the shift - // is positive for all numbers except gcd = abs(min value) - // The call to .abs() causes a panic in debug mode - if m == Self::min_value() || n == Self::min_value() { - return (1 << shift).abs() - } - - // guaranteed to be positive now, rest like unsigned algorithm - m = m.abs(); - n = n.abs(); - - // divide n and m by 2 until odd - // m inside loop - n >>= n.trailing_zeros(); - - while m != 0 { - m >>= m.trailing_zeros(); - if n > m { ::std::mem::swap(&mut n, &mut m) } - m -= n; - } - - n << shift - } - - /// Calculates the Lowest Common Multiple (LCM) of the number and - /// `other`. - #[inline] - fn lcm(&self, other: &Self) -> Self { - // should not have to recalculate abs - (*self * (*other / self.gcd(other))).abs() - } - - /// Deprecated, use `is_multiple_of` instead. - #[inline] - fn divides(&self, other: &Self) -> bool { - self.is_multiple_of(other) - } - - /// Returns `true` if the number is a multiple of `other`. - #[inline] - fn is_multiple_of(&self, other: &Self) -> bool { - *self % *other == 0 - } - - /// Returns `true` if the number is divisible by `2` - #[inline] - fn is_even(&self) -> bool { (*self) & 1 == 0 } - - /// Returns `true` if the number is not divisible by `2` - #[inline] - fn is_odd(&self) -> bool { !self.is_even() } - - /// Simultaneous truncated integer division and modulus. - #[inline] - fn div_rem(&self, other: &Self) -> (Self, Self) { - (*self / *other, *self % *other) - } - } - - #[cfg(test)] - mod $test_mod { - use Integer; - - /// Checks that the division rule holds for: - /// - /// - `n`: numerator (dividend) - /// - `d`: denominator (divisor) - /// - `qr`: quotient and remainder - #[cfg(test)] - fn test_division_rule((n,d): ($T, $T), (q,r): ($T, $T)) { - assert_eq!(d * q + r, n); - } - - #[test] - fn test_div_rem() { - fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) { - let (n,d) = nd; - let separate_div_rem = (n / d, n % d); - let combined_div_rem = n.div_rem(&d); - - assert_eq!(separate_div_rem, qr); - assert_eq!(combined_div_rem, qr); - - test_division_rule(nd, separate_div_rem); - test_division_rule(nd, combined_div_rem); - } - - test_nd_dr(( 8, 3), ( 2, 2)); - test_nd_dr(( 8, -3), (-2, 2)); - test_nd_dr((-8, 3), (-2, -2)); - test_nd_dr((-8, -3), ( 2, -2)); - - test_nd_dr(( 1, 2), ( 0, 1)); - test_nd_dr(( 1, -2), ( 0, 1)); - test_nd_dr((-1, 2), ( 0, -1)); - test_nd_dr((-1, -2), ( 0, -1)); - } - - #[test] - fn test_div_mod_floor() { - fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) { - let (n,d) = nd; - let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d)); - let combined_div_mod_floor = n.div_mod_floor(&d); - - assert_eq!(separate_div_mod_floor, dm); - assert_eq!(combined_div_mod_floor, dm); - - test_division_rule(nd, separate_div_mod_floor); - test_division_rule(nd, combined_div_mod_floor); - } - - test_nd_dm(( 8, 3), ( 2, 2)); - test_nd_dm(( 8, -3), (-3, -1)); - test_nd_dm((-8, 3), (-3, 1)); - test_nd_dm((-8, -3), ( 2, -2)); - - test_nd_dm(( 1, 2), ( 0, 1)); - test_nd_dm(( 1, -2), (-1, -1)); - test_nd_dm((-1, 2), (-1, 1)); - test_nd_dm((-1, -2), ( 0, -1)); - } - - #[test] - fn test_gcd() { - assert_eq!((10 as $T).gcd(&2), 2 as $T); - assert_eq!((10 as $T).gcd(&3), 1 as $T); - assert_eq!((0 as $T).gcd(&3), 3 as $T); - assert_eq!((3 as $T).gcd(&3), 3 as $T); - assert_eq!((56 as $T).gcd(&42), 14 as $T); - assert_eq!((3 as $T).gcd(&-3), 3 as $T); - assert_eq!((-6 as $T).gcd(&3), 3 as $T); - assert_eq!((-4 as $T).gcd(&-2), 2 as $T); - } - - #[test] - fn test_gcd_cmp_with_euclidean() { - fn euclidean_gcd(mut m: $T, mut n: $T) -> $T { - while m != 0 { - ::std::mem::swap(&mut m, &mut n); - m %= n; - } - - n.abs() - } - - // gcd(-128, b) = 128 is not representable as positive value - // for i8 - for i in -127..127 { - for j in -127..127 { - assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); - } - } - - // last value - // FIXME: Use inclusive ranges for above loop when implemented - let i = 127; - for j in -127..127 { - assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); - } - assert_eq!(127.gcd(&127), 127); - } - - #[test] - fn test_gcd_min_val() { - let min = <$T>::min_value(); - let max = <$T>::max_value(); - let max_pow2 = max / 2 + 1; - assert_eq!(min.gcd(&max), 1 as $T); - assert_eq!(max.gcd(&min), 1 as $T); - assert_eq!(min.gcd(&max_pow2), max_pow2); - assert_eq!(max_pow2.gcd(&min), max_pow2); - assert_eq!(min.gcd(&42), 2 as $T); - assert_eq!((42 as $T).gcd(&min), 2 as $T); - } - - #[test] - #[should_panic] - fn test_gcd_min_val_min_val() { - let min = <$T>::min_value(); - assert!(min.gcd(&min) >= 0); - } - - #[test] - #[should_panic] - fn test_gcd_min_val_0() { - let min = <$T>::min_value(); - assert!(min.gcd(&0) >= 0); - } - - #[test] - #[should_panic] - fn test_gcd_0_min_val() { - let min = <$T>::min_value(); - assert!((0 as $T).gcd(&min) >= 0); - } - - #[test] - fn test_lcm() { - assert_eq!((1 as $T).lcm(&0), 0 as $T); - assert_eq!((0 as $T).lcm(&1), 0 as $T); - assert_eq!((1 as $T).lcm(&1), 1 as $T); - assert_eq!((-1 as $T).lcm(&1), 1 as $T); - assert_eq!((1 as $T).lcm(&-1), 1 as $T); - assert_eq!((-1 as $T).lcm(&-1), 1 as $T); - assert_eq!((8 as $T).lcm(&9), 72 as $T); - assert_eq!((11 as $T).lcm(&5), 55 as $T); - } - - #[test] - fn test_even() { - assert_eq!((-4 as $T).is_even(), true); - assert_eq!((-3 as $T).is_even(), false); - assert_eq!((-2 as $T).is_even(), true); - assert_eq!((-1 as $T).is_even(), false); - assert_eq!((0 as $T).is_even(), true); - assert_eq!((1 as $T).is_even(), false); - assert_eq!((2 as $T).is_even(), true); - assert_eq!((3 as $T).is_even(), false); - assert_eq!((4 as $T).is_even(), true); - } - - #[test] - fn test_odd() { - assert_eq!((-4 as $T).is_odd(), false); - assert_eq!((-3 as $T).is_odd(), true); - assert_eq!((-2 as $T).is_odd(), false); - assert_eq!((-1 as $T).is_odd(), true); - assert_eq!((0 as $T).is_odd(), false); - assert_eq!((1 as $T).is_odd(), true); - assert_eq!((2 as $T).is_odd(), false); - assert_eq!((3 as $T).is_odd(), true); - assert_eq!((4 as $T).is_odd(), false); - } - } - ) -} - -impl_integer_for_isize!(i8, test_integer_i8); -impl_integer_for_isize!(i16, test_integer_i16); -impl_integer_for_isize!(i32, test_integer_i32); -impl_integer_for_isize!(i64, test_integer_i64); -impl_integer_for_isize!(isize, test_integer_isize); - -macro_rules! impl_integer_for_usize { - ($T:ty, $test_mod:ident) => ( - impl Integer for $T { - /// Unsigned integer division. Returns the same result as `div` (`/`). - #[inline] - fn div_floor(&self, other: &Self) -> Self { - *self / *other - } - - /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). - #[inline] - fn mod_floor(&self, other: &Self) -> Self { - *self % *other - } - - /// Calculates the Greatest Common Divisor (GCD) of the number and `other` - #[inline] - fn gcd(&self, other: &Self) -> Self { - // Use Stein's algorithm - let mut m = *self; - let mut n = *other; - if m == 0 || n == 0 { return m | n } - - // find common factors of 2 - let shift = (m | n).trailing_zeros(); - - // divide n and m by 2 until odd - // m inside loop - n >>= n.trailing_zeros(); - - while m != 0 { - m >>= m.trailing_zeros(); - if n > m { ::std::mem::swap(&mut n, &mut m) } - m -= n; - } - - n << shift - } - - /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. - #[inline] - fn lcm(&self, other: &Self) -> Self { - *self * (*other / self.gcd(other)) - } - - /// Deprecated, use `is_multiple_of` instead. - #[inline] - fn divides(&self, other: &Self) -> bool { - self.is_multiple_of(other) - } - - /// Returns `true` if the number is a multiple of `other`. - #[inline] - fn is_multiple_of(&self, other: &Self) -> bool { - *self % *other == 0 - } - - /// Returns `true` if the number is divisible by `2`. - #[inline] - fn is_even(&self) -> bool { - *self % 2 == 0 - } - - /// Returns `true` if the number is not divisible by `2`. - #[inline] - fn is_odd(&self) -> bool { - !self.is_even() - } - - /// Simultaneous truncated integer division and modulus. - #[inline] - fn div_rem(&self, other: &Self) -> (Self, Self) { - (*self / *other, *self % *other) - } - } - - #[cfg(test)] - mod $test_mod { - use Integer; - - #[test] - fn test_div_mod_floor() { - assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T); - assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T); - assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T)); - assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T); - assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T); - assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T)); - assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T); - assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T); - assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T)); - } - - #[test] - fn test_gcd() { - assert_eq!((10 as $T).gcd(&2), 2 as $T); - assert_eq!((10 as $T).gcd(&3), 1 as $T); - assert_eq!((0 as $T).gcd(&3), 3 as $T); - assert_eq!((3 as $T).gcd(&3), 3 as $T); - assert_eq!((56 as $T).gcd(&42), 14 as $T); - } - - #[test] - fn test_gcd_cmp_with_euclidean() { - fn euclidean_gcd(mut m: $T, mut n: $T) -> $T { - while m != 0 { - ::std::mem::swap(&mut m, &mut n); - m %= n; - } - n - } - - for i in 0..255 { - for j in 0..255 { - assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); - } - } - - // last value - // FIXME: Use inclusive ranges for above loop when implemented - let i = 255; - for j in 0..255 { - assert_eq!(euclidean_gcd(i,j), i.gcd(&j)); - } - assert_eq!(255.gcd(&255), 255); - } - - #[test] - fn test_lcm() { - assert_eq!((1 as $T).lcm(&0), 0 as $T); - assert_eq!((0 as $T).lcm(&1), 0 as $T); - assert_eq!((1 as $T).lcm(&1), 1 as $T); - assert_eq!((8 as $T).lcm(&9), 72 as $T); - assert_eq!((11 as $T).lcm(&5), 55 as $T); - assert_eq!((15 as $T).lcm(&17), 255 as $T); - } - - #[test] - fn test_is_multiple_of() { - assert!((6 as $T).is_multiple_of(&(6 as $T))); - assert!((6 as $T).is_multiple_of(&(3 as $T))); - assert!((6 as $T).is_multiple_of(&(1 as $T))); - } - - #[test] - fn test_even() { - assert_eq!((0 as $T).is_even(), true); - assert_eq!((1 as $T).is_even(), false); - assert_eq!((2 as $T).is_even(), true); - assert_eq!((3 as $T).is_even(), false); - assert_eq!((4 as $T).is_even(), true); - } - - #[test] - fn test_odd() { - assert_eq!((0 as $T).is_odd(), false); - assert_eq!((1 as $T).is_odd(), true); - assert_eq!((2 as $T).is_odd(), false); - assert_eq!((3 as $T).is_odd(), true); - assert_eq!((4 as $T).is_odd(), false); - } - } - ) -} - -impl_integer_for_usize!(u8, test_integer_u8); -impl_integer_for_usize!(u16, test_integer_u16); -impl_integer_for_usize!(u32, test_integer_u32); -impl_integer_for_usize!(u64, test_integer_u64); -impl_integer_for_usize!(usize, test_integer_usize); - -/// An iterator over binomial coefficients. -pub struct IterBinomial { - a: T, - n: T, - k: T, -} - -impl IterBinomial - where T: Integer, -{ - /// For a given n, iterate over all binomial coefficients binomial(n, k), for k=0...n. - /// - /// Note that this might overflow, depending on `T`. For the primitive - /// integer types, the following n are the largest ones for which there will - /// be no overflow: - /// - /// type | n - /// -----|--- - /// u8 | 10 - /// i8 | 9 - /// u16 | 18 - /// i16 | 17 - /// u32 | 34 - /// i32 | 33 - /// u64 | 67 - /// i64 | 66 - /// - /// For larger n, `T` should be a bigint type. - pub fn new(n: T) -> IterBinomial { - IterBinomial { - k: T::zero(), a: T::one(), n: n - } - } -} - -impl Iterator for IterBinomial - where T: Integer + Clone -{ - type Item = T; - - fn next(&mut self) -> Option { - if self.k > self.n { - return None; - } - self.a = if !self.k.is_zero() { - multiply_and_divide( - self.a.clone(), - self.n.clone() - self.k.clone() + T::one(), - self.k.clone() - ) - } else { - T::one() - }; - self.k = self.k.clone() + T::one(); - Some(self.a.clone()) - } -} - -/// Calculate r * a / b, avoiding overflows and fractions. -/// -/// Assumes that b divides r * a evenly. -fn multiply_and_divide(r: T, a: T, b: T) -> T { - // See http://blog.plover.com/math/choose-2.html for the idea. - let g = gcd(r.clone(), b.clone()); - r/g.clone() * (a / (b/g)) -} - -/// Calculate the binomial coefficient. -/// -/// Note that this might overflow, depending on `T`. For the primitive integer -/// types, the following n are the largest ones possible such that there will -/// be no overflow for any k: -/// -/// type | n -/// -----|--- -/// u8 | 10 -/// i8 | 9 -/// u16 | 18 -/// i16 | 17 -/// u32 | 34 -/// i32 | 33 -/// u64 | 67 -/// i64 | 66 -/// -/// For larger n, consider using a bigint type for `T`. -pub fn binomial(mut n: T, k: T) -> T { - // See http://blog.plover.com/math/choose.html for the idea. - if k > n { - return T::zero(); - } - if k > n.clone() - k.clone() { - return binomial(n.clone(), n - k); - } - let mut r = T::one(); - let mut d = T::one(); - loop { - if d > k { - break; - } - r = multiply_and_divide(r, n.clone(), d.clone()); - n = n - T::one(); - d = d + T::one(); - } - r -} - -/// Calculate the multinomial coefficient. -pub fn multinomial(k: &[T]) -> T - where for<'a> T: Add<&'a T, Output = T> -{ - let mut r = T::one(); - let mut p = T::zero(); - for i in k { - p = p + i; - r = r * binomial(p.clone(), i.clone()); - } - r -} - -#[test] -fn test_lcm_overflow() { - macro_rules! check { - ($t:ty, $x:expr, $y:expr, $r:expr) => { { - let x: $t = $x; - let y: $t = $y; - let o = x.checked_mul(y); - assert!(o.is_none(), - "sanity checking that {} input {} * {} overflows", - stringify!($t), x, y); - assert_eq!(x.lcm(&y), $r); - assert_eq!(y.lcm(&x), $r); - } } - } - - // Original bug (Issue #166) - check!(i64, 46656000000000000, 600, 46656000000000000); - - check!(i8, 0x40, 0x04, 0x40); - check!(u8, 0x80, 0x02, 0x80); - check!(i16, 0x40_00, 0x04, 0x40_00); - check!(u16, 0x80_00, 0x02, 0x80_00); - check!(i32, 0x4000_0000, 0x04, 0x4000_0000); - check!(u32, 0x8000_0000, 0x02, 0x8000_0000); - check!(i64, 0x4000_0000_0000_0000, 0x04, 0x4000_0000_0000_0000); - check!(u64, 0x8000_0000_0000_0000, 0x02, 0x8000_0000_0000_0000); -} - -#[test] -fn test_iter_binomial() { - macro_rules! check_simple { - ($t:ty) => { { - let n: $t = 3; - let c: Vec<_> = IterBinomial::new(n).collect(); - let expected = vec![1, 3, 3, 1]; - assert_eq!(c, expected); - } } - } - - check_simple!(u8); - check_simple!(i8); - check_simple!(u16); - check_simple!(i16); - check_simple!(u32); - check_simple!(i32); - check_simple!(u64); - check_simple!(i64); - - macro_rules! check_binomial { - ($t:ty, $n:expr) => { { - let n: $t = $n; - let c: Vec<_> = IterBinomial::new(n).collect(); - let mut k: $t = 0; - for b in c { - assert_eq!(b, binomial(n, k)); - k += 1; - } - } } - } - - // Check the largest n for which there is no overflow. - check_binomial!(u8, 10); - check_binomial!(i8, 9); - check_binomial!(u16, 18); - check_binomial!(i16, 17); - check_binomial!(u32, 34); - check_binomial!(i32, 33); - check_binomial!(u64, 67); - check_binomial!(i64, 66); -} - -#[test] -fn test_binomial() { - macro_rules! check { - ($t:ty, $x:expr, $y:expr, $r:expr) => { { - let x: $t = $x; - let y: $t = $y; - let expected: $t = $r; - assert_eq!(binomial(x, y), expected); - if y <= x { - assert_eq!(binomial(x, x - y), expected); - } - } } - } - check!(u8, 9, 4, 126); - check!(u8, 0, 0, 1); - check!(u8, 2, 3, 0); - - check!(i8, 9, 4, 126); - check!(i8, 0, 0, 1); - check!(i8, 2, 3, 0); - - check!(u16, 100, 2, 4950); - check!(u16, 14, 4, 1001); - check!(u16, 0, 0, 1); - check!(u16, 2, 3, 0); - - check!(i16, 100, 2, 4950); - check!(i16, 14, 4, 1001); - check!(i16, 0, 0, 1); - check!(i16, 2, 3, 0); - - check!(u32, 100, 2, 4950); - check!(u32, 35, 11, 417225900); - check!(u32, 14, 4, 1001); - check!(u32, 0, 0, 1); - check!(u32, 2, 3, 0); - - check!(i32, 100, 2, 4950); - check!(i32, 35, 11, 417225900); - check!(i32, 14, 4, 1001); - check!(i32, 0, 0, 1); - check!(i32, 2, 3, 0); - - check!(u64, 100, 2, 4950); - check!(u64, 35, 11, 417225900); - check!(u64, 14, 4, 1001); - check!(u64, 0, 0, 1); - check!(u64, 2, 3, 0); - - check!(i64, 100, 2, 4950); - check!(i64, 35, 11, 417225900); - check!(i64, 14, 4, 1001); - check!(i64, 0, 0, 1); - check!(i64, 2, 3, 0); -} - -#[test] -fn test_multinomial() { - macro_rules! check_binomial { - ($t:ty, $k:expr) => { { - let n: $t = $k.iter().fold(0, |acc, &x| acc + x); - let k: &[$t] = $k; - assert_eq!(k.len(), 2); - assert_eq!(multinomial(k), binomial(n, k[0])); - } } - } - - check_binomial!(u8, &[4, 5]); - - check_binomial!(i8, &[4, 5]); - - check_binomial!(u16, &[2, 98]); - check_binomial!(u16, &[4, 10]); - - check_binomial!(i16, &[2, 98]); - check_binomial!(i16, &[4, 10]); - - check_binomial!(u32, &[2, 98]); - check_binomial!(u32, &[11, 24]); - check_binomial!(u32, &[4, 10]); - - check_binomial!(i32, &[2, 98]); - check_binomial!(i32, &[11, 24]); - check_binomial!(i32, &[4, 10]); - - check_binomial!(u64, &[2, 98]); - check_binomial!(u64, &[11, 24]); - check_binomial!(u64, &[4, 10]); - - check_binomial!(i64, &[2, 98]); - check_binomial!(i64, &[11, 24]); - check_binomial!(i64, &[4, 10]); - - macro_rules! check_multinomial { - ($t:ty, $k:expr, $r:expr) => { { - let k: &[$t] = $k; - let expected: $t = $r; - assert_eq!(multinomial(k), expected); - } } - } - - check_multinomial!(u8, &[2, 1, 2], 30); - check_multinomial!(u8, &[2, 3, 0], 10); - - check_multinomial!(i8, &[2, 1, 2], 30); - check_multinomial!(i8, &[2, 3, 0], 10); - - check_multinomial!(u16, &[2, 1, 2], 30); - check_multinomial!(u16, &[2, 3, 0], 10); - - check_multinomial!(i16, &[2, 1, 2], 30); - check_multinomial!(i16, &[2, 3, 0], 10); - - check_multinomial!(u32, &[2, 1, 2], 30); - check_multinomial!(u32, &[2, 3, 0], 10); - - check_multinomial!(i32, &[2, 1, 2], 30); - check_multinomial!(i32, &[2, 3, 0], 10); - - check_multinomial!(u64, &[2, 1, 2], 30); - check_multinomial!(u64, &[2, 3, 0], 10); - - check_multinomial!(i64, &[2, 1, 2], 30); - check_multinomial!(i64, &[2, 3, 0], 10); - - check_multinomial!(u64, &[], 1); - check_multinomial!(u64, &[0], 1); - check_multinomial!(u64, &[12345], 1); -} diff --git a/iter/Cargo.toml b/iter/Cargo.toml deleted file mode 100644 index 742148c..0000000 --- a/iter/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -description = "External iterators for generic mathematics" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics"] -categories = [ "algorithms", "science" ] -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num" -name = "num-iter" -version = "0.1.34" - -[dependencies] - -[dependencies.num-integer] -optional = false -path = "../integer" -version = "0.1.32" - -[dependencies.num-traits] -optional = false -path = "../traits" -version = "0.1.32" diff --git a/iter/LICENSE-APACHE b/iter/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/iter/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/iter/LICENSE-MIT b/iter/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/iter/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/iter/src/lib.rs b/iter/src/lib.rs deleted file mode 100644 index 68323ef..0000000 --- a/iter/src/lib.rs +++ /dev/null @@ -1,378 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! External iterators for generic mathematics -#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://rust-num.github.io/num/favicon.ico", - html_root_url = "https://rust-num.github.io/num/", - html_playground_url = "http://play.integer32.com/")] - -extern crate num_traits as traits; -extern crate num_integer as integer; - -use integer::Integer; -use traits::{Zero, One, CheckedAdd, ToPrimitive}; -use std::ops::{Add, Sub}; - -/// An iterator over the range [start, stop) -#[derive(Clone)] -pub struct Range { - state: A, - stop: A, - one: A -} - -/// Returns an iterator over the given range [start, stop) (that is, starting -/// at start (inclusive), and ending at stop (exclusive)). -/// -/// # Example -/// -/// ```rust -/// let array = [0, 1, 2, 3, 4]; -/// -/// for i in num_iter::range(0, 5) { -/// println!("{}", i); -/// assert_eq!(i, array[i]); -/// } -/// ``` -#[inline] -pub fn range(start: A, stop: A) -> Range - where A: Add + PartialOrd + Clone + One -{ - Range{state: start, stop: stop, one: One::one()} -} - -// FIXME: rust-lang/rust#10414: Unfortunate type bound -impl Iterator for Range - where A: Add + PartialOrd + Clone + ToPrimitive -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - if self.state < self.stop { - let result = self.state.clone(); - self.state = self.state.clone() + self.one.clone(); - Some(result) - } else { - None - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - // This first checks if the elements are representable as i64. If they aren't, try u64 (to - // handle cases like range(huge, huger)). We don't use usize/int because the difference of - // the i64/u64 might lie within their range. - let bound = match self.state.to_i64() { - Some(a) => { - let sz = self.stop.to_i64().map(|b| b.checked_sub(a)); - match sz { - Some(Some(bound)) => bound.to_usize(), - _ => None, - } - }, - None => match self.state.to_u64() { - Some(a) => { - let sz = self.stop.to_u64().map(|b| b.checked_sub(a)); - match sz { - Some(Some(bound)) => bound.to_usize(), - _ => None - } - }, - None => None - } - }; - - match bound { - Some(b) => (b, Some(b)), - // Standard fallback for unbounded/unrepresentable bounds - None => (0, None) - } - } -} - -/// `Integer` is required to ensure the range will be the same regardless of -/// the direction it is consumed. -impl DoubleEndedIterator for Range - where A: Integer + Clone + ToPrimitive -{ - #[inline] - fn next_back(&mut self) -> Option { - if self.stop > self.state { - self.stop = self.stop.clone() - self.one.clone(); - Some(self.stop.clone()) - } else { - None - } - } -} - -/// An iterator over the range [start, stop] -#[derive(Clone)] -pub struct RangeInclusive { - range: Range, - done: bool, -} - -/// Return an iterator over the range [start, stop] -#[inline] -pub fn range_inclusive(start: A, stop: A) -> RangeInclusive - where A: Add + PartialOrd + Clone + One -{ - RangeInclusive{range: range(start, stop), done: false} -} - -impl Iterator for RangeInclusive - where A: Add + PartialOrd + Clone + ToPrimitive -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - match self.range.next() { - Some(x) => Some(x), - None => { - if !self.done && self.range.state == self.range.stop { - self.done = true; - Some(self.range.stop.clone()) - } else { - None - } - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let (lo, hi) = self.range.size_hint(); - if self.done { - (lo, hi) - } else { - let lo = lo.saturating_add(1); - let hi = match hi { - Some(x) => x.checked_add(1), - None => None - }; - (lo, hi) - } - } -} - -impl DoubleEndedIterator for RangeInclusive - where A: Sub + Integer + Clone + ToPrimitive -{ - #[inline] - fn next_back(&mut self) -> Option { - if self.range.stop > self.range.state { - let result = self.range.stop.clone(); - self.range.stop = self.range.stop.clone() - self.range.one.clone(); - Some(result) - } else if !self.done && self.range.state == self.range.stop { - self.done = true; - Some(self.range.stop.clone()) - } else { - None - } - } -} - -/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[derive(Clone)] -pub struct RangeStep { - state: A, - stop: A, - step: A, - rev: bool, -} - -/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. -#[inline] -pub fn range_step(start: A, stop: A, step: A) -> RangeStep - where A: CheckedAdd + PartialOrd + Clone + Zero -{ - let rev = step < Zero::zero(); - RangeStep{state: start, stop: stop, step: step, rev: rev} -} - -impl Iterator for RangeStep - where A: CheckedAdd + PartialOrd + Clone -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) { - let result = self.state.clone(); - match self.state.checked_add(&self.step) { - Some(x) => self.state = x, - None => self.state = self.stop.clone() - } - Some(result) - } else { - None - } - } -} - -/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. -#[derive(Clone)] -pub struct RangeStepInclusive { - state: A, - stop: A, - step: A, - rev: bool, - done: bool, -} - -/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. -#[inline] -pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepInclusive - where A: CheckedAdd + PartialOrd + Clone + Zero -{ - let rev = step < Zero::zero(); - RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false} -} - -impl Iterator for RangeStepInclusive - where A: CheckedAdd + PartialOrd + Clone + PartialEq -{ - type Item = A; - - #[inline] - fn next(&mut self) -> Option { - if !self.done && ((self.rev && self.state >= self.stop) || - (!self.rev && self.state <= self.stop)) { - let result = self.state.clone(); - match self.state.checked_add(&self.step) { - Some(x) => self.state = x, - None => self.done = true - } - Some(result) - } else { - None - } - } -} - -#[cfg(test)] -mod tests { - use std::usize; - use std::ops::{Add, Mul}; - use std::cmp::Ordering; - use traits::{One, ToPrimitive}; - - #[test] - fn test_range() { - /// A mock type to check Range when ToPrimitive returns None - struct Foo; - - impl ToPrimitive for Foo { - fn to_i64(&self) -> Option { None } - fn to_u64(&self) -> Option { None } - } - - impl Add for Foo { - type Output = Foo; - - fn add(self, _: Foo) -> Foo { - Foo - } - } - - impl PartialEq for Foo { - fn eq(&self, _: &Foo) -> bool { - true - } - } - - impl PartialOrd for Foo { - fn partial_cmp(&self, _: &Foo) -> Option { - None - } - } - - impl Clone for Foo { - fn clone(&self) -> Foo { - Foo - } - } - - impl Mul for Foo { - type Output = Foo; - - fn mul(self, _: Foo) -> Foo { - Foo - } - } - - impl One for Foo { - fn one() -> Foo { - Foo - } - } - - assert!(super::range(0, 5).collect::>() == vec![0, 1, 2, 3, 4]); - assert!(super::range(-10, -1).collect::>() == - vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]); - assert!(super::range(0, 5).rev().collect::>() == vec![4, 3, 2, 1, 0]); - assert_eq!(super::range(200, -5).count(), 0); - assert_eq!(super::range(200, -5).rev().count(), 0); - assert_eq!(super::range(200, 200).count(), 0); - assert_eq!(super::range(200, 200).rev().count(), 0); - - assert_eq!(super::range(0, 100).size_hint(), (100, Some(100))); - // this test is only meaningful when sizeof usize < sizeof u64 - assert_eq!(super::range(usize::MAX - 1, usize::MAX).size_hint(), (1, Some(1))); - assert_eq!(super::range(-10, -1).size_hint(), (9, Some(9))); - } - - #[test] - fn test_range_inclusive() { - assert!(super::range_inclusive(0, 5).collect::>() == - vec![0, 1, 2, 3, 4, 5]); - assert!(super::range_inclusive(0, 5).rev().collect::>() == - vec![5, 4, 3, 2, 1, 0]); - assert_eq!(super::range_inclusive(200, -5).count(), 0); - assert_eq!(super::range_inclusive(200, -5).rev().count(), 0); - assert!(super::range_inclusive(200, 200).collect::>() == vec![200]); - assert!(super::range_inclusive(200, 200).rev().collect::>() == vec![200]); - } - - #[test] - fn test_range_step() { - assert!(super::range_step(0, 20, 5).collect::>() == - vec![0, 5, 10, 15]); - assert!(super::range_step(20, 0, -5).collect::>() == - vec![20, 15, 10, 5]); - assert!(super::range_step(20, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(super::range_step(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(super::range_step(200, -5, 1).collect::>() == vec![]); - assert!(super::range_step(200, 200, 1).collect::>() == vec![]); - } - - #[test] - fn test_range_step_inclusive() { - assert!(super::range_step_inclusive(0, 20, 5).collect::>() == - vec![0, 5, 10, 15, 20]); - assert!(super::range_step_inclusive(20, 0, -5).collect::>() == - vec![20, 15, 10, 5, 0]); - assert!(super::range_step_inclusive(20, 0, -6).collect::>() == - vec![20, 14, 8, 2]); - assert!(super::range_step_inclusive(200u8, 255, 50).collect::>() == - vec![200u8, 250]); - assert!(super::range_step_inclusive(200, -5, 1).collect::>() == - vec![]); - assert!(super::range_step_inclusive(200, 200, 1).collect::>() == - vec![200]); - } -} diff --git a/rational/Cargo.toml b/rational/Cargo.toml deleted file mode 100644 index 5a58f3b..0000000 --- a/rational/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -description = "Rational numbers implementation for Rust" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics"] -categories = [ "algorithms", "data-structures", "science" ] -license = "MIT/Apache-2.0" -name = "num-rational" -repository = "https://github.com/rust-num/num" -version = "0.1.40" - -[dependencies] - -[dependencies.num-bigint] -optional = true -path = "../bigint" -version = "0.1.32" - -[dependencies.num-integer] -path = "../integer" -version = "0.1.32" - -[dependencies.num-traits] -path = "../traits" -version = "0.1.32" - -[dependencies.rustc-serialize] -optional = true -version = "0.3.19" - -[dependencies.serde] -optional = true -version = ">= 0.7.0, < 0.9.0" - -[features] -default = ["bigint", "rustc-serialize"] -bigint = ["num-bigint"] diff --git a/rational/LICENSE-APACHE b/rational/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/rational/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/rational/LICENSE-MIT b/rational/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/rational/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/rational/src/lib.rs b/rational/src/lib.rs deleted file mode 100644 index ae00142..0000000 --- a/rational/src/lib.rs +++ /dev/null @@ -1,1413 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Rational numbers -#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://rust-num.github.io/num/favicon.ico", - html_root_url = "https://rust-num.github.io/num/", - html_playground_url = "http://play.integer32.com/")] - -#[cfg(feature = "rustc-serialize")] -extern crate rustc_serialize; -#[cfg(feature = "serde")] -extern crate serde; -#[cfg(feature = "num-bigint")] -extern crate num_bigint as bigint; - -extern crate num_traits as traits; -extern crate num_integer as integer; - -use std::cmp; -use std::error::Error; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::ops::{Add, Div, Mul, Neg, Rem, Sub}; -use std::str::FromStr; - -#[cfg(feature = "num-bigint")] -use bigint::{BigInt, BigUint, Sign}; - -use integer::Integer; -use traits::{FromPrimitive, Float, PrimInt, Num, Signed, Zero, One, Bounded, NumCast}; - -/// Represents the ratio between 2 numbers. -#[derive(Copy, Clone, Debug)] -#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))] -#[allow(missing_docs)] -pub struct Ratio { - numer: T, - denom: T, -} - -/// Alias for a `Ratio` of machine-sized integers. -pub type Rational = Ratio; -pub type Rational32 = Ratio; -pub type Rational64 = Ratio; - -#[cfg(feature = "num-bigint")] -/// Alias for arbitrary precision rationals. -pub type BigRational = Ratio; - -impl Ratio { - /// Creates a new `Ratio`. Fails if `denom` is zero. - #[inline] - pub fn new(numer: T, denom: T) -> Ratio { - if denom.is_zero() { - panic!("denominator == 0"); - } - let mut ret = Ratio::new_raw(numer, denom); - ret.reduce(); - ret - } - - /// Creates a `Ratio` representing the integer `t`. - #[inline] - pub fn from_integer(t: T) -> Ratio { - Ratio::new_raw(t, One::one()) - } - - /// Creates a `Ratio` without checking for `denom == 0` or reducing. - #[inline] - pub fn new_raw(numer: T, denom: T) -> Ratio { - Ratio { - numer: numer, - denom: denom, - } - } - - /// Converts to an integer, rounding towards zero. - #[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 - } - - /// Returns true if the rational number is an integer (denominator is 1). - #[inline] - pub fn is_integer(&self) -> bool { - self.denom == One::one() - } - - /// Puts self into lowest terms, with denom > 0. - fn reduce(&mut self) { - let g: T = self.numer.gcd(&self.denom); - - // FIXME(#5992): assignment operator overloads - // self.numer /= g; - self.numer = self.numer.clone() / g.clone(); - // FIXME(#5992): assignment operator overloads - // self.denom /= g; - self.denom = self.denom.clone() / g; - - // keep denom positive! - if self.denom < T::zero() { - self.numer = T::zero() - self.numer.clone(); - self.denom = T::zero() - self.denom.clone(); - } - } - - /// Returns a reduced copy of self. - /// - /// In general, it is not necessary to use this method, as the only - /// method of procuring a non-reduced fraction is through `new_raw`. - pub fn reduced(&self) -> Ratio { - let mut ret = self.clone(); - ret.reduce(); - ret - } - - /// Returns the reciprocal. - /// - /// Fails if the `Ratio` is zero. - #[inline] - pub fn recip(&self) -> Ratio { - match self.numer.cmp(&T::zero()) { - cmp::Ordering::Equal => panic!("numerator == 0"), - cmp::Ordering::Greater => Ratio::new_raw(self.denom.clone(), self.numer.clone()), - cmp::Ordering::Less => Ratio::new_raw(T::zero() - self.denom.clone(), - T::zero() - self.numer.clone()) - } - } - - /// Rounds towards minus infinity. - #[inline] - pub fn floor(&self) -> Ratio { - if *self < Zero::zero() { - let one: T = One::one(); - Ratio::from_integer((self.numer.clone() - self.denom.clone() + one) / - self.denom.clone()) - } else { - Ratio::from_integer(self.numer.clone() / self.denom.clone()) - } - } - - /// Rounds towards plus infinity. - #[inline] - pub fn ceil(&self) -> Ratio { - if *self < Zero::zero() { - Ratio::from_integer(self.numer.clone() / self.denom.clone()) - } else { - let one: T = One::one(); - Ratio::from_integer((self.numer.clone() + self.denom.clone() - one) / - self.denom.clone()) - } - } - - /// Rounds to the nearest integer. Rounds half-way cases away from zero. - #[inline] - pub fn round(&self) -> Ratio { - let zero: Ratio = Zero::zero(); - let one: T = One::one(); - let two: T = one.clone() + one.clone(); - - // Find unsigned fractional part of rational number - let mut fractional = self.fract(); - if fractional < zero { - fractional = zero - fractional - }; - - // The algorithm compares the unsigned fractional part with 1/2, that - // is, a/b >= 1/2, or a >= b/2. For odd denominators, we use - // a >= (b/2)+1. This avoids overflow issues. - let half_or_larger = if fractional.denom().is_even() { - *fractional.numer() >= fractional.denom().clone() / two.clone() - } else { - *fractional.numer() >= (fractional.denom().clone() / two.clone()) + one.clone() - }; - - if half_or_larger { - let one: Ratio = One::one(); - if *self >= Zero::zero() { - self.trunc() + one - } else { - self.trunc() - one - } - } else { - self.trunc() - } - } - - /// Rounds towards zero. - #[inline] - pub fn trunc(&self) -> Ratio { - Ratio::from_integer(self.numer.clone() / self.denom.clone()) - } - - /// Returns the fractional part of a number, with division rounded towards zero. - /// - /// Satisfies `self == self.trunc() + self.fract()`. - #[inline] - pub fn fract(&self) -> Ratio { - Ratio::new_raw(self.numer.clone() % self.denom.clone(), self.denom.clone()) - } -} - -impl Ratio { - /// Raises the `Ratio` to the power of an exponent. - #[inline] - pub fn pow(&self, expon: i32) -> Ratio { - match expon.cmp(&0) { - cmp::Ordering::Equal => One::one(), - cmp::Ordering::Less => self.recip().pow(-expon), - cmp::Ordering::Greater => { - Ratio::new_raw(self.numer.pow(expon as u32), self.denom.pow(expon as u32)) - } - } - } -} - -#[cfg(feature = "num-bigint")] -impl Ratio { - /// Converts a float into a rational number. - pub fn from_float(f: T) -> Option { - if !f.is_finite() { - return None; - } - let (mantissa, exponent, sign) = f.integer_decode(); - let bigint_sign = if sign == 1 { - Sign::Plus - } else { - Sign::Minus - }; - if exponent < 0 { - let one: BigInt = One::one(); - let denom: BigInt = one << ((-exponent) as usize); - 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 usize); - Some(Ratio::from_integer(BigInt::from_biguint(bigint_sign, numer))) - } - } -} - -// From integer -impl From for Ratio where T: Clone + Integer { - fn from(x: T) -> Ratio { - Ratio::from_integer(x) - } -} - - -// From pair (through the `new` constructor) -impl From<(T, T)> for Ratio where T: Clone + Integer { - fn from(pair: (T, T)) -> Ratio { - Ratio::new(pair.0, pair.1) - } -} - -// Comparisons - -// Mathematically, comparing a/b and c/d is the same as comparing a*d and b*c, but it's very easy -// for those multiplications to overflow fixed-size integers, so we need to take care. - -impl Ord for Ratio { - #[inline] - fn cmp(&self, other: &Self) -> cmp::Ordering { - // With equal denominators, the numerators can be directly compared - if self.denom == other.denom { - let ord = self.numer.cmp(&other.numer); - return if self.denom < T::zero() { - ord.reverse() - } else { - ord - }; - } - - // With equal numerators, the denominators can be inversely compared - if self.numer == other.numer { - let ord = self.denom.cmp(&other.denom); - return if self.numer < T::zero() { - ord - } else { - ord.reverse() - }; - } - - // Unfortunately, we don't have CheckedMul to try. That could sometimes avoid all the - // division below, or even always avoid it for BigInt and BigUint. - // FIXME- future breaking change to add Checked* to Integer? - - // Compare as floored integers and remainders - let (self_int, self_rem) = self.numer.div_mod_floor(&self.denom); - let (other_int, other_rem) = other.numer.div_mod_floor(&other.denom); - match self_int.cmp(&other_int) { - cmp::Ordering::Greater => cmp::Ordering::Greater, - cmp::Ordering::Less => cmp::Ordering::Less, - cmp::Ordering::Equal => { - match (self_rem.is_zero(), other_rem.is_zero()) { - (true, true) => cmp::Ordering::Equal, - (true, false) => cmp::Ordering::Less, - (false, true) => cmp::Ordering::Greater, - (false, false) => { - // Compare the reciprocals of the remaining fractions in reverse - let self_recip = Ratio::new_raw(self.denom.clone(), self_rem); - let other_recip = Ratio::new_raw(other.denom.clone(), other_rem); - self_recip.cmp(&other_recip).reverse() - } - } - } - } - } -} - -impl PartialOrd for Ratio { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for Ratio { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == cmp::Ordering::Equal - } -} - -impl Eq for Ratio {} - -// NB: We can't just `#[derive(Hash)]`, because it needs to agree -// with `Eq` even for non-reduced ratios. -impl Hash for Ratio { - fn hash(&self, state: &mut H) { - recurse(&self.numer, &self.denom, state); - - fn recurse(numer: &T, denom: &T, state: &mut H) { - if !denom.is_zero() { - let (int, rem) = numer.div_mod_floor(denom); - int.hash(state); - recurse(denom, &rem, state); - } else { - denom.hash(state); - } - } - } -} - - -macro_rules! forward_val_val_binop { - (impl $imp:ident, $method:ident) => { - impl $imp> for Ratio { - type Output = Ratio; - - #[inline] - fn $method(self, other: Ratio) -> Ratio { - (&self).$method(&other) - } - } - } -} - -macro_rules! forward_ref_val_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T> $imp> for &'a Ratio where - T: Clone + Integer - { - type Output = Ratio; - - #[inline] - fn $method(self, other: Ratio) -> Ratio { - self.$method(&other) - } - } - } -} - -macro_rules! forward_val_ref_binop { - (impl $imp:ident, $method:ident) => { - impl<'a, T> $imp<&'a Ratio> for Ratio where - T: Clone + Integer - { - type Output = Ratio; - - #[inline] - fn $method(self, other: &Ratio) -> Ratio { - (&self).$method(other) - } - } - } -} - -macro_rules! forward_all_binop { - (impl $imp:ident, $method:ident) => { - forward_val_val_binop!(impl $imp, $method); - forward_ref_val_binop!(impl $imp, $method); - forward_val_ref_binop!(impl $imp, $method); - }; -} - -// Arithmetic -forward_all_binop!(impl Mul, mul); -// a/b * c/d = (a*c)/(b*d) -impl<'a, 'b, T> Mul<&'b Ratio> for &'a Ratio - where T: Clone + Integer -{ - type Output = Ratio; - #[inline] - fn mul(self, rhs: &Ratio) -> Ratio { - Ratio::new(self.numer.clone() * rhs.numer.clone(), - self.denom.clone() * rhs.denom.clone()) - } -} - -forward_all_binop!(impl Div, div); -// (a/b) / (c/d) = (a*d)/(b*c) -impl<'a, 'b, T> Div<&'b Ratio> for &'a Ratio - where T: Clone + Integer -{ - type Output = Ratio; - - #[inline] - fn div(self, rhs: &Ratio) -> Ratio { - Ratio::new(self.numer.clone() * rhs.denom.clone(), - self.denom.clone() * rhs.numer.clone()) - } -} - -// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern -macro_rules! arith_impl { - (impl $imp:ident, $method:ident) => { - forward_all_binop!(impl $imp, $method); - impl<'a, 'b, T: Clone + Integer> - $imp<&'b Ratio> for &'a Ratio { - type Output = Ratio; - #[inline] - fn $method(self, rhs: &Ratio) -> Ratio { - Ratio::new((self.numer.clone() * rhs.denom.clone()).$method(self.denom.clone() * rhs.numer.clone()), - self.denom.clone() * rhs.denom.clone()) - } - } - } -} - -// 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 Neg for Ratio - where T: Clone + Integer + Neg -{ - type Output = Ratio; - - #[inline] - fn neg(self) -> Ratio { - Ratio::new_raw(-self.numer, self.denom) - } -} - -impl<'a, T> Neg for &'a Ratio - where T: Clone + Integer + Neg -{ - type Output = Ratio; - - #[inline] - fn neg(self) -> Ratio { - -self.clone() - } -} - -// Constants -impl Zero for Ratio { - #[inline] - fn zero() -> Ratio { - Ratio::new_raw(Zero::zero(), One::one()) - } - - #[inline] - fn is_zero(&self) -> bool { - self.numer.is_zero() - } -} - -impl One for Ratio { - #[inline] - fn one() -> Ratio { - Ratio::new_raw(One::one(), One::one()) - } -} - -impl Num for Ratio { - type FromStrRadixErr = ParseRatioError; - - /// Parses `numer/denom` where the numbers are in base `radix`. - fn from_str_radix(s: &str, radix: u32) -> Result, ParseRatioError> { - let split: Vec<&str> = s.splitn(2, '/').collect(); - if split.len() < 2 { - Err(ParseRatioError { kind: RatioErrorKind::ParseError }) - } else { - let a_result: Result = T::from_str_radix(split[0], radix).map_err(|_| { - ParseRatioError { kind: RatioErrorKind::ParseError } - }); - a_result.and_then(|a| { - let b_result: Result = T::from_str_radix(split[1], radix).map_err(|_| { - ParseRatioError { kind: RatioErrorKind::ParseError } - }); - b_result.and_then(|b| { - if b.is_zero() { - Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator }) - } else { - Ok(Ratio::new(a.clone(), b.clone())) - } - }) - }) - } - } -} - -impl Signed for Ratio { - #[inline] - fn abs(&self) -> Ratio { - if self.is_negative() { - -self.clone() - } else { - self.clone() - } - } - - #[inline] - fn abs_sub(&self, other: &Ratio) -> Ratio { - if *self <= *other { - Zero::zero() - } else { - self - other - } - } - - #[inline] - fn signum(&self) -> Ratio { - if self.is_positive() { - Self::one() - } else if self.is_zero() { - Self::zero() - } else { - -Self::one() - } - } - - #[inline] - fn is_positive(&self) -> bool { - (self.numer.is_positive() && self.denom.is_positive()) || - (self.numer.is_negative() && self.denom.is_negative()) - } - - #[inline] - fn is_negative(&self) -> bool { - (self.numer.is_negative() && self.denom.is_positive()) || - (self.numer.is_positive() && self.denom.is_negative()) - } -} - -// String conversions -impl fmt::Display for Ratio - where T: fmt::Display + Eq + One -{ - /// Renders as `numer/denom`. If denom=1, renders as numer. - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.denom == One::one() { - write!(f, "{}", self.numer) - } else { - write!(f, "{}/{}", self.numer, self.denom) - } - } -} - -impl FromStr for Ratio { - type Err = ParseRatioError; - - /// Parses `numer/denom` or just `numer`. - fn from_str(s: &str) -> Result, ParseRatioError> { - let mut split = s.splitn(2, '/'); - - let n = try!(split.next().ok_or(ParseRatioError { kind: RatioErrorKind::ParseError })); - let num = try!(FromStr::from_str(n) - .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError })); - - let d = split.next().unwrap_or("1"); - let den = try!(FromStr::from_str(d) - .map_err(|_| ParseRatioError { kind: RatioErrorKind::ParseError })); - - if Zero::is_zero(&den) { - Err(ParseRatioError { kind: RatioErrorKind::ZeroDenominator }) - } else { - Ok(Ratio::new(num, den)) - } - } -} - -impl Into<(T, T)> for Ratio { - fn into(self) -> (T, T) { - (self.numer, self.denom) - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for Ratio - where T: serde::Serialize + Clone + Integer + PartialOrd -{ - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: serde::Serializer - { - (self.numer(), self.denom()).serialize(serializer) - } -} - -#[cfg(feature = "serde")] -impl serde::Deserialize for Ratio - where T: serde::Deserialize + Clone + Integer + PartialOrd -{ - fn deserialize(deserializer: &mut D) -> Result - where D: serde::Deserializer - { - let (numer, denom): (T,T) = try!(serde::Deserialize::deserialize(deserializer)); - if denom.is_zero() { - Err(serde::de::Error::invalid_value("denominator is zero")) - } else { - Ok(Ratio::new_raw(numer, denom)) - } - } -} - -// FIXME: Bubble up specific errors -#[derive(Copy, Clone, Debug, PartialEq)] -pub struct ParseRatioError { - kind: RatioErrorKind, -} - -#[derive(Copy, Clone, Debug, PartialEq)] -enum RatioErrorKind { - ParseError, - ZeroDenominator, -} - -impl fmt::Display for ParseRatioError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -impl Error for ParseRatioError { - fn description(&self) -> &str { - self.kind.description() - } -} - -impl RatioErrorKind { - fn description(&self) -> &'static str { - match *self { - RatioErrorKind::ParseError => "failed to parse integer", - RatioErrorKind::ZeroDenominator => "zero value denominator", - } - } -} - -#[cfg(feature = "num-bigint")] -impl FromPrimitive for Ratio { - fn from_i64(n: i64) -> Option { - Some(Ratio::from_integer(n.into())) - } - - fn from_u64(n: u64) -> Option { - Some(Ratio::from_integer(n.into())) - } - - fn from_f32(n: f32) -> Option { - Ratio::from_float(n) - } - - fn from_f64(n: f64) -> Option { - Ratio::from_float(n) - } -} - -macro_rules! from_primitive_integer { - ($typ:ty, $approx:ident) => { - impl FromPrimitive for Ratio<$typ> { - fn from_i64(n: i64) -> Option { - <$typ as FromPrimitive>::from_i64(n).map(Ratio::from_integer) - } - - fn from_u64(n: u64) -> Option { - <$typ as FromPrimitive>::from_u64(n).map(Ratio::from_integer) - } - - fn from_f32(n: f32) -> Option { - $approx(n, 10e-20, 30) - } - - fn from_f64(n: f64) -> Option { - $approx(n, 10e-20, 30) - } - } - } -} - -from_primitive_integer!(i8, approximate_float); -from_primitive_integer!(i16, approximate_float); -from_primitive_integer!(i32, approximate_float); -from_primitive_integer!(i64, approximate_float); -from_primitive_integer!(isize, approximate_float); - -from_primitive_integer!(u8, approximate_float_unsigned); -from_primitive_integer!(u16, approximate_float_unsigned); -from_primitive_integer!(u32, approximate_float_unsigned); -from_primitive_integer!(u64, approximate_float_unsigned); -from_primitive_integer!(usize, approximate_float_unsigned); - -impl Ratio { - pub fn approximate_float(f: F) -> Option> { - // 1/10e-20 < 1/2**32 which seems like a good default, and 30 seems - // to work well. Might want to choose something based on the types in the future, e.g. - // T::max().recip() and T::bits() or something similar. - let epsilon = ::from(10e-20).expect("Can't convert 10e-20"); - approximate_float(f, epsilon, 30) - } -} - -fn approximate_float(val: F, max_error: F, max_iterations: usize) -> Option> - where T: Integer + Signed + Bounded + NumCast + Clone, - F: Float + NumCast -{ - let negative = val.is_sign_negative(); - let abs_val = val.abs(); - - let r = approximate_float_unsigned(abs_val, max_error, max_iterations); - - // Make negative again if needed - if negative { - r.map(|r| r.neg()) - } else { - r - } -} - -// No Unsigned constraint because this also works on positive integers and is called -// like that, see above -fn approximate_float_unsigned(val: F, max_error: F, max_iterations: usize) -> Option> - where T: Integer + Bounded + NumCast + Clone, - F: Float + NumCast -{ - // Continued fractions algorithm - // http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac - - if val < F::zero() || val.is_nan() { - return None; - } - - let mut q = val; - let mut n0 = T::zero(); - let mut d0 = T::one(); - let mut n1 = T::one(); - let mut d1 = T::zero(); - - let t_max = T::max_value(); - let t_max_f = match ::from(t_max.clone()) { - None => return None, - Some(t_max_f) => t_max_f, - }; - - // 1/epsilon > T::MAX - let epsilon = t_max_f.recip(); - - // Overflow - if q > t_max_f { - return None; - } - - for _ in 0..max_iterations { - let a = match ::from(q) { - None => break, - Some(a) => a, - }; - - let a_f = match ::from(a.clone()) { - None => break, - Some(a_f) => a_f, - }; - let f = q - a_f; - - // Prevent overflow - if !a.is_zero() && - (n1 > t_max.clone() / a.clone() || - d1 > t_max.clone() / a.clone() || - a.clone() * n1.clone() > t_max.clone() - n0.clone() || - a.clone() * d1.clone() > t_max.clone() - d0.clone()) { - break; - } - - let n = a.clone() * n1.clone() + n0.clone(); - let d = a.clone() * d1.clone() + d0.clone(); - - n0 = n1; - d0 = d1; - n1 = n.clone(); - d1 = d.clone(); - - // Simplify fraction. Doing so here instead of at the end - // allows us to get closer to the target value without overflows - let g = Integer::gcd(&n1, &d1); - if !g.is_zero() { - n1 = n1 / g.clone(); - d1 = d1 / g.clone(); - } - - // Close enough? - let (n_f, d_f) = match (::from(n), ::from(d)) { - (Some(n_f), Some(d_f)) => (n_f, d_f), - _ => break, - }; - if (n_f / d_f - val).abs() < max_error { - break; - } - - // Prevent division by ~0 - if f < epsilon { - break; - } - q = f.recip(); - } - - // Overflow - if d1.is_zero() { - return None; - } - - Some(Ratio::new(n1, d1)) -} - -#[cfg(test)] -fn hash(x: &T) -> u64 { - use std::hash::BuildHasher; - use std::collections::hash_map::RandomState; - let mut hasher = ::Hasher::new(); - x.hash(&mut hasher); - hasher.finish() -} - -#[cfg(test)] -mod test { - use super::{Ratio, Rational}; - #[cfg(feature = "num-bigint")] - use super::BigRational; - - use std::str::FromStr; - use std::i32; - use std::f64; - use traits::{Zero, One, Signed, FromPrimitive}; - - pub const _0: Rational = Ratio { - numer: 0, - denom: 1, - }; - pub const _1: Rational = Ratio { - numer: 1, - denom: 1, - }; - pub const _2: Rational = Ratio { - numer: 2, - denom: 1, - }; - pub const _NEG2: Rational = Ratio { - numer: -2, - denom: 1, - }; - pub const _1_2: Rational = Ratio { - numer: 1, - denom: 2, - }; - pub const _3_2: Rational = Ratio { - numer: 3, - denom: 2, - }; - pub const _NEG1_2: Rational = Ratio { - numer: -1, - denom: 2, - }; - pub const _1_NEG2: Rational = Ratio { - numer: 1, - denom: -2, - }; - pub const _NEG1_NEG2: Rational = Ratio { - numer: -1, - denom: -2, - }; - pub const _1_3: Rational = Ratio { - numer: 1, - denom: 3, - }; - pub const _NEG1_3: Rational = Ratio { - numer: -1, - denom: 3, - }; - pub const _2_3: Rational = Ratio { - numer: 2, - denom: 3, - }; - pub const _NEG2_3: Rational = Ratio { - numer: -2, - denom: 3, - }; - - #[cfg(feature = "num-bigint")] - pub fn to_big(n: Rational) -> BigRational { - Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(), - FromPrimitive::from_isize(n.denom).unwrap()) - } - #[cfg(not(feature = "num-bigint"))] - pub fn to_big(n: Rational) -> Rational { - Ratio::new(FromPrimitive::from_isize(n.numer).unwrap(), - FromPrimitive::from_isize(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)); - assert_eq!(_2, From::from(2)); - } - - #[test] - fn test_new_reduce() { - let one22 = Ratio::new(2, 2); - - assert_eq!(one22, One::one()); - } - #[test] - #[should_panic] - fn test_new_zero() { - let _a = Ratio::new(1, 0); - } - - #[test] - fn test_approximate_float() { - assert_eq!(Ratio::from_f32(0.5f32), Some(Ratio::new(1i64, 2))); - assert_eq!(Ratio::from_f64(0.5f64), Some(Ratio::new(1i32, 2))); - assert_eq!(Ratio::from_f32(5f32), Some(Ratio::new(5i64, 1))); - assert_eq!(Ratio::from_f64(5f64), Some(Ratio::new(5i32, 1))); - assert_eq!(Ratio::from_f32(29.97f32), Some(Ratio::new(2997i64, 100))); - assert_eq!(Ratio::from_f32(-29.97f32), Some(Ratio::new(-2997i64, 100))); - - assert_eq!(Ratio::::from_f32(63.5f32), Some(Ratio::new(127i8, 2))); - assert_eq!(Ratio::::from_f32(126.5f32), Some(Ratio::new(126i8, 1))); - assert_eq!(Ratio::::from_f32(127.0f32), Some(Ratio::new(127i8, 1))); - assert_eq!(Ratio::::from_f32(127.5f32), None); - assert_eq!(Ratio::::from_f32(-63.5f32), Some(Ratio::new(-127i8, 2))); - assert_eq!(Ratio::::from_f32(-126.5f32), Some(Ratio::new(-126i8, 1))); - assert_eq!(Ratio::::from_f32(-127.0f32), Some(Ratio::new(-127i8, 1))); - assert_eq!(Ratio::::from_f32(-127.5f32), None); - - assert_eq!(Ratio::::from_f32(-127f32), None); - assert_eq!(Ratio::::from_f32(127f32), Some(Ratio::new(127u8, 1))); - assert_eq!(Ratio::::from_f32(127.5f32), Some(Ratio::new(255u8, 2))); - assert_eq!(Ratio::::from_f32(256f32), None); - - assert_eq!(Ratio::::from_f64(-10e200), None); - assert_eq!(Ratio::::from_f64(10e200), None); - assert_eq!(Ratio::::from_f64(f64::INFINITY), None); - assert_eq!(Ratio::::from_f64(f64::NEG_INFINITY), None); - assert_eq!(Ratio::::from_f64(f64::NAN), None); - assert_eq!(Ratio::::from_f64(f64::EPSILON), Some(Ratio::new(1, 4503599627370496))); - assert_eq!(Ratio::::from_f64(0.0), Some(Ratio::new(0, 1))); - assert_eq!(Ratio::::from_f64(-0.0), Some(Ratio::new(0, 1))); - } - - #[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_cmp_overflow() { - use std::cmp::Ordering; - - // issue #7 example: - let big = Ratio::new(128u8, 1); - let small = big.recip(); - assert!(big > small); - - // try a few that are closer together - // (some matching numer, some matching denom, some neither) - let ratios = vec![ - Ratio::new(125_i8, 127_i8), - Ratio::new(63_i8, 64_i8), - Ratio::new(124_i8, 125_i8), - Ratio::new(125_i8, 126_i8), - Ratio::new(126_i8, 127_i8), - Ratio::new(127_i8, 126_i8), - ]; - - fn check_cmp(a: Ratio, b: Ratio, ord: Ordering) { - println!("comparing {} and {}", a, b); - assert_eq!(a.cmp(&b), ord); - assert_eq!(b.cmp(&a), ord.reverse()); - } - - for (i, &a) in ratios.iter().enumerate() { - check_cmp(a, a, Ordering::Equal); - check_cmp(-a, a, Ordering::Less); - for &b in &ratios[i + 1..] { - check_cmp(a, b, Ordering::Less); - check_cmp(-a, -b, Ordering::Greater); - check_cmp(a.recip(), b.recip(), Ordering::Greater); - check_cmp(-a.recip(), -b.recip(), Ordering::Less); - } - } - } - - #[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()); - } - - #[test] - fn test_show() { - assert_eq!(format!("{}", _2), "2".to_string()); - assert_eq!(format!("{}", _1_2), "1/2".to_string()); - assert_eq!(format!("{}", _0), "0".to_string()); - assert_eq!(format!("{}", Ratio::from_integer(-2)), "-2".to_string()); - } - - mod arith { - use super::{_0, _1, _2, _1_2, _3_2, _NEG1_2, to_big}; - use super::super::{Ratio, Rational}; - - #[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_panic] - fn test_div_0() { - let _a = _1 / _0; - } - } - - #[test] - fn test_round() { - assert_eq!(_1_3.ceil(), _1); - assert_eq!(_1_3.floor(), _0); - assert_eq!(_1_3.round(), _0); - assert_eq!(_1_3.trunc(), _0); - - assert_eq!(_NEG1_3.ceil(), _0); - assert_eq!(_NEG1_3.floor(), -_1); - assert_eq!(_NEG1_3.round(), _0); - assert_eq!(_NEG1_3.trunc(), _0); - - assert_eq!(_2_3.ceil(), _1); - assert_eq!(_2_3.floor(), _0); - assert_eq!(_2_3.round(), _1); - assert_eq!(_2_3.trunc(), _0); - - assert_eq!(_NEG2_3.ceil(), _0); - assert_eq!(_NEG2_3.floor(), -_1); - assert_eq!(_NEG2_3.round(), -_1); - assert_eq!(_NEG2_3.trunc(), _0); - - 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); - - // Overflow checks - - let _neg1 = Ratio::from_integer(-1); - let _large_rat1 = Ratio::new(i32::MAX, i32::MAX - 1); - let _large_rat2 = Ratio::new(i32::MAX - 1, i32::MAX); - let _large_rat3 = Ratio::new(i32::MIN + 2, i32::MIN + 1); - let _large_rat4 = Ratio::new(i32::MIN + 1, i32::MIN + 2); - let _large_rat5 = Ratio::new(i32::MIN + 2, i32::MAX); - let _large_rat6 = Ratio::new(i32::MAX, i32::MIN + 2); - let _large_rat7 = Ratio::new(1, i32::MIN + 1); - let _large_rat8 = Ratio::new(1, i32::MAX); - - assert_eq!(_large_rat1.round(), One::one()); - assert_eq!(_large_rat2.round(), One::one()); - assert_eq!(_large_rat3.round(), One::one()); - assert_eq!(_large_rat4.round(), One::one()); - assert_eq!(_large_rat5.round(), _neg1); - assert_eq!(_large_rat6.round(), _neg1); - assert_eq!(_large_rat7.round(), Zero::zero()); - assert_eq!(_large_rat8.round(), Zero::zero()); - } - - #[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); - - assert_eq!(_3_2.recip(), _2_3); - assert_eq!(_NEG1_2.recip(), _NEG2); - assert_eq!(_NEG1_2.recip().denom(), &1); - } - - #[test] - #[should_panic(expected = "== 0")] - fn test_recip_fail() { - let _a = Ratio::new(0, 1).recip(); - } - - #[test] - fn test_pow() { - assert_eq!(_1_2.pow(2), Ratio::new(1, 4)); - assert_eq!(_1_2.pow(-2), Ratio::new(4, 1)); - assert_eq!(_1.pow(1), _1); - assert_eq!(_NEG1_2.pow(2), _1_2.pow(2)); - assert_eq!(_NEG1_2.pow(3), -_1_2.pow(3)); - assert_eq!(_3_2.pow(0), _1); - assert_eq!(_3_2.pow(-1), _3_2.recip()); - assert_eq!(_3_2.pow(3), Ratio::new(27, 8)); - } - - #[test] - fn test_to_from_str() { - fn test(r: Rational, s: String) { - assert_eq!(FromStr::from_str(&s), Ok(r)); - assert_eq!(r.to_string(), s); - } - test(_1, "1".to_string()); - test(_0, "0".to_string()); - test(_1_2, "1/2".to_string()); - test(_3_2, "3/2".to_string()); - test(_2, "2".to_string()); - test(_NEG1_2, "-1/2".to_string()); - } - #[test] - fn test_from_str_fail() { - fn test(s: &str) { - let rational: Result = FromStr::from_str(s); - assert!(rational.is_err()); - } - - let xs = ["0 /1", "abc", "", "1/", "--1/2", "3/2/1", "1/0"]; - for &s in xs.iter() { - test(s); - } - } - - #[cfg(feature = "num-bigint")] - #[test] - fn test_from_float() { - use traits::Float; - fn test(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.5918555f64, ("-4713381968463931", "549755813888")); - test(1.0 / 2f64.powf(100.), - ("1", "1267650600228229401496703205376")); - } - - #[cfg(feature = "num-bigint")] - #[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); - } - - #[test] - fn test_signed() { - assert_eq!(_NEG1_2.abs(), _1_2); - assert_eq!(_3_2.abs_sub(&_1_2), _1); - assert_eq!(_1_2.abs_sub(&_3_2), Zero::zero()); - assert_eq!(_1_2.signum(), One::one()); - assert_eq!(_NEG1_2.signum(), ->::one()); - assert_eq!(_0.signum(), Zero::zero()); - assert!(_NEG1_2.is_negative()); - assert!(_1_NEG2.is_negative()); - assert!(!_NEG1_2.is_positive()); - assert!(!_1_NEG2.is_positive()); - assert!(_1_2.is_positive()); - assert!(_NEG1_NEG2.is_positive()); - assert!(!_1_2.is_negative()); - assert!(!_NEG1_NEG2.is_negative()); - assert!(!_0.is_positive()); - assert!(!_0.is_negative()); - } - - #[test] - fn test_hash() { - assert!(::hash(&_0) != ::hash(&_1)); - assert!(::hash(&_0) != ::hash(&_3_2)); - - // a == b -> hash(a) == hash(b) - let a = Rational::new_raw(4, 2); - let b = Rational::new_raw(6, 3); - assert_eq!(a, b); - assert_eq!(::hash(&a), ::hash(&b)); - - let a = Rational::new_raw(123456789, 1000); - let b = Rational::new_raw(123456789 * 5, 5000); - assert_eq!(a, b); - assert_eq!(::hash(&a), ::hash(&b)); - } - - #[test] - fn test_into_pair() { - assert_eq! ((0, 1), _0.into()); - assert_eq! ((-2, 1), _NEG2.into()); - assert_eq! ((1, -2), _1_NEG2.into()); - } - - #[test] - fn test_from_pair() { - assert_eq! (_0, Ratio::from ((0, 1))); - assert_eq! (_1, Ratio::from ((1, 1))); - assert_eq! (_NEG2, Ratio::from ((-2, 1))); - assert_eq! (_1_NEG2, Ratio::from ((1, -2))); - } -} diff --git a/traits/src/bounds.rs b/src/bounds.rs similarity index 100% rename from traits/src/bounds.rs rename to src/bounds.rs diff --git a/traits/src/cast.rs b/src/cast.rs similarity index 100% rename from traits/src/cast.rs rename to src/cast.rs diff --git a/traits/src/float.rs b/src/float.rs similarity index 100% rename from traits/src/float.rs rename to src/float.rs diff --git a/traits/src/identities.rs b/src/identities.rs similarity index 100% rename from traits/src/identities.rs rename to src/identities.rs diff --git a/traits/src/int.rs b/src/int.rs similarity index 100% rename from traits/src/int.rs rename to src/int.rs diff --git a/src/lib.rs b/src/lib.rs index 8eefb08..253f236 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,104 +8,428 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A collection of numeric types and traits for Rust. -//! -//! This includes new types for big integers, rationals, and complex numbers, -//! new traits for generic programming on numeric properties like `Integer`, -//! and generic range iterators. -//! -//! ## Example -//! -//! This example uses the BigRational type and [Newton's method][newt] to -//! approximate a square root to arbitrary precision: -//! -//! ``` -//! extern crate num; -//! # #[cfg(all(feature = "bigint", feature="rational"))] -//! # mod test { -//! -//! use num::FromPrimitive; -//! use num::bigint::BigInt; -//! use num::rational::{Ratio, BigRational}; -//! -//! # pub -//! fn approx_sqrt(number: u64, iterations: usize) -> BigRational { -//! let start: Ratio = Ratio::from_integer(FromPrimitive::from_u64(number).unwrap()); -//! let mut approx = start.clone(); -//! -//! for _ in 0..iterations { -//! approx = (&approx + (&start / &approx)) / -//! Ratio::from_integer(FromPrimitive::from_u64(2).unwrap()); -//! } -//! -//! approx -//! } -//! # } -//! # #[cfg(not(all(feature = "bigint", feature="rational")))] -//! # mod test { pub fn approx_sqrt(n: u64, _: usize) -> u64 { n } } -//! # use test::approx_sqrt; -//! -//! fn main() { -//! println!("{}", approx_sqrt(10, 4)); // prints 4057691201/1283082416 -//! } -//! -//! ``` -//! -//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method -#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://rust-num.github.io/num/favicon.ico", - html_root_url = "https://rust-num.github.io/num/", - html_playground_url = "http://play.integer32.com/")] +//! Numeric traits for generic mathematics -extern crate num_traits; -extern crate num_integer; -extern crate num_iter; -#[cfg(feature = "num-complex")] -extern crate num_complex; -#[cfg(feature = "num-bigint")] -extern crate num_bigint; -#[cfg(feature = "num-rational")] -extern crate num_rational; +#![doc(html_root_url = "https://docs.rs/num-traits/0.1")] -#[cfg(feature = "num-bigint")] -pub use num_bigint::{BigInt, BigUint}; -#[cfg(feature = "num-rational")] -pub use num_rational::Rational; -#[cfg(all(feature = "num-rational", feature="num-bigint"))] -pub use num_rational::BigRational; -#[cfg(feature = "num-complex")] -pub use num_complex::Complex; -pub use num_integer::Integer; -pub use num_iter::{range, range_inclusive, range_step, range_step_inclusive}; -pub use num_traits::{Num, Zero, One, Signed, Unsigned, Bounded, - one, zero, abs, abs_sub, signum, - Saturating, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, - PrimInt, Float, ToPrimitive, FromPrimitive, NumCast, cast, - pow, checked_pow, clamp}; +use std::ops::{Add, Sub, Mul, Div, Rem}; +use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use std::num::Wrapping; -#[cfg(feature = "num-bigint")] -pub mod bigint { - pub use num_bigint::*; +pub use bounds::Bounded; +pub use float::{Float, FloatConst}; +pub use identities::{Zero, One, zero, one}; +pub use ops::checked::*; +pub use ops::wrapping::*; +pub use ops::saturating::Saturating; +pub use sign::{Signed, Unsigned, abs, abs_sub, signum}; +pub use cast::*; +pub use int::PrimInt; +pub use pow::{pow, checked_pow}; + +pub mod identities; +pub mod sign; +pub mod ops; +pub mod bounds; +pub mod float; +pub mod cast; +pub mod int; +pub mod pow; + +/// The base trait for numeric types, covering `0` and `1` values, +/// comparisons, basic numeric operations, and string conversion. +pub trait Num: PartialEq + Zero + One + NumOps +{ + type FromStrRadixErr; + + /// Convert from a string and radix <= 36. + /// + /// # Examples + /// + /// ```rust + /// use num_traits::Num; + /// + /// let result = ::from_str_radix("27", 10); + /// assert_eq!(result, Ok(27)); + /// + /// let result = ::from_str_radix("foo", 10); + /// assert!(result.is_err()); + /// ``` + fn from_str_radix(str: &str, radix: u32) -> Result; } -#[cfg(feature = "num-complex")] -pub mod complex { - pub use num_complex::*; +/// The trait for types implementing basic numeric operations +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumOps + : Add + + Sub + + Mul + + Div + + Rem +{} + +impl NumOps for T +where T: Add + + Sub + + Mul + + Div + + Rem +{} + +/// The trait for `Num` types which also implement numeric operations taking +/// the second operand by reference. +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumRef: Num + for<'r> NumOps<&'r Self> {} +impl NumRef for T where T: Num + for<'r> NumOps<&'r T> {} + +/// The trait for references which implement numeric operations, taking the +/// second operand either by value or by reference. +/// +/// This is automatically implemented for types which implement the operators. +pub trait RefNum: NumOps + for<'r> NumOps<&'r Base, Base> {} +impl RefNum for T where T: NumOps + for<'r> NumOps<&'r Base, Base> {} + +/// The trait for types implementing numeric assignment operators (like `+=`). +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumAssignOps + : AddAssign + + SubAssign + + MulAssign + + DivAssign + + RemAssign +{} + +impl NumAssignOps for T +where T: AddAssign + + SubAssign + + MulAssign + + DivAssign + + RemAssign +{} + +/// The trait for `Num` types which also implement assignment operators. +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumAssign: Num + NumAssignOps {} +impl NumAssign for T where T: Num + NumAssignOps {} + +/// The trait for `NumAssign` types which also implement assignment operations +/// taking the second operand by reference. +/// +/// This is automatically implemented for types which implement the operators. +pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {} +impl NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {} + + +macro_rules! int_trait_impl { + ($name:ident for $($t:ty)*) => ($( + impl $name for $t { + type FromStrRadixErr = ::std::num::ParseIntError; + #[inline] + fn from_str_radix(s: &str, radix: u32) + -> Result + { + <$t>::from_str_radix(s, radix) + } + } + )*) +} +int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64); + +impl Num for Wrapping + where Wrapping: + Add> + Sub> + + Mul> + Div> + Rem> +{ + type FromStrRadixErr = T::FromStrRadixErr; + fn from_str_radix(str: &str, radix: u32) -> Result { + T::from_str_radix(str, radix).map(Wrapping) + } } -pub mod integer { - pub use num_integer::*; + +#[derive(Debug)] +pub enum FloatErrorKind { + Empty, + Invalid, +} +// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us, +// so there's not really any way for us to reuse it. +#[derive(Debug)] +pub struct ParseFloatError { + pub kind: FloatErrorKind, } -pub mod iter { - pub use num_iter::*; +// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck +// with this implementation ourselves until we want to make a breaking change. +// (would have to drop it from `Num` though) +macro_rules! float_trait_impl { + ($name:ident for $($t:ty)*) => ($( + impl $name for $t { + type FromStrRadixErr = ParseFloatError; + + fn from_str_radix(src: &str, radix: u32) + -> Result + { + use self::FloatErrorKind::*; + use self::ParseFloatError as PFE; + + // Special values + match src { + "inf" => return Ok(Float::infinity()), + "-inf" => return Ok(Float::neg_infinity()), + "NaN" => return Ok(Float::nan()), + _ => {}, + } + + fn slice_shift_char(src: &str) -> Option<(char, &str)> { + src.chars().nth(0).map(|ch| (ch, &src[1..])) + } + + let (is_positive, src) = match slice_shift_char(src) { + None => return Err(PFE { kind: Empty }), + Some(('-', "")) => return Err(PFE { kind: Empty }), + Some(('-', src)) => (false, src), + Some((_, _)) => (true, src), + }; + + // The significand to accumulate + let mut sig = if is_positive { 0.0 } else { -0.0 }; + // Necessary to detect overflow + let mut prev_sig = sig; + let mut cs = src.chars().enumerate(); + // Exponent prefix and exponent index offset + let mut exp_info = None::<(char, usize)>; + + // Parse the integer part of the significand + for (i, c) in cs.by_ref() { + match c.to_digit(radix) { + Some(digit) => { + // shift significand one digit left + sig = sig * (radix as $t); + + // add/subtract current digit depending on sign + if is_positive { + sig = sig + ((digit as isize) as $t); + } else { + sig = sig - ((digit as isize) as $t); + } + + // Detect overflow by comparing to last value, except + // if we've not seen any non-zero digits. + if prev_sig != 0.0 { + if is_positive && sig <= prev_sig + { return Ok(Float::infinity()); } + if !is_positive && sig >= prev_sig + { return Ok(Float::neg_infinity()); } + + // Detect overflow by reversing the shift-and-add process + if is_positive && (prev_sig != (sig - digit as $t) / radix as $t) + { return Ok(Float::infinity()); } + if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t) + { return Ok(Float::neg_infinity()); } + } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + '.' => { + break; // start of fractional part + }, + _ => { + return Err(PFE { kind: Invalid }); + }, + }, + } + } + + // If we are not yet at the exponent parse the fractional + // part of the significand + if exp_info.is_none() { + let mut power = 1.0; + for (i, c) in cs.by_ref() { + match c.to_digit(radix) { + Some(digit) => { + // Decrease power one order of magnitude + power = power / (radix as $t); + // add/subtract current digit depending on sign + sig = if is_positive { + sig + (digit as $t) * power + } else { + sig - (digit as $t) * power + }; + // Detect overflow by comparing to last value + if is_positive && sig < prev_sig + { return Ok(Float::infinity()); } + if !is_positive && sig > prev_sig + { return Ok(Float::neg_infinity()); } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + _ => { + return Err(PFE { kind: Invalid }); + }, + }, + } + } + } + + // Parse and calculate the exponent + let exp = match exp_info { + Some((c, offset)) => { + let base = match c { + 'E' | 'e' if radix == 10 => 10.0, + 'P' | 'p' if radix == 16 => 2.0, + _ => return Err(PFE { kind: Invalid }), + }; + + // Parse the exponent as decimal integer + let src = &src[offset..]; + let (is_positive, exp) = match slice_shift_char(src) { + Some(('-', src)) => (false, src.parse::()), + Some(('+', src)) => (true, src.parse::()), + Some((_, _)) => (true, src.parse::()), + None => return Err(PFE { kind: Invalid }), + }; + + match (is_positive, exp) { + (true, Ok(exp)) => base.powi(exp as i32), + (false, Ok(exp)) => 1.0 / base.powi(exp as i32), + (_, Err(_)) => return Err(PFE { kind: Invalid }), + } + }, + None => 1.0, // no exponent + }; + + Ok(sig * exp) + } + } + )*) +} +float_trait_impl!(Num for f32 f64); + +/// A value bounded by a minimum and a maximum +/// +/// If input is less than min then this returns min. +/// If input is greater than max then this returns max. +/// Otherwise this returns input. +#[inline] +pub fn clamp(input: T, min: T, max: T) -> T { + debug_assert!(min <= max, "min must be less than or equal to max"); + if input < min { + min + } else if input > max { + max + } else { + input + } } -pub mod traits { - pub use num_traits::*; +#[test] +fn clamp_test() { + // Int test + assert_eq!(1, clamp(1, -1, 2)); + assert_eq!(-1, clamp(-2, -1, 2)); + assert_eq!(2, clamp(3, -1, 2)); + + // Float test + assert_eq!(1.0, clamp(1.0, -1.0, 2.0)); + assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0)); + assert_eq!(2.0, clamp(3.0, -1.0, 2.0)); } -#[cfg(feature = "num-rational")] -pub mod rational { - pub use num_rational::*; +#[test] +fn from_str_radix_unwrap() { + // The Result error must impl Debug to allow unwrap() + + let i: i32 = Num::from_str_radix("0", 10).unwrap(); + assert_eq!(i, 0); + + let f: f32 = Num::from_str_radix("0.0", 10).unwrap(); + assert_eq!(f, 0.0); } + +#[test] +fn wrapping_is_num() { + fn require_num(_: &T) {} + require_num(&Wrapping(42_u32)); + require_num(&Wrapping(-42)); +} + +#[test] +fn wrapping_from_str_radix() { + macro_rules! test_wrapping_from_str_radix { + ($($t:ty)+) => { + $( + for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] { + let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0); + assert_eq!(w, <$t as Num>::from_str_radix(s, r)); + } + )+ + }; + } + + test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} + +#[test] +fn check_num_ops() { + fn compute(x: T, y: T) -> T { + x * y / y % y + y - y + } + assert_eq!(compute(1, 2), 1) +} + +#[test] +fn check_numref_ops() { + fn compute(x: T, y: &T) -> T { + x * y / y % y + y - y + } + assert_eq!(compute(1, &2), 1) +} + +#[test] +fn check_refnum_ops() { + fn compute(x: &T, y: T) -> T + where for<'a> &'a T: RefNum + { + &(&(&(&(x * y) / y) % y) + y) - y + } + assert_eq!(compute(&1, 2), 1) +} + +#[test] +fn check_refref_ops() { + fn compute(x: &T, y: &T) -> T + where for<'a> &'a T: RefNum + { + &(&(&(&(x * y) / y) % y) + y) - y + } + assert_eq!(compute(&1, &2), 1) +} + +#[test] +fn check_numassign_ops() { + fn compute(mut x: T, y: T) -> T { + x *= y; + x /= y; + x %= y; + x += y; + x -= y; + x + } + assert_eq!(compute(1, 2), 1) +} + +// TODO test `NumAssignRef`, but even the standard numeric types don't +// implement this yet. (see rust pr41336) diff --git a/traits/src/ops/checked.rs b/src/ops/checked.rs similarity index 100% rename from traits/src/ops/checked.rs rename to src/ops/checked.rs diff --git a/traits/src/ops/mod.rs b/src/ops/mod.rs similarity index 100% rename from traits/src/ops/mod.rs rename to src/ops/mod.rs diff --git a/traits/src/ops/saturating.rs b/src/ops/saturating.rs similarity index 100% rename from traits/src/ops/saturating.rs rename to src/ops/saturating.rs diff --git a/traits/src/ops/wrapping.rs b/src/ops/wrapping.rs similarity index 100% rename from traits/src/ops/wrapping.rs rename to src/ops/wrapping.rs diff --git a/traits/src/pow.rs b/src/pow.rs similarity index 100% rename from traits/src/pow.rs rename to src/pow.rs diff --git a/traits/src/sign.rs b/src/sign.rs similarity index 100% rename from traits/src/sign.rs rename to src/sign.rs diff --git a/traits/Cargo.toml b/traits/Cargo.toml deleted file mode 100644 index e691851..0000000 --- a/traits/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -description = "Numeric traits for generic mathematics" -documentation = "http://rust-num.github.io/num" -homepage = "https://github.com/rust-num/num" -keywords = ["mathematics", "numerics"] -categories = [ "algorithms", "science" ] -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-num/num" -name = "num-traits" -version = "0.1.41" - -[dependencies] diff --git a/traits/LICENSE-APACHE b/traits/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/traits/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/traits/LICENSE-MIT b/traits/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/traits/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/traits/src/lib.rs b/traits/src/lib.rs deleted file mode 100644 index 0cfc2c7..0000000 --- a/traits/src/lib.rs +++ /dev/null @@ -1,437 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Numeric traits for generic mathematics -#![doc(html_logo_url = "https://rust-num.github.io/num/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://rust-num.github.io/num/favicon.ico", - html_root_url = "https://rust-num.github.io/num/", - html_playground_url = "http://play.integer32.com/")] - -use std::ops::{Add, Sub, Mul, Div, Rem}; -use std::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; -use std::num::Wrapping; - -pub use bounds::Bounded; -pub use float::{Float, FloatConst}; -pub use identities::{Zero, One, zero, one}; -pub use ops::checked::*; -pub use ops::wrapping::*; -pub use ops::saturating::Saturating; -pub use sign::{Signed, Unsigned, abs, abs_sub, signum}; -pub use cast::*; -pub use int::PrimInt; -pub use pow::{pow, checked_pow}; - -pub mod identities; -pub mod sign; -pub mod ops; -pub mod bounds; -pub mod float; -pub mod cast; -pub mod int; -pub mod pow; - -/// The base trait for numeric types, covering `0` and `1` values, -/// comparisons, basic numeric operations, and string conversion. -pub trait Num: PartialEq + Zero + One + NumOps -{ - type FromStrRadixErr; - - /// Convert from a string and radix <= 36. - /// - /// # Examples - /// - /// ```rust - /// use num_traits::Num; - /// - /// let result = ::from_str_radix("27", 10); - /// assert_eq!(result, Ok(27)); - /// - /// let result = ::from_str_radix("foo", 10); - /// assert!(result.is_err()); - /// ``` - fn from_str_radix(str: &str, radix: u32) -> Result; -} - -/// The trait for types implementing basic numeric operations -/// -/// This is automatically implemented for types which implement the operators. -pub trait NumOps - : Add - + Sub - + Mul - + Div - + Rem -{} - -impl NumOps for T -where T: Add - + Sub - + Mul - + Div - + Rem -{} - -/// The trait for `Num` types which also implement numeric operations taking -/// the second operand by reference. -/// -/// This is automatically implemented for types which implement the operators. -pub trait NumRef: Num + for<'r> NumOps<&'r Self> {} -impl NumRef for T where T: Num + for<'r> NumOps<&'r T> {} - -/// The trait for references which implement numeric operations, taking the -/// second operand either by value or by reference. -/// -/// This is automatically implemented for types which implement the operators. -pub trait RefNum: NumOps + for<'r> NumOps<&'r Base, Base> {} -impl RefNum for T where T: NumOps + for<'r> NumOps<&'r Base, Base> {} - -/// The trait for types implementing numeric assignment operators (like `+=`). -/// -/// This is automatically implemented for types which implement the operators. -pub trait NumAssignOps - : AddAssign - + SubAssign - + MulAssign - + DivAssign - + RemAssign -{} - -impl NumAssignOps for T -where T: AddAssign - + SubAssign - + MulAssign - + DivAssign - + RemAssign -{} - -/// The trait for `Num` types which also implement assignment operators. -/// -/// This is automatically implemented for types which implement the operators. -pub trait NumAssign: Num + NumAssignOps {} -impl NumAssign for T where T: Num + NumAssignOps {} - -/// The trait for `NumAssign` types which also implement assignment operations -/// taking the second operand by reference. -/// -/// This is automatically implemented for types which implement the operators. -pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {} -impl NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {} - - -macro_rules! int_trait_impl { - ($name:ident for $($t:ty)*) => ($( - impl $name for $t { - type FromStrRadixErr = ::std::num::ParseIntError; - #[inline] - fn from_str_radix(s: &str, radix: u32) - -> Result - { - <$t>::from_str_radix(s, radix) - } - } - )*) -} -int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64); - -impl Num for Wrapping - where Wrapping: - Add> + Sub> - + Mul> + Div> + Rem> -{ - type FromStrRadixErr = T::FromStrRadixErr; - fn from_str_radix(str: &str, radix: u32) -> Result { - T::from_str_radix(str, radix).map(Wrapping) - } -} - - -#[derive(Debug)] -pub enum FloatErrorKind { - Empty, - Invalid, -} -// FIXME: std::num::ParseFloatError is stable in 1.0, but opaque to us, -// so there's not really any way for us to reuse it. -#[derive(Debug)] -pub struct ParseFloatError { - pub kind: FloatErrorKind, -} - -// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck -// with this implementation ourselves until we want to make a breaking change. -// (would have to drop it from `Num` though) -macro_rules! float_trait_impl { - ($name:ident for $($t:ty)*) => ($( - impl $name for $t { - type FromStrRadixErr = ParseFloatError; - - fn from_str_radix(src: &str, radix: u32) - -> Result - { - use self::FloatErrorKind::*; - use self::ParseFloatError as PFE; - - // Special values - match src { - "inf" => return Ok(Float::infinity()), - "-inf" => return Ok(Float::neg_infinity()), - "NaN" => return Ok(Float::nan()), - _ => {}, - } - - fn slice_shift_char(src: &str) -> Option<(char, &str)> { - src.chars().nth(0).map(|ch| (ch, &src[1..])) - } - - let (is_positive, src) = match slice_shift_char(src) { - None => return Err(PFE { kind: Empty }), - Some(('-', "")) => return Err(PFE { kind: Empty }), - Some(('-', src)) => (false, src), - Some((_, _)) => (true, src), - }; - - // The significand to accumulate - let mut sig = if is_positive { 0.0 } else { -0.0 }; - // Necessary to detect overflow - let mut prev_sig = sig; - let mut cs = src.chars().enumerate(); - // Exponent prefix and exponent index offset - let mut exp_info = None::<(char, usize)>; - - // Parse the integer part of the significand - for (i, c) in cs.by_ref() { - match c.to_digit(radix) { - Some(digit) => { - // shift significand one digit left - sig = sig * (radix as $t); - - // add/subtract current digit depending on sign - if is_positive { - sig = sig + ((digit as isize) as $t); - } else { - sig = sig - ((digit as isize) as $t); - } - - // Detect overflow by comparing to last value, except - // if we've not seen any non-zero digits. - if prev_sig != 0.0 { - if is_positive && sig <= prev_sig - { return Ok(Float::infinity()); } - if !is_positive && sig >= prev_sig - { return Ok(Float::neg_infinity()); } - - // Detect overflow by reversing the shift-and-add process - if is_positive && (prev_sig != (sig - digit as $t) / radix as $t) - { return Ok(Float::infinity()); } - if !is_positive && (prev_sig != (sig + digit as $t) / radix as $t) - { return Ok(Float::neg_infinity()); } - } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - '.' => { - break; // start of fractional part - }, - _ => { - return Err(PFE { kind: Invalid }); - }, - }, - } - } - - // If we are not yet at the exponent parse the fractional - // part of the significand - if exp_info.is_none() { - let mut power = 1.0; - for (i, c) in cs.by_ref() { - match c.to_digit(radix) { - Some(digit) => { - // Decrease power one order of magnitude - power = power / (radix as $t); - // add/subtract current digit depending on sign - sig = if is_positive { - sig + (digit as $t) * power - } else { - sig - (digit as $t) * power - }; - // Detect overflow by comparing to last value - if is_positive && sig < prev_sig - { return Ok(Float::infinity()); } - if !is_positive && sig > prev_sig - { return Ok(Float::neg_infinity()); } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - _ => { - return Err(PFE { kind: Invalid }); - }, - }, - } - } - } - - // Parse and calculate the exponent - let exp = match exp_info { - Some((c, offset)) => { - let base = match c { - 'E' | 'e' if radix == 10 => 10.0, - 'P' | 'p' if radix == 16 => 2.0, - _ => return Err(PFE { kind: Invalid }), - }; - - // Parse the exponent as decimal integer - let src = &src[offset..]; - let (is_positive, exp) = match slice_shift_char(src) { - Some(('-', src)) => (false, src.parse::()), - Some(('+', src)) => (true, src.parse::()), - Some((_, _)) => (true, src.parse::()), - None => return Err(PFE { kind: Invalid }), - }; - - match (is_positive, exp) { - (true, Ok(exp)) => base.powi(exp as i32), - (false, Ok(exp)) => 1.0 / base.powi(exp as i32), - (_, Err(_)) => return Err(PFE { kind: Invalid }), - } - }, - None => 1.0, // no exponent - }; - - Ok(sig * exp) - } - } - )*) -} -float_trait_impl!(Num for f32 f64); - -/// A value bounded by a minimum and a maximum -/// -/// If input is less than min then this returns min. -/// If input is greater than max then this returns max. -/// Otherwise this returns input. -#[inline] -pub fn clamp(input: T, min: T, max: T) -> T { - debug_assert!(min <= max, "min must be less than or equal to max"); - if input < min { - min - } else if input > max { - max - } else { - input - } -} - -#[test] -fn clamp_test() { - // Int test - assert_eq!(1, clamp(1, -1, 2)); - assert_eq!(-1, clamp(-2, -1, 2)); - assert_eq!(2, clamp(3, -1, 2)); - - // Float test - assert_eq!(1.0, clamp(1.0, -1.0, 2.0)); - assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0)); - assert_eq!(2.0, clamp(3.0, -1.0, 2.0)); -} - -#[test] -fn from_str_radix_unwrap() { - // The Result error must impl Debug to allow unwrap() - - let i: i32 = Num::from_str_radix("0", 10).unwrap(); - assert_eq!(i, 0); - - let f: f32 = Num::from_str_radix("0.0", 10).unwrap(); - assert_eq!(f, 0.0); -} - -#[test] -fn wrapping_is_num() { - fn require_num(_: &T) {} - require_num(&Wrapping(42_u32)); - require_num(&Wrapping(-42)); -} - -#[test] -fn wrapping_from_str_radix() { - macro_rules! test_wrapping_from_str_radix { - ($($t:ty)+) => { - $( - for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] { - let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0); - assert_eq!(w, <$t as Num>::from_str_radix(s, r)); - } - )+ - }; - } - - test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); -} - -#[test] -fn check_num_ops() { - fn compute(x: T, y: T) -> T { - x * y / y % y + y - y - } - assert_eq!(compute(1, 2), 1) -} - -#[test] -fn check_numref_ops() { - fn compute(x: T, y: &T) -> T { - x * y / y % y + y - y - } - assert_eq!(compute(1, &2), 1) -} - -#[test] -fn check_refnum_ops() { - fn compute(x: &T, y: T) -> T - where for<'a> &'a T: RefNum - { - &(&(&(&(x * y) / y) % y) + y) - y - } - assert_eq!(compute(&1, 2), 1) -} - -#[test] -fn check_refref_ops() { - fn compute(x: &T, y: &T) -> T - where for<'a> &'a T: RefNum - { - &(&(&(&(x * y) / y) % y) + y) - y - } - assert_eq!(compute(&1, &2), 1) -} - -#[test] -fn check_numassign_ops() { - fn compute(mut x: T, y: T) -> T { - x *= y; - x /= y; - x %= y; - x += y; - x -= y; - x - } - assert_eq!(compute(1, 2), 1) -} - -// TODO test `NumAssignRef`, but even the standard numeric types don't -// implement this yet. (see rust pr41336)