diff --git a/Cargo.lock b/Cargo.lock index 3a9193535489..9485e1674448 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3520,11 +3520,11 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 0.1.6", + "autocfg 1.0.1", "num-integer", "num-traits", ] @@ -3542,11 +3542,11 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg 0.1.6", + "autocfg 1.0.1", "num-traits", ] diff --git a/third_party/rust/num-bigint/.cargo-checksum.json b/third_party/rust/num-bigint/.cargo-checksum.json index 288114fb2c67..390f95e39fef 100644 --- a/third_party/rust/num-bigint/.cargo-checksum.json +++ b/third_party/rust/num-bigint/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"ba1041ccca008388ab7d7432ae63b811d8e744c8fa9e50f371bfbeb78acd1995","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"25f684f15b0ed6ea216c3831e567a9b5dc02b78ff7e579e0d7323305db75218c","RELEASES.md":"5a3045437dc1850ae4e39acd14f2660ed7bace9b0c4d7dae3950f049dbfd4d65","benches/bigint.rs":"252c0dc1f220a6fbdc151e729069260c2f5909516467ceb873e412e5691d7042","benches/factorial.rs":"d536f5584987847f10321b94175a0d8fd2beb14b7c814ec28eef1f96ca081fbe","benches/gcd.rs":"7ec5ce7174e1d31bd08ccc5670f5a32a5c084f258d7980cd6d02e0a8bb5562c4","benches/roots.rs":"3f87db894c379122aee5cd8520c7c759c26d8a9649ac47f45d1bf4d560e1cb07","benches/shootout-pidigits.rs":"985b76d6dba05c396efe4da136c6a0bb2c02bcf5b05cbb346f0f802a891629bb","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"56d4fbb7a55750e61d2074df2735a31995c1decbd988c0e722926235e0fed487","ci/rustup.sh":"c976bb2756da3876363b01fdbf06c13de20df421e5add45e4017c4df42ed06a6","ci/test_full.sh":"a0ac26b85809eb43edd813c9dc88f34a1a8227b7618f4bede89c8f2ac9a4c05a","src/algorithms.rs":"8827c46df051214d1d0e7670680ca9f4834eae678ed340c86b5ea32fddbc7c3c","src/bigint.rs":"7f113fdc034c566bc8475ff0a7d136aa8250cae047b4356084e6797a15f968e1","src/bigrand.rs":"d2f72b8833f367dd8990b4b026f302d838144c5a4de942135d39a3a9932f137d","src/biguint.rs":"b95bfcf84e3f831fb07982aa4b058cd16a524eaa493946eed8e8c5fb8d65797a","src/lib.rs":"d5cc50306f73f07555e7d3413edd2ca5c7d54cbc80a2e83844d77fb8750ae314","src/macros.rs":"2e763517922d960c06e3ac4d319b1d81e66dffadfde8fdf300ff8b8bb95bd8cd","src/monty.rs":"6a867846b7f6af9115add2fd59fccd0651c71dd7f2316e8fb9c812ff3c27da12","tests/bigint.rs":"f7df454f085a862ad5a98e3a802303a3fdf06275a7a1b92074b40b76a715bed2","tests/bigint_bitwise.rs":"dc9436c8f200f2b0ac08cefb23bb8e39c4e688e9026a506a678416c3d573128b","tests/bigint_scalar.rs":"aa176ed102cafd425a215a93460806914d8f3ac288c98ec3e56772fa17379838","tests/biguint.rs":"9ae79f96d1a3beca5be95dffe9d79dc3436f886edc6cae51faf4203c3e0c4681","tests/biguint_scalar.rs":"9cc6f2bf2fe77f34b09eb2266c23aded3b27a60dc1859eb60d3013164292467e","tests/consts/mod.rs":"f9ea5f40733e2f5f432803d830be9db929d91e5e5efd8510b07c6ced2fe554be","tests/macros/mod.rs":"2789b680dd14a770d5ceef430018be0ada85098d69e218c61c17214084c4f763","tests/modpow.rs":"f14cdea11e355a371b314cc866dfa13281a3226706ab2cf01c1485273afde300","tests/quickcheck.rs":"6d6c1ec244b2384a8b34e989870aef8bcedccf6cc46e2626b29a032703bef03c","tests/rand.rs":"08370135bd78432660cfcd708a9ea852022d555bc92c1f3c482fabd17faa64a0","tests/roots.rs":"9ec1bdb0cd1c72402a41e5470325a5276af75979b7fc0f0b63e7bbbb9f3505b2","tests/serde.rs":"79d7a0347207b3a3666af67d2ed97fa34f2922732121a3cb8f5b9f990846acfa","tests/torture.rs":"9fe4897580c0ebe2b7062f5b0b890b4b03510daa45c9236f0edba7144f9eb6f8"},"package":"f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a"} \ No newline at end of file +{"files":{"Cargo.toml":"e10df83bce937fc2d2ee258af173fee42891dc2d5bc3217955935669bdcc6dfb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"00ff4891b409b25220a0f863c772a786c81cf291fab894963a2c8d7a251f67fd","RELEASES.md":"e712d5bdd58cc82a34f15f7926b4a7a65022ededc3069375fc54ab63eba2d133","benches/bigint.rs":"252c0dc1f220a6fbdc151e729069260c2f5909516467ceb873e412e5691d7042","benches/factorial.rs":"d536f5584987847f10321b94175a0d8fd2beb14b7c814ec28eef1f96ca081fbe","benches/gcd.rs":"7ec5ce7174e1d31bd08ccc5670f5a32a5c084f258d7980cd6d02e0a8bb5562c4","benches/roots.rs":"3f87db894c379122aee5cd8520c7c759c26d8a9649ac47f45d1bf4d560e1cb07","benches/shootout-pidigits.rs":"985b76d6dba05c396efe4da136c6a0bb2c02bcf5b05cbb346f0f802a891629bb","bors.toml":"1c81ede536a37edd30fe4e622ff0531b25372403ac9475a5d6c50f14156565a2","build.rs":"b4b2d0df90ca7570a339ca4d84a72e4ef00d9dced8927350424e666790c752d7","ci/rustup.sh":"c976bb2756da3876363b01fdbf06c13de20df421e5add45e4017c4df42ed06a6","ci/test_full.sh":"a0ac26b85809eb43edd813c9dc88f34a1a8227b7618f4bede89c8f2ac9a4c05a","src/algorithms.rs":"96220e32bd2496fbcba07ba35ef21e08e12a38d85d9724b33877c078040caf99","src/bigint.rs":"5d4888db1d8487a5c73bd4ee23967f4ba04f6f6edb4c3212902297e61f628141","src/bigrand.rs":"025b795928efa69592da2a7f54a60b0b72105ec6bae652f1f1b6402d6ca7bf3a","src/biguint.rs":"068abe461e9ba0582a2a18aede236ffdfe0cffc39fae9688f6a0873af6935b9b","src/lib.rs":"0f4280a9ffd3b8465ecaf9a7c99087bf18e5242b31d0311ac15bec4e995e5a41","src/macros.rs":"327691e39e31ac2d708e2bb02b50338d57cb0d3ca7107a30117df391bf781714","src/monty.rs":"ecdacb02e7d0a64b249a3395bf33c26f62b1ca05908f2eab0edd7f8f7a2ad7ae","tests/bigint.rs":"f7df454f085a862ad5a98e3a802303a3fdf06275a7a1b92074b40b76a715bed2","tests/bigint_bitwise.rs":"dc9436c8f200f2b0ac08cefb23bb8e39c4e688e9026a506a678416c3d573128b","tests/bigint_scalar.rs":"fddaa72911cd22cd34df130fee65dc1a1447ddbd9dfe5491b15e7a5868ee49e7","tests/biguint.rs":"9ae79f96d1a3beca5be95dffe9d79dc3436f886edc6cae51faf4203c3e0c4681","tests/biguint_scalar.rs":"4601e36b78bb177893f3abbd0a4050030eb8a65d3e57cdf005aea0a5b811adde","tests/consts/mod.rs":"f9ea5f40733e2f5f432803d830be9db929d91e5e5efd8510b07c6ced2fe554be","tests/macros/mod.rs":"5e73339e8baa9fc2c3f5b9097f9909091b5e4b47f905ffdf7da81d4647c6141c","tests/modpow.rs":"e21e46a97fc5da7eed1db5d6a52ac7ba50b78532f1a97aa46d41867d4848282c","tests/quickcheck.rs":"a3c68279b50cc35ec2856b74ac3f3265457dd788ed6138a14dd16a32868f22ba","tests/rand.rs":"08370135bd78432660cfcd708a9ea852022d555bc92c1f3c482fabd17faa64a0","tests/roots.rs":"9ec1bdb0cd1c72402a41e5470325a5276af75979b7fc0f0b63e7bbbb9f3505b2","tests/serde.rs":"79d7a0347207b3a3666af67d2ed97fa34f2922732121a3cb8f5b9f990846acfa","tests/torture.rs":"9fe4897580c0ebe2b7062f5b0b890b4b03510daa45c9236f0edba7144f9eb6f8"},"package":"090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"} \ No newline at end of file diff --git a/third_party/rust/num-bigint/Cargo.toml b/third_party/rust/num-bigint/Cargo.toml index d8403a5659fc..9b99bae63f42 100644 --- a/third_party/rust/num-bigint/Cargo.toml +++ b/third_party/rust/num-bigint/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "num-bigint" -version = "0.2.3" +version = "0.2.6" authors = ["The Rust Project Developers"] build = "build.rs" description = "Big integer implementation for Rust" @@ -42,11 +42,11 @@ name = "roots" name = "shootout-pidigits" harness = false [dependencies.num-integer] -version = "0.1.39" +version = "0.1.42" default-features = false [dependencies.num-traits] -version = "0.2.7" +version = "0.2.11" default-features = false [dependencies.quickcheck] @@ -73,7 +73,7 @@ default-features = false [dev-dependencies.serde_test] version = "1.0" [build-dependencies.autocfg] -version = "0.1.2" +version = "1" [features] default = ["std"] diff --git a/third_party/rust/num-bigint/README.md b/third_party/rust/num-bigint/README.md index f7eefed87e69..4691c9a72505 100644 --- a/third_party/rust/num-bigint/README.md +++ b/third_party/rust/num-bigint/README.md @@ -33,6 +33,19 @@ Implementations for `i128` and `u128` are only available with Rust 1.26 and later. The build script automatically detects this, but you can make it mandatory by enabling the `i128` crate feature. +### Random Generation + +`num-bigint` supports the generation of random big integers when the `rand` +feature is enabled. To enable it include rand as + +```toml +rand = "0.5" +num-bigint = { version = "0.2", features = ["rand"] } +``` + +Note that you must use the version of `rand` that `num-bigint` is compatible +with: `0.5`. + ## Releases Release notes are available in [RELEASES.md](RELEASES.md). diff --git a/third_party/rust/num-bigint/RELEASES.md b/third_party/rust/num-bigint/RELEASES.md index 911dd7835f87..358534ec0a92 100644 --- a/third_party/rust/num-bigint/RELEASES.md +++ b/third_party/rust/num-bigint/RELEASES.md @@ -1,3 +1,35 @@ +# Release 0.2.6 (2020-01-27) + +- [Fix the promotion of negative `isize` in `BigInt` assign-ops][133]. + +**Contributors**: @cuviper, @HactarCE + +[133]: https://github.com/rust-num/num-bigint/pull/133 + +# Release 0.2.5 (2020-01-09) + +- [Updated the `autocfg` build dependency to 1.0][126]. + +**Contributors**: @cuviper, @tspiteri + +[126]: https://github.com/rust-num/num-bigint/pull/126 + +# Release 0.2.4 (2020-01-01) + +- [The new `BigUint::to_u32_digits` method][104] returns the number as a + little-endian vector of base-232 digits. The same method on + `BigInt` also returns the sign. +- [`BigUint::modpow` now applies a modulus even for exponent 1][113], which + also affects `BigInt::modpow`. +- [`BigInt::modpow` now returns the correct sign for negative bases with even + exponents][114]. + +[104]: https://github.com/rust-num/num-bigint/pull/104 +[113]: https://github.com/rust-num/num-bigint/pull/113 +[114]: https://github.com/rust-num/num-bigint/pull/114 + +**Contributors**: @alex-ozdemir, @cuviper, @dingelish, @Speedy37, @youknowone + # Release 0.2.3 (2019-09-03) - [`Pow` is now implemented for `BigUint` exponents][77]. diff --git a/third_party/rust/num-bigint/build.rs b/third_party/rust/num-bigint/build.rs index 15590bbc12bb..e483c15fd7f6 100644 --- a/third_party/rust/num-bigint/build.rs +++ b/third_party/rust/num-bigint/build.rs @@ -10,5 +10,5 @@ fn main() { panic!("i128 support was not detected!"); } - autocfg::rerun_path(file!()); + autocfg::rerun_path("build.rs"); } diff --git a/third_party/rust/num-bigint/src/algorithms.rs b/third_party/rust/num-bigint/src/algorithms.rs index 26f29b81546f..223f051a6aab 100644 --- a/third_party/rust/num-bigint/src/algorithms.rs +++ b/third_party/rust/num-bigint/src/algorithms.rs @@ -470,17 +470,17 @@ fn mac3(acc: &mut [BigDigit], b: &[BigDigit], c: &[BigDigit]) { 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; + comp2 += &comp1 - &r4; + comp1 -= &comp3; // Recomposition. The coefficients of the polynomial are now known. // // Evaluate at w(t) where t is our given base to get the result. let result = r0 - + (comp1 << 32 * i) - + (comp2 << 2 * 32 * i) - + (comp3 << 3 * 32 * i) - + (r4 << 4 * 32 * i); + + (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); } @@ -656,8 +656,8 @@ fn div_rem_core(mut a: BigUint, b: &BigUint) -> (BigUint, BigUint) { while cmp_slice(&prod.data[..], &a.data[j..]) == Greater { let one: BigUint = One::one(); - q0 = q0 - one; - prod = prod - b; + q0 -= one; + prod -= b; } add2(&mut q.data[j..], &q0.data[..]); @@ -667,7 +667,7 @@ fn div_rem_core(mut a: BigUint, b: &BigUint) -> (BigUint, BigUint) { tmp = q0; } - debug_assert!(&a < b); + debug_assert!(a < *b); (q.normalized(), a) } @@ -759,7 +759,7 @@ pub fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { return Greater; } } - return Equal; + Equal } #[cfg(test)] diff --git a/third_party/rust/num-bigint/src/bigint.rs b/third_party/rust/num-bigint/src/bigint.rs index 93c72be6af49..bd74e7d32396 100644 --- a/third_party/rust/num-bigint/src/bigint.rs +++ b/third_party/rust/num-bigint/src/bigint.rs @@ -2097,21 +2097,21 @@ impl<'a> Neg for &'a BigInt { impl CheckedAdd for BigInt { #[inline] fn checked_add(&self, v: &BigInt) -> Option { - return Some(self.add(v)); + Some(self.add(v)) } } impl CheckedSub for BigInt { #[inline] fn checked_sub(&self, v: &BigInt) -> Option { - return Some(self.sub(v)); + Some(self.sub(v)) } } impl CheckedMul for BigInt { #[inline] fn checked_mul(&self, v: &BigInt) -> Option { - return Some(self.mul(v)); + Some(self.mul(v)) } } @@ -2121,7 +2121,7 @@ impl CheckedDiv for BigInt { if v.is_zero() { return None; } - return Some(self.div(v)); + Some(self.div(v)) } } @@ -2195,7 +2195,7 @@ impl Integer for BigInt { /// Deprecated, use `is_multiple_of` instead. #[inline] fn divides(&self, other: &BigInt) -> bool { - return self.is_multiple_of(other); + self.is_multiple_of(other) } /// Returns `true` if the number is a multiple of `other`. @@ -2572,7 +2572,7 @@ impl_to_bigint!(f64, FromPrimitive::from_f64); impl BigInt { /// Creates and initializes a BigInt. /// - /// The digits are in little-endian base 232. + /// The base 232 digits are ordered least significant digit first. #[inline] pub fn new(sign: Sign, digits: Vec) -> BigInt { BigInt::from_biguint(sign, BigUint::new(digits)) @@ -2580,7 +2580,7 @@ impl BigInt { /// Creates and initializes a `BigInt`. /// - /// The digits are in little-endian base 232. + /// The base 232 digits are ordered least significant digit first. #[inline] pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt { if sign == NoSign { @@ -2596,12 +2596,16 @@ impl BigInt { } /// Creates and initializes a `BigInt`. + /// + /// The base 232 digits are ordered least significant digit first. #[inline] pub fn from_slice(sign: Sign, slice: &[u32]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_slice(slice)) } /// Reinitializes a `BigInt`. + /// + /// The base 232 digits are ordered least significant digit first. #[inline] pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) { if sign == NoSign { @@ -2778,7 +2782,26 @@ impl BigInt { (self.sign, self.data.to_bytes_le()) } - /// Returns the two's complement byte representation of the `BigInt` in big-endian byte order. + /// Returns the sign and the `u32` digits representation of the `BigInt` ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from(-1125).to_u32_digits(), (Sign::Minus, vec![1125])); + /// assert_eq!(BigInt::from(4294967295u32).to_u32_digits(), (Sign::Plus, vec![4294967295])); + /// assert_eq!(BigInt::from(4294967296u64).to_u32_digits(), (Sign::Plus, vec![0, 1])); + /// assert_eq!(BigInt::from(-112500000000i64).to_u32_digits(), (Sign::Minus, vec![830850304, 26])); + /// assert_eq!(BigInt::from(112500000000i64).to_u32_digits(), (Sign::Plus, vec![830850304, 26])); + /// ``` + #[inline] + pub fn to_u32_digits(&self) -> (Sign, Vec) { + (self.sign, self.data.to_u32_digits()) + } + + /// Returns the two's-complement byte representation of the `BigInt` in big-endian byte order. /// /// # Examples /// @@ -2791,7 +2814,7 @@ impl BigInt { #[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); + let first_byte = bytes.first().cloned().unwrap_or(0); if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) @@ -2806,7 +2829,7 @@ impl BigInt { bytes } - /// Returns the two's complement byte representation of the `BigInt` in little-endian byte order. + /// Returns the two's-complement byte representation of the `BigInt` in little-endian byte order. /// /// # Examples /// @@ -2819,7 +2842,7 @@ impl BigInt { #[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); + let last_byte = bytes.last().cloned().unwrap_or(0); if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero) @@ -2930,17 +2953,17 @@ impl BigInt { #[inline] pub fn checked_add(&self, v: &BigInt) -> Option { - return Some(self.add(v)); + Some(self.add(v)) } #[inline] pub fn checked_sub(&self, v: &BigInt) -> Option { - return Some(self.sub(v)); + Some(self.sub(v)) } #[inline] pub fn checked_mul(&self, v: &BigInt) -> Option { - return Some(self.mul(v)); + Some(self.mul(v)) } #[inline] @@ -2948,7 +2971,7 @@ impl BigInt { if v.is_zero() { return None; } - return Some(self.div(v)); + Some(self.div(v)) } /// Returns `(self ^ exponent) mod modulus` @@ -2972,7 +2995,10 @@ impl BigInt { } // The sign of the result follows the modulus, like `mod_floor`. - let (sign, mag) = match (self.is_negative(), modulus.is_negative()) { + let (sign, mag) = match ( + self.is_negative() && exponent.is_odd(), + modulus.is_negative(), + ) { (false, false) => (Plus, result), (true, false) => (Plus, &modulus.data - result), (false, true) => (Minus, &modulus.data - result), diff --git a/third_party/rust/num-bigint/src/bigrand.rs b/third_party/rust/num-bigint/src/bigrand.rs index 4a13b29df48b..69564dd13a94 100644 --- a/third_party/rust/num-bigint/src/bigrand.rs +++ b/third_party/rust/num-bigint/src/bigrand.rs @@ -14,6 +14,9 @@ use bigint::{into_magnitude, magnitude}; use integer::Integer; use traits::Zero; +/// A trait for sampling random big integers. +/// +/// The `rand` feature must be enabled to use this. See crate-level documentation for details. pub trait RandBigInt { /// Generate a random `BigUint` of the given bit size. fn gen_biguint(&mut self, bit_size: usize) -> BigUint; @@ -191,6 +194,8 @@ impl SampleUniform for BigInt { } /// A random distribution for `BigUint` and `BigInt` values of a particular bit size. +/// +/// The `rand` feature must be enabled to use this. See crate-level documentation for details. #[derive(Clone, Copy, Debug)] pub struct RandomBits { bits: usize, diff --git a/third_party/rust/num-bigint/src/biguint.rs b/third_party/rust/num-bigint/src/biguint.rs index e6e9fbcce5ab..68363424ffc4 100644 --- a/third_party/rust/num-bigint/src/biguint.rs +++ b/third_party/rust/num-bigint/src/biguint.rs @@ -61,7 +61,7 @@ impl Arbitrary for BigUint { #[allow(bare_trait_objects)] // `dyn` needs Rust 1.27 to parse, even when cfg-disabled fn shrink(&self) -> Box> { // Use shrinker from Vec - Box::new(self.data.shrink().map(|x| BigUint::new(x))) + Box::new(self.data.shrink().map(BigUint::new)) } } @@ -600,7 +600,7 @@ impl AddAssign for BigUint { #[inline] fn add_assign(&mut self, other: u32) { if other != 0 { - if self.data.len() == 0 { + if self.data.is_empty() { self.data.push(0); } @@ -745,7 +745,7 @@ impl Sub for u32 { #[inline] fn sub(self, mut other: BigUint) -> BigUint { - if other.data.len() == 0 { + if other.data.is_empty() { other.data.push(self as BigDigit); } else { sub2rev(&[self as BigDigit], &mut other.data[..]); @@ -1225,7 +1225,7 @@ impl<'a> Neg for &'a BigUint { impl CheckedAdd for BigUint { #[inline] fn checked_add(&self, v: &BigUint) -> Option { - return Some(self.add(v)); + Some(self.add(v)) } } @@ -1243,7 +1243,7 @@ impl CheckedSub for BigUint { impl CheckedMul for BigUint { #[inline] fn checked_mul(&self, v: &BigUint) -> Option { - return Some(self.mul(v)); + Some(self.mul(v)) } } @@ -1253,7 +1253,7 @@ impl CheckedDiv for BigUint { if v.is_zero() { return None; } - return Some(self.div(v)); + Some(self.div(v)) } } @@ -1678,9 +1678,9 @@ impl FromPrimitive for BigUint { let mut ret = BigUint::from(mantissa); if exponent > 0 { - ret = ret << exponent as usize; + ret <<= exponent as usize; } else if exponent < 0 { - ret = ret >> (-exponent) as usize; + ret >>= (-exponent) as usize; } Some(ret) } @@ -1915,7 +1915,7 @@ pub fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { impl BigUint { /// Creates and initializes a `BigUint`. /// - /// The digits are in little-endian base 232. + /// The base 232 digits are ordered least significant digit first. #[inline] pub fn new(digits: Vec) -> BigUint { BigUint { data: digits }.normalized() @@ -1923,7 +1923,7 @@ impl BigUint { /// Creates and initializes a `BigUint`. /// - /// The digits are in little-endian base 232. + /// The base 232 digits are ordered least significant digit first. #[inline] pub fn from_slice(slice: &[u32]) -> BigUint { BigUint::new(slice.to_vec()) @@ -1931,7 +1931,7 @@ impl BigUint { /// Assign a value to a `BigUint`. /// - /// The digits are in little-endian base 232. + /// The base 232 digits are ordered least significant digit first. #[inline] pub fn assign_from_slice(&mut self, slice: &[u32]) { self.data.resize(slice.len(), 0); @@ -2125,6 +2125,24 @@ impl BigUint { } } + /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).to_u32_digits(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).to_u32_digits(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).to_u32_digits(), vec![0, 1]); + /// assert_eq!(BigUint::from(112500000000u64).to_u32_digits(), vec![830850304, 26]); + /// ``` + #[inline] + pub fn to_u32_digits(&self) -> Vec { + self.data.clone() + } + /// Returns the integer formatted as a string in the given radix. /// `radix` must be in the range `2...36`. /// @@ -2190,7 +2208,7 @@ impl BigUint { return 0; } let zeros = self.data.last().unwrap().leading_zeros(); - return self.data.len() * big_digit::BITS - zeros as usize; + self.data.len() * big_digit::BITS - zeros as usize } /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to @@ -2251,7 +2269,7 @@ fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> Big Some(i) => i, }; - let mut base = base.clone(); + let mut base = base % modulus; for _ in 0..i { for _ in 0..big_digit::BITS { base = &base * &base % modulus; diff --git a/third_party/rust/num-bigint/src/lib.rs b/third_party/rust/num-bigint/src/lib.rs index dece7bab0070..837870a6265d 100644 --- a/third_party/rust/num-bigint/src/lib.rs +++ b/third_party/rust/num-bigint/src/lib.rs @@ -71,6 +71,33 @@ //! # } //! ``` //! +//! See the "Features" section for instructions for enabling random number generation. +//! +//! ## Features +//! +//! The `std` crate feature is mandatory and enabled by default. If you depend on +//! `num-bigint` with `default-features = false`, you must manually enable the +//! `std` feature yourself. In the future, we hope to support `#![no_std]` with +//! the `alloc` crate when `std` is not enabled. +//! +//! Implementations for `i128` and `u128` are only available with Rust 1.26 and +//! later. The build script automatically detects this, but you can make it +//! mandatory by enabling the `i128` crate feature. +//! +//! ### Random Generation +//! +//! `num-bigint` supports the generation of random big integers when the `rand` +//! feature is enabled. To enable it include rand as +//! +//! ```toml +//! rand = "0.5" +//! num-bigint = { version = "0.2", features = ["rand"] } +//! ``` +//! +//! Note that you must use the version of `rand` that `num-bigint` is compatible +//! with: `0.5`. +//! +//! //! ## Compatibility //! //! The `num-bigint` crate is tested for rustc 1.15 and greater. diff --git a/third_party/rust/num-bigint/src/macros.rs b/third_party/rust/num-bigint/src/macros.rs index 0ba6e48c72fe..735cfcb9f36c 100644 --- a/third_party/rust/num-bigint/src/macros.rs +++ b/third_party/rust/num-bigint/src/macros.rs @@ -344,7 +344,7 @@ macro_rules! promote_signed_scalars { macro_rules! promote_signed_scalars_assign { (impl $imp:ident for $res:ty, $method:ident) => { promote_scalars_assign!(impl $imp for $res, $method, i8, i16); - promote_scalars_assign!(impl $imp for $res, $method, isize); + promote_scalars_assign!(impl $imp for $res, $method, isize); } } diff --git a/third_party/rust/num-bigint/src/monty.rs b/third_party/rust/num-bigint/src/monty.rs index 72a4ab53eb68..62f59b38fc54 100644 --- a/third_party/rust/num-bigint/src/monty.rs +++ b/third_party/rust/num-bigint/src/monty.rs @@ -84,7 +84,7 @@ fn monty_redc(a: BigUint, mr: &MontyReducer) -> BigUint { let ret = BigUint::new(c[n_size..].to_vec()); // 5: if R >= β^n then return R-N else return R. - if &ret < mr.n { + if ret < *mr.n { ret } else { ret - mr.n @@ -121,7 +121,7 @@ pub fn monty_modpow(a: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { ans = monty_mult(ans, &apri, &mr); } apri = monty_sqr(apri, &mr); - e = e >> 1; + e >>= 1; } // Map the result back to the residues domain diff --git a/third_party/rust/num-bigint/tests/bigint_scalar.rs b/third_party/rust/num-bigint/tests/bigint_scalar.rs index ae9a6d7aa22f..6a1601eaa947 100644 --- a/third_party/rust/num-bigint/tests/bigint_scalar.rs +++ b/third_party/rust/num-bigint/tests/bigint_scalar.rs @@ -18,6 +18,7 @@ fn test_scalar_add() { fn check(x: &BigInt, y: &BigInt, z: &BigInt) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_signed_scalar_op!(x + y == z); + assert_signed_scalar_assign_op!(x += y == z); } for elm in SUM_TRIPLES.iter() { @@ -43,6 +44,7 @@ fn test_scalar_sub() { fn check(x: &BigInt, y: &BigInt, z: &BigInt) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_signed_scalar_op!(x - y == z); + assert_signed_scalar_assign_op!(x -= y == z); } for elm in SUM_TRIPLES.iter() { @@ -68,6 +70,7 @@ fn test_scalar_mul() { fn check(x: &BigInt, y: &BigInt, z: &BigInt) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_signed_scalar_op!(x * y == z); + assert_signed_scalar_assign_op!(x *= y == z); } for elm in MUL_TRIPLES.iter() { @@ -98,15 +101,18 @@ fn test_scalar_div_rem() { assert!(q == *ans_q); assert!(r == *ans_r); + let b = BigInt::from(b); 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); + assert_signed_scalar_op!(a / b == ans_q); + assert_signed_scalar_op!(a % b == ans_r); + assert_signed_scalar_assign_op!(a /= b == ans_q); + assert_signed_scalar_assign_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); - } + let nb = -b; + assert_signed_scalar_op!(a / nb == -ans_q.clone()); + assert_signed_scalar_op!(a % nb == ans_r); + assert_signed_scalar_assign_op!(a /= nb == -ans_q.clone()); + assert_signed_scalar_assign_op!(a %= nb == ans_r); } fn check(a: &BigInt, b: u32, q: &BigInt, r: &BigInt) { diff --git a/third_party/rust/num-bigint/tests/biguint_scalar.rs b/third_party/rust/num-bigint/tests/biguint_scalar.rs index fb8fbf0357af..452277357d5f 100644 --- a/third_party/rust/num-bigint/tests/biguint_scalar.rs +++ b/third_party/rust/num-bigint/tests/biguint_scalar.rs @@ -15,6 +15,7 @@ fn test_scalar_add() { fn check(x: &BigUint, y: &BigUint, z: &BigUint) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_unsigned_scalar_op!(x + y == z); + assert_unsigned_scalar_assign_op!(x += y == z); } for elm in SUM_TRIPLES.iter() { @@ -33,6 +34,7 @@ fn test_scalar_sub() { fn check(x: &BigUint, y: &BigUint, z: &BigUint) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_unsigned_scalar_op!(x - y == z); + assert_unsigned_scalar_assign_op!(x -= y == z); } for elm in SUM_TRIPLES.iter() { @@ -51,6 +53,7 @@ fn test_scalar_mul() { fn check(x: &BigUint, y: &BigUint, z: &BigUint) { let (x, y, z) = (x.clone(), y.clone(), z.clone()); assert_unsigned_scalar_op!(x * y == z); + assert_unsigned_scalar_assign_op!(x *= y == z); } for elm in MUL_TRIPLES.iter() { @@ -76,6 +79,8 @@ fn test_scalar_div_rem() { let (x, y, z, r) = (x.clone(), y.clone(), z.clone(), r.clone()); assert_unsigned_scalar_op!(x / y == z); assert_unsigned_scalar_op!(x % y == r); + assert_unsigned_scalar_assign_op!(x /= y == z); + assert_unsigned_scalar_assign_op!(x %= y == r); } for elm in MUL_TRIPLES.iter() { @@ -104,6 +109,8 @@ fn test_scalar_div_rem() { check(&a, &b, &c, &d); assert_unsigned_scalar_op!(a / b == c); assert_unsigned_scalar_op!(a % b == d); + assert_unsigned_scalar_assign_op!(a /= b == c); + assert_unsigned_scalar_assign_op!(a %= b == d); } } } diff --git a/third_party/rust/num-bigint/tests/macros/mod.rs b/third_party/rust/num-bigint/tests/macros/mod.rs index d848b29b35ee..946534a374a8 100644 --- a/third_party/rust/num-bigint/tests/macros/mod.rs +++ b/third_party/rust/num-bigint/tests/macros/mod.rs @@ -68,3 +68,49 @@ macro_rules! assert_signed_scalar_op { $left $op $right == $expected); }; } + +/// Assert that an op works for scalar right +macro_rules! assert_scalar_assign_op { + (($($to:ident),*) $left:ident $op:tt $right:ident == $expected:expr) => { + $( + if let Some(right) = $right.$to() { + let mut left = $left.clone(); + assert_eq!({ left $op right; left}, $expected); + } + )* + }; +} + +#[cfg(not(has_i128))] +macro_rules! assert_unsigned_scalar_assign_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_assign_op!((to_u8, to_u16, to_u32, to_u64, to_usize) + $left $op $right == $expected); + }; +} + +#[cfg(has_i128)] +macro_rules! assert_unsigned_scalar_assign_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_assign_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128) + $left $op $right == $expected); + }; +} + +#[cfg(not(has_i128))] +macro_rules! assert_signed_scalar_assign_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_assign_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); + }; +} + +#[cfg(has_i128)] +macro_rules! assert_signed_scalar_assign_op { + ($left:ident $op:tt $right:ident == $expected:expr) => { + assert_scalar_assign_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128, + to_i8, to_i16, to_i32, to_i64, to_isize, to_i128) + $left $op $right == $expected); + }; +} diff --git a/third_party/rust/num-bigint/tests/modpow.rs b/third_party/rust/num-bigint/tests/modpow.rs index b7a992c863ad..a5f8b9289016 100644 --- a/third_party/rust/num-bigint/tests/modpow.rs +++ b/third_party/rust/num-bigint/tests/modpow.rs @@ -81,6 +81,19 @@ mod biguint { check_modpow::(0, 15, 11, 0); check_modpow::(3, 7, 11, 9); check_modpow::(5, 117, 19, 1); + check_modpow::(20, 1, 2, 0); + check_modpow::(20, 1, 3, 2); + } + + #[test] + fn test_modpow_small() { + for b in 0u64..11 { + for e in 0u64..11 { + for m in 1..11 { + check_modpow::(b, e, m, b.pow(e as u32) % m); + } + } + } } #[test] @@ -102,7 +115,7 @@ mod biguint { mod bigint { use num_bigint::BigInt; use num_integer::Integer; - use num_traits::{Num, One, Signed, Zero}; + use num_traits::{Num, One, Signed}; fn check_modpow>(b: T, e: T, m: T, r: T) { fn check(b: &BigInt, e: &BigInt, m: &BigInt, r: &BigInt) { @@ -122,12 +135,18 @@ mod bigint { let m: BigInt = m.into(); let r: BigInt = r.into(); - let neg_r = if r.is_zero() { BigInt::zero() } else { &m - &r }; + let neg_b_r = if e.is_odd() { + (-&r).mod_floor(&m) + } else { + r.clone() + }; + let neg_m_r = r.mod_floor(&-&m); + let neg_bm_r = neg_b_r.mod_floor(&-&m); check(&b, &e, &m, &r); - check(&-&b, &e, &m, &neg_r); - check(&b, &e, &-&m, &-neg_r); - check(&-b, &e, &-m, &-r); + check(&-&b, &e, &m, &neg_b_r); + check(&b, &e, &-&m, &neg_m_r); + check(&-b, &e, &-&m, &neg_bm_r); } #[test] @@ -136,6 +155,22 @@ mod bigint { check_modpow(0, 15, 11, 0); check_modpow(3, 7, 11, 9); check_modpow(5, 117, 19, 1); + check_modpow(-20, 1, 2, 0); + check_modpow(-20, 1, 3, 1); + } + + #[test] + fn test_modpow_small() { + for b in -10i64..11 { + for e in 0i64..11 { + for m in -10..11 { + if m == 0 { + continue; + } + check_modpow(b, e, m, b.pow(e as u32).mod_floor(&m)); + } + } + } } #[test] diff --git a/third_party/rust/num-bigint/tests/quickcheck.rs b/third_party/rust/num-bigint/tests/quickcheck.rs index 6bb251fa9031..a9e7b04b5256 100644 --- a/third_party/rust/num-bigint/tests/quickcheck.rs +++ b/third_party/rust/num-bigint/tests/quickcheck.rs @@ -10,7 +10,8 @@ extern crate quickcheck; extern crate quickcheck_macros; use num_bigint::{BigInt, BigUint}; -use num_traits::{Num, One, Pow, Zero}; +use num_integer::Integer; +use num_traits::{Num, One, Pow, Signed, Zero}; use quickcheck::{QuickCheck, StdThreadGen, TestResult}; #[quickcheck] @@ -315,3 +316,46 @@ fn quicktest_shift() { qc.quickcheck(test_shl_unsigned as fn(u32, u8) -> TestResult); qc.quickcheck(test_shl_signed as fn(i32, u8) -> TestResult); } + +#[test] +fn quickcheck_modpow() { + let gen = StdThreadGen::new(usize::max_value()); + let mut qc = QuickCheck::with_gen(gen); + + fn simple_modpow(base: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt { + assert!(!exponent.is_negative()); + let mut result = BigInt::one().mod_floor(modulus); + let mut base = base.mod_floor(modulus); + let mut exponent = exponent.clone(); + while !exponent.is_zero() { + if exponent.is_odd() { + result = (result * &base).mod_floor(modulus); + } + base = (&base * &base).mod_floor(modulus); + exponent >>= 1; + } + result + } + + fn test_modpow(base: i128, exponent: u128, modulus: i128) -> TestResult { + if modulus.is_zero() { + TestResult::discard() + } else { + let base = BigInt::from(base); + let exponent = BigInt::from(exponent); + let modulus = BigInt::from(modulus); + let modpow = base.modpow(&exponent, &modulus); + let simple = simple_modpow(&base, &exponent, &modulus); + if modpow != simple { + eprintln!("{}.modpow({}, {})", base, exponent, modulus); + eprintln!(" expected {}", simple); + eprintln!(" actual {}", modpow); + TestResult::failed() + } else { + TestResult::passed() + } + } + } + + qc.quickcheck(test_modpow as fn(i128, u128, i128) -> TestResult); +} diff --git a/third_party/rust/num-integer/.cargo-checksum.json b/third_party/rust/num-integer/.cargo-checksum.json index 1b932b50ba54..7732a7dba78e 100644 --- a/third_party/rust/num-integer/.cargo-checksum.json +++ b/third_party/rust/num-integer/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"54f4df5d505f0f8581a9455d2ea52bc385f003f97116c3d13b0e8e0cc491903f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"7ad5fb625f7ef61595a2180f3b26715457552faa8bb08526c70b416da29b2533","RELEASES.md":"ea8b30468b1d1c16ebe9e148a62df378cb9d3198bb4095c889fe521245690f9d","benches/gcd.rs":"9b5c0ae8ccd6c7fc8f8384fb351d10cfdd0be5fbea9365f9ea925d8915b015bf","benches/roots.rs":"79b4ab2d8fe7bbf43fe65314d2e1bc206165bc4cb34b3ceaa899f9ea7af31c09","build.rs":"56d4fbb7a55750e61d2074df2735a31995c1decbd988c0e722926235e0fed487","src/lib.rs":"937d6a77d6542b47aafb872df7181dcafc1ab596df0e5d78b2e6577ae9463dd0","src/roots.rs":"2a9b908bd3666b5cffc58c1b37d329e46ed02f71ad6d5deea1e8440c10660e1a","tests/roots.rs":"a0caa4142899ec8cb806a7a0d3410c39d50de97cceadc4c2ceca707be91b1ddd"},"package":"b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"} \ No newline at end of file +{"files":{"Cargo.toml":"bf0e4a51897e9586cffa4897f69bf7caee769cc9b0292f3dd7ebd4fd5ddcb8f3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"68f533703554b9130ea902776bd9eb20d1a2d32b213ebadebcd49ed0f1ef9728","RELEASES.md":"658b382f2358d6f6733021ecfdcc1fc1faf89d7106e0f72d0f3b34d35442d71b","benches/average.rs":"2a30b4ccd8ece8663d17583ae2e3623e654b5f401babef90f1634722824e6c2b","benches/gcd.rs":"9b5c0ae8ccd6c7fc8f8384fb351d10cfdd0be5fbea9365f9ea925d8915b015bf","benches/roots.rs":"79b4ab2d8fe7bbf43fe65314d2e1bc206165bc4cb34b3ceaa899f9ea7af31c09","build.rs":"575b157527243fe355a7c8d7d874a1f790c3fb0177beba9032076a7803c5b9dd","src/average.rs":"a66cf6a49f893e60697c17b2540258e69daa15ab97d8d444c6f2e8cac2f01ae9","src/lib.rs":"bf0ce9a09f92f606ca038288cde7a29670ccca480d42ec97e88f3c56b117e33c","src/roots.rs":"2a9b908bd3666b5cffc58c1b37d329e46ed02f71ad6d5deea1e8440c10660e1a","tests/average.rs":"5f26a31be042626e9af66f7b751798621561fa090da48b1ec5ab63e388288a91","tests/roots.rs":"a0caa4142899ec8cb806a7a0d3410c39d50de97cceadc4c2ceca707be91b1ddd"},"package":"d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"} \ No newline at end of file diff --git a/third_party/rust/num-integer/Cargo.toml b/third_party/rust/num-integer/Cargo.toml index 3937fa1477ac..8f72e395981c 100644 --- a/third_party/rust/num-integer/Cargo.toml +++ b/third_party/rust/num-integer/Cargo.toml @@ -12,25 +12,25 @@ [package] name = "num-integer" -version = "0.1.41" +version = "0.1.44" authors = ["The Rust Project Developers"] build = "build.rs" -exclude = ["/ci/*", "/.travis.yml", "/bors.toml"] +exclude = ["/bors.toml", "/ci/*", "/.github/*"] description = "Integer traits and functions" homepage = "https://github.com/rust-num/num-integer" documentation = "https://docs.rs/num-integer" readme = "README.md" keywords = ["mathematics", "numerics"] categories = ["algorithms", "science", "no-std"] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" repository = "https://github.com/rust-num/num-integer" [package.metadata.docs.rs] features = ["std"] [dependencies.num-traits] -version = "0.2.4" +version = "0.2.11" default-features = false [build-dependencies.autocfg] -version = "0.1.3" +version = "1" [features] default = ["std"] diff --git a/third_party/rust/num-integer/README.md b/third_party/rust/num-integer/README.md index 4b3d42e7218d..5f638cd0f42b 100644 --- a/third_party/rust/num-integer/README.md +++ b/third_party/rust/num-integer/README.md @@ -2,8 +2,8 @@ [![crate](https://img.shields.io/crates/v/num-integer.svg)](https://crates.io/crates/num-integer) [![documentation](https://docs.rs/num-integer/badge.svg)](https://docs.rs/num-integer) -![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg) -[![Travis status](https://travis-ci.org/rust-num/num-integer.svg?branch=master)](https://travis-ci.org/rust-num/num-integer) +[![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) +[![build status](https://github.com/rust-num/num-integer/workflows/master/badge.svg)](https://github.com/rust-num/num-integer/actions) `Integer` trait and functions for Rust. @@ -40,7 +40,6 @@ Implementations for `i128` and `u128` are only available with Rust 1.26 and later. The build script automatically detects this, but you can make it mandatory by enabling the `i128` crate feature. - ## Releases Release notes are available in [RELEASES.md](RELEASES.md). @@ -48,3 +47,18 @@ Release notes are available in [RELEASES.md](RELEASES.md). ## Compatibility The `num-integer` crate is tested for rustc 1.8 and greater. + +## License + +Licensed under either of + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/third_party/rust/num-integer/RELEASES.md b/third_party/rust/num-integer/RELEASES.md index ebc19f76cd51..05be073c35bd 100644 --- a/third_party/rust/num-integer/RELEASES.md +++ b/third_party/rust/num-integer/RELEASES.md @@ -1,3 +1,30 @@ +# Release 0.1.44 (2020-10-29) + +- [The "i128" feature now bypasses compiler probing][35]. The build script + used to probe anyway and panic if requested support wasn't found, but + sometimes this ran into bad corner cases with `autocfg`. + +**Contributors**: @cuviper + +[35]: https://github.com/rust-num/num-integer/pull/35 + +# Release 0.1.43 (2020-06-11) + +- [The new `Average` trait][31] computes fast integer averages, rounded up or + down, without any risk of overflow. + +**Contributors**: @althonos, @cuviper + +[31]: https://github.com/rust-num/num-integer/pull/31 + +# Release 0.1.42 (2020-01-09) + +- [Updated the `autocfg` build dependency to 1.0][29]. + +**Contributors**: @cuviper, @dingelish + +[29]: https://github.com/rust-num/num-integer/pull/29 + # Release 0.1.41 (2019-05-21) - [Fixed feature detection on `no_std` targets][25]. diff --git a/third_party/rust/num-integer/benches/average.rs b/third_party/rust/num-integer/benches/average.rs new file mode 100644 index 000000000000..05d824c840ec --- /dev/null +++ b/third_party/rust/num-integer/benches/average.rs @@ -0,0 +1,414 @@ +//! Benchmark sqrt and cbrt + +#![feature(test)] + +extern crate num_integer; +extern crate num_traits; +extern crate test; + +use num_integer::Integer; +use num_traits::{AsPrimitive, PrimInt, WrappingAdd, WrappingMul}; +use std::cmp::{max, min}; +use std::fmt::Debug; +use test::{black_box, Bencher}; + +// --- Utilities for RNG ---------------------------------------------------- + +trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {} + +impl BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {} + +// Simple PRNG so we don't have to worry about rand compatibility +fn lcg(x: T) -> T +where + u32: AsPrimitive, + T: BenchInteger, +{ + // LCG parameters from Numerical Recipes + // (but we're applying it to arbitrary sizes) + const LCG_A: u32 = 1664525; + const LCG_C: u32 = 1013904223; + x.wrapping_mul(&LCG_A.as_()).wrapping_add(&LCG_C.as_()) +} + +// --- Alt. Implementations ------------------------------------------------- + +trait NaiveAverage { + fn naive_average_ceil(&self, other: &Self) -> Self; + fn naive_average_floor(&self, other: &Self) -> Self; +} + +trait UncheckedAverage { + fn unchecked_average_ceil(&self, other: &Self) -> Self; + fn unchecked_average_floor(&self, other: &Self) -> Self; +} + +trait ModuloAverage { + fn modulo_average_ceil(&self, other: &Self) -> Self; + fn modulo_average_floor(&self, other: &Self) -> Self; +} + +macro_rules! naive_average { + ($T:ident) => { + impl super::NaiveAverage for $T { + fn naive_average_floor(&self, other: &$T) -> $T { + match self.checked_add(*other) { + Some(z) => z.div_floor(&2), + None => { + if self > other { + let diff = self - other; + other + diff.div_floor(&2) + } else { + let diff = other - self; + self + diff.div_floor(&2) + } + } + } + } + fn naive_average_ceil(&self, other: &$T) -> $T { + match self.checked_add(*other) { + Some(z) => z.div_ceil(&2), + None => { + if self > other { + let diff = self - other; + self - diff.div_floor(&2) + } else { + let diff = other - self; + other - diff.div_floor(&2) + } + } + } + } + } + }; +} + +macro_rules! unchecked_average { + ($T:ident) => { + impl super::UncheckedAverage for $T { + fn unchecked_average_floor(&self, other: &$T) -> $T { + self.wrapping_add(*other) / 2 + } + fn unchecked_average_ceil(&self, other: &$T) -> $T { + (self.wrapping_add(*other) / 2).wrapping_add(1) + } + } + }; +} + +macro_rules! modulo_average { + ($T:ident) => { + impl super::ModuloAverage for $T { + fn modulo_average_ceil(&self, other: &$T) -> $T { + let (q1, r1) = self.div_mod_floor(&2); + let (q2, r2) = other.div_mod_floor(&2); + q1 + q2 + (r1 | r2) + } + fn modulo_average_floor(&self, other: &$T) -> $T { + let (q1, r1) = self.div_mod_floor(&2); + let (q2, r2) = other.div_mod_floor(&2); + q1 + q2 + (r1 * r2) + } + } + }; +} + +// --- Bench functions ------------------------------------------------------ + +fn bench_unchecked(b: &mut Bencher, v: &[(T, T)], f: F) +where + T: Integer + Debug + Copy, + F: Fn(&T, &T) -> T, +{ + b.iter(|| { + for (x, y) in v { + black_box(f(x, y)); + } + }); +} + +fn bench_ceil(b: &mut Bencher, v: &[(T, T)], f: F) +where + T: Integer + Debug + Copy, + F: Fn(&T, &T) -> T, +{ + for &(i, j) in v { + let rt = f(&i, &j); + let (a, b) = (min(i, j), max(i, j)); + // if both number are the same sign, check rt is in the middle + if (a < T::zero()) == (b < T::zero()) { + if (b - a).is_even() { + assert_eq!(rt - a, b - rt); + } else { + assert_eq!(rt - a, b - rt + T::one()); + } + // if both number have a different sign, + } else { + if (a + b).is_even() { + assert_eq!(rt, (a + b) / (T::one() + T::one())) + } else { + assert_eq!(rt, (a + b + T::one()) / (T::one() + T::one())) + } + } + } + bench_unchecked(b, v, f); +} + +fn bench_floor(b: &mut Bencher, v: &[(T, T)], f: F) +where + T: Integer + Debug + Copy, + F: Fn(&T, &T) -> T, +{ + for &(i, j) in v { + let rt = f(&i, &j); + let (a, b) = (min(i, j), max(i, j)); + // if both number are the same sign, check rt is in the middle + if (a < T::zero()) == (b < T::zero()) { + if (b - a).is_even() { + assert_eq!(rt - a, b - rt); + } else { + assert_eq!(rt - a + T::one(), b - rt); + } + // if both number have a different sign, + } else { + if (a + b).is_even() { + assert_eq!(rt, (a + b) / (T::one() + T::one())) + } else { + assert_eq!(rt, (a + b - T::one()) / (T::one() + T::one())) + } + } + } + bench_unchecked(b, v, f); +} + +// --- Bench implementation ------------------------------------------------- + +macro_rules! bench_average { + ($($T:ident),*) => {$( + mod $T { + use test::Bencher; + use num_integer::{Average, Integer}; + use super::{UncheckedAverage, NaiveAverage, ModuloAverage}; + use super::{bench_ceil, bench_floor, bench_unchecked}; + + naive_average!($T); + unchecked_average!($T); + modulo_average!($T); + + const SIZE: $T = 30; + + fn overflowing() -> Vec<($T, $T)> { + (($T::max_value()-SIZE)..$T::max_value()) + .flat_map(|x| -> Vec<_> { + (($T::max_value()-100)..($T::max_value()-100+SIZE)) + .map(|y| (x, y)) + .collect() + }) + .collect() + } + + fn small() -> Vec<($T, $T)> { + (0..SIZE) + .flat_map(|x| -> Vec<_> {(0..SIZE).map(|y| (x, y)).collect()}) + .collect() + } + + fn rand() -> Vec<($T, $T)> { + small() + .into_iter() + .map(|(x, y)| (super::lcg(x), super::lcg(y))) + .collect() + } + + mod ceil { + + use super::*; + + mod small { + + use super::*; + + #[bench] + fn optimized(b: &mut Bencher) { + let v = small(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.average_ceil(y)); + } + + #[bench] + fn naive(b: &mut Bencher) { + let v = small(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.naive_average_ceil(y)); + } + + #[bench] + fn unchecked(b: &mut Bencher) { + let v = small(); + bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_ceil(y)); + } + + #[bench] + fn modulo(b: &mut Bencher) { + let v = small(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.modulo_average_ceil(y)); + } + } + + mod overflowing { + + use super::*; + + #[bench] + fn optimized(b: &mut Bencher) { + let v = overflowing(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.average_ceil(y)); + } + + #[bench] + fn naive(b: &mut Bencher) { + let v = overflowing(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.naive_average_ceil(y)); + } + + #[bench] + fn unchecked(b: &mut Bencher) { + let v = overflowing(); + bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_ceil(y)); + } + + #[bench] + fn modulo(b: &mut Bencher) { + let v = overflowing(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.modulo_average_ceil(y)); + } + } + + mod rand { + + use super::*; + + #[bench] + fn optimized(b: &mut Bencher) { + let v = rand(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.average_ceil(y)); + } + + #[bench] + fn naive(b: &mut Bencher) { + let v = rand(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.naive_average_ceil(y)); + } + + #[bench] + fn unchecked(b: &mut Bencher) { + let v = rand(); + bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_ceil(y)); + } + + #[bench] + fn modulo(b: &mut Bencher) { + let v = rand(); + bench_ceil(b, &v, |x: &$T, y: &$T| x.modulo_average_ceil(y)); + } + } + + } + + mod floor { + + use super::*; + + mod small { + + use super::*; + + #[bench] + fn optimized(b: &mut Bencher) { + let v = small(); + bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y)); + } + + #[bench] + fn naive(b: &mut Bencher) { + let v = small(); + bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y)); + } + + #[bench] + fn unchecked(b: &mut Bencher) { + let v = small(); + bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y)); + } + + #[bench] + fn modulo(b: &mut Bencher) { + let v = small(); + bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y)); + } + } + + mod overflowing { + + use super::*; + + #[bench] + fn optimized(b: &mut Bencher) { + let v = overflowing(); + bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y)); + } + + #[bench] + fn naive(b: &mut Bencher) { + let v = overflowing(); + bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y)); + } + + #[bench] + fn unchecked(b: &mut Bencher) { + let v = overflowing(); + bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y)); + } + + #[bench] + fn modulo(b: &mut Bencher) { + let v = overflowing(); + bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y)); + } + } + + mod rand { + + use super::*; + + #[bench] + fn optimized(b: &mut Bencher) { + let v = rand(); + bench_floor(b, &v, |x: &$T, y: &$T| x.average_floor(y)); + } + + #[bench] + fn naive(b: &mut Bencher) { + let v = rand(); + bench_floor(b, &v, |x: &$T, y: &$T| x.naive_average_floor(y)); + } + + #[bench] + fn unchecked(b: &mut Bencher) { + let v = rand(); + bench_unchecked(b, &v, |x: &$T, y: &$T| x.unchecked_average_floor(y)); + } + + #[bench] + fn modulo(b: &mut Bencher) { + let v = rand(); + bench_floor(b, &v, |x: &$T, y: &$T| x.modulo_average_floor(y)); + } + } + + } + + } + )*} +} + +bench_average!(i8, i16, i32, i64, i128, isize); +bench_average!(u8, u16, u32, u64, u128, usize); diff --git a/third_party/rust/num-integer/build.rs b/third_party/rust/num-integer/build.rs index 15590bbc12bb..37c985766a38 100644 --- a/third_party/rust/num-integer/build.rs +++ b/third_party/rust/num-integer/build.rs @@ -3,12 +3,11 @@ extern crate autocfg; use std::env; fn main() { - let ac = autocfg::new(); - if ac.probe_type("i128") { - println!("cargo:rustc-cfg=has_i128"); - } else if env::var_os("CARGO_FEATURE_I128").is_some() { - panic!("i128 support was not detected!"); + // If the "i128" feature is explicity requested, don't bother probing for it. + // It will still cause a build error if that was set improperly. + if env::var_os("CARGO_FEATURE_I128").is_some() || autocfg::new().probe_type("i128") { + autocfg::emit("has_i128"); } - autocfg::rerun_path(file!()); + autocfg::rerun_path("build.rs"); } diff --git a/third_party/rust/num-integer/src/average.rs b/third_party/rust/num-integer/src/average.rs new file mode 100644 index 000000000000..29cd11e3fec6 --- /dev/null +++ b/third_party/rust/num-integer/src/average.rs @@ -0,0 +1,78 @@ +use core::ops::{BitAnd, BitOr, BitXor, Shr}; +use Integer; + +/// Provides methods to compute the average of two integers, without overflows. +pub trait Average: Integer { + /// Returns the ceiling value of the average of `self` and `other`. + /// -- `⌈(self + other)/2⌉` + /// + /// # Examples + /// + /// ``` + /// use num_integer::Average; + /// + /// assert_eq!(( 3).average_ceil(&10), 7); + /// assert_eq!((-2).average_ceil(&-5), -3); + /// assert_eq!(( 4).average_ceil(& 4), 4); + /// + /// assert_eq!(u8::max_value().average_ceil(&2), 129); + /// assert_eq!(i8::min_value().average_ceil(&-1), -64); + /// assert_eq!(i8::min_value().average_ceil(&i8::max_value()), 0); + /// ``` + /// + fn average_ceil(&self, other: &Self) -> Self; + + /// Returns the floor value of the average of `self` and `other`. + /// -- `⌊(self + other)/2⌋` + /// + /// # Examples + /// + /// ``` + /// use num_integer::Average; + /// + /// assert_eq!(( 3).average_floor(&10), 6); + /// assert_eq!((-2).average_floor(&-5), -4); + /// assert_eq!(( 4).average_floor(& 4), 4); + /// + /// assert_eq!(u8::max_value().average_floor(&2), 128); + /// assert_eq!(i8::min_value().average_floor(&-1), -65); + /// assert_eq!(i8::min_value().average_floor(&i8::max_value()), -1); + /// ``` + /// + fn average_floor(&self, other: &Self) -> Self; +} + +impl Average for I +where + I: Integer + Shr, + for<'a, 'b> &'a I: + BitAnd<&'b I, Output = I> + BitOr<&'b I, Output = I> + BitXor<&'b I, Output = I>, +{ + // The Henry Gordon Dietz implementation as shown in the Hacker's Delight, + // see http://aggregate.org/MAGIC/#Average%20of%20Integers + + /// Returns the floor value of the average of `self` and `other`. + #[inline] + fn average_floor(&self, other: &I) -> I { + (self & other) + ((self ^ other) >> 1) + } + + /// Returns the ceil value of the average of `self` and `other`. + #[inline] + fn average_ceil(&self, other: &I) -> I { + (self | other) - ((self ^ other) >> 1) + } +} + +/// Returns the floor value of the average of `x` and `y` -- +/// see [Average::average_floor](trait.Average.html#tymethod.average_floor). +#[inline] +pub fn average_floor(x: T, y: T) -> T { + x.average_floor(&y) +} +/// Returns the ceiling value of the average of `x` and `y` -- +/// see [Average::average_ceil](trait.Average.html#tymethod.average_ceil). +#[inline] +pub fn average_ceil(x: T, y: T) -> T { + x.average_ceil(&y) +} diff --git a/third_party/rust/num-integer/src/lib.rs b/third_party/rust/num-integer/src/lib.rs index aa12ba68c4bb..02819541b958 100644 --- a/third_party/rust/num-integer/src/lib.rs +++ b/third_party/rust/num-integer/src/lib.rs @@ -30,6 +30,10 @@ mod roots; pub use roots::Roots; pub use roots::{cbrt, nth_root, sqrt}; +mod average; +pub use average::Average; +pub use average::{average_ceil, average_floor}; + pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// Floored integer division. /// @@ -257,7 +261,6 @@ pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// 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. diff --git a/third_party/rust/num-integer/tests/average.rs b/third_party/rust/num-integer/tests/average.rs new file mode 100644 index 000000000000..9fd8cf18f4ea --- /dev/null +++ b/third_party/rust/num-integer/tests/average.rs @@ -0,0 +1,100 @@ +extern crate num_integer; +extern crate num_traits; + +macro_rules! test_average { + ($I:ident, $U:ident) => { + mod $I { + mod ceil { + use num_integer::Average; + + #[test] + fn same_sign() { + assert_eq!((14 as $I).average_ceil(&16), 15 as $I); + assert_eq!((14 as $I).average_ceil(&17), 16 as $I); + + let max = $crate::std::$I::MAX; + assert_eq!((max - 3).average_ceil(&(max - 1)), max - 2); + assert_eq!((max - 3).average_ceil(&(max - 2)), max - 2); + } + + #[test] + fn different_sign() { + assert_eq!((14 as $I).average_ceil(&-4), 5 as $I); + assert_eq!((14 as $I).average_ceil(&-5), 5 as $I); + + let min = $crate::std::$I::MIN; + let max = $crate::std::$I::MAX; + assert_eq!(min.average_ceil(&max), 0 as $I); + } + } + + mod floor { + use num_integer::Average; + + #[test] + fn same_sign() { + assert_eq!((14 as $I).average_floor(&16), 15 as $I); + assert_eq!((14 as $I).average_floor(&17), 15 as $I); + + let max = $crate::std::$I::MAX; + assert_eq!((max - 3).average_floor(&(max - 1)), max - 2); + assert_eq!((max - 3).average_floor(&(max - 2)), max - 3); + } + + #[test] + fn different_sign() { + assert_eq!((14 as $I).average_floor(&-4), 5 as $I); + assert_eq!((14 as $I).average_floor(&-5), 4 as $I); + + let min = $crate::std::$I::MIN; + let max = $crate::std::$I::MAX; + assert_eq!(min.average_floor(&max), -1 as $I); + } + } + } + + mod $U { + mod ceil { + use num_integer::Average; + + #[test] + fn bounded() { + assert_eq!((14 as $U).average_ceil(&16), 15 as $U); + assert_eq!((14 as $U).average_ceil(&17), 16 as $U); + } + + #[test] + fn overflow() { + let max = $crate::std::$U::MAX; + assert_eq!((max - 3).average_ceil(&(max - 1)), max - 2); + assert_eq!((max - 3).average_ceil(&(max - 2)), max - 2); + } + } + + mod floor { + use num_integer::Average; + + #[test] + fn bounded() { + assert_eq!((14 as $U).average_floor(&16), 15 as $U); + assert_eq!((14 as $U).average_floor(&17), 15 as $U); + } + + #[test] + fn overflow() { + let max = $crate::std::$U::MAX; + assert_eq!((max - 3).average_floor(&(max - 1)), max - 2); + assert_eq!((max - 3).average_floor(&(max - 2)), max - 3); + } + } + } + }; +} + +test_average!(i8, u8); +test_average!(i16, u16); +test_average!(i32, u32); +test_average!(i64, u64); +#[cfg(has_i128)] +test_average!(i128, u128); +test_average!(isize, usize);