From a849284320679d646d10b14b0dca34cf13567925 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 27 Apr 2018 23:52:41 -0700 Subject: [PATCH] Remove big_digit::* from the public API The *idea* of `big_digit` and its type aliases is that we may someday use something other than `u32` in the representation, perhaps even different sizes for different targets. That's still a possibility, but I think it's not really feasible to expose this variation in the public API. Calling `BigUint::from_slice([1, 2, 3])` is only meaningful if you know what that size is, and users can't really alternate this kind of thing based on a type definition. So for now, we just commit to `u32` units in the public API, no matter what we may do internally. This removal is a breaking change, part of the 0.2 semver bump. If I'm wrong and somebody can show a compelling use case for `big_digit`, we can always add things back into the public API later. --- src/algorithms.rs | 47 +++---------------------------------- src/bigint.rs | 8 +++---- src/biguint.rs | 13 ++++------- src/lib.rs | 40 +++++++++++++++++++++++++++++-- tests/bigint.rs | 22 ++++++++--------- tests/bigint_bitwise.rs | 6 ++--- tests/bigint_scalar.rs | 6 ++--- tests/biguint.rs | 52 +++++++++++++++++++++++------------------ tests/consts/mod.rs | 26 ++++++++++----------- 9 files changed, 108 insertions(+), 112 deletions(-) diff --git a/src/algorithms.rs b/src/algorithms.rs index 032ce987..c3b3a840 100644 --- a/src/algorithms.rs +++ b/src/algorithms.rs @@ -12,49 +12,7 @@ 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; - - /// A `SignedDoubleBigDigit` is the signed version of `DoubleBigDigit`. - pub type SignedDoubleBigDigit = i64; - - 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, SignedDoubleBigDigit}; +use big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit}; // Generic functions for add/subtract/multiply with carry/borrow: @@ -647,7 +605,8 @@ pub fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { #[cfg(test)] mod algorithm_tests { - use {BigDigit, BigUint, BigInt}; + use big_digit::BigDigit; + use {BigUint, BigInt}; use Sign::Plus; use traits::Num; diff --git a/src/bigint.rs b/src/bigint.rs index 6e7faf49..03cfd46f 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -25,7 +25,7 @@ use traits::{ToPrimitive, FromPrimitive, Num, CheckedAdd, CheckedSub, use self::Sign::{Minus, NoSign, Plus}; use super::ParseBigIntError; -use super::big_digit::{self, BigDigit, DoubleBigDigit}; +use big_digit::{self, BigDigit, DoubleBigDigit}; use biguint; use biguint::to_str_radix_reversed; use biguint::{BigUint, IntDigits}; @@ -1868,7 +1868,7 @@ impl BigInt { /// /// The digits are in little-endian base 232. #[inline] - pub fn new(sign: Sign, digits: Vec) -> BigInt { + pub fn new(sign: Sign, digits: Vec) -> BigInt { BigInt::from_biguint(sign, BigUint::new(digits)) } @@ -1891,13 +1891,13 @@ impl BigInt { /// Creates and initializes a `BigInt`. #[inline] - pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt { + pub fn from_slice(sign: Sign, slice: &[u32]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_slice(slice)) } /// Reinitializes a `BigInt`. #[inline] - pub fn assign_from_slice(&mut self, sign: Sign, slice: &[BigDigit]) { + pub fn assign_from_slice(&mut self, sign: Sign, slice: &[u32]) { if sign == NoSign { self.data.assign_from_slice(&[]); self.sign = NoSign; diff --git a/src/biguint.rs b/src/biguint.rs index 0866a02b..2dd9181c 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -21,12 +21,12 @@ use integer::Integer; use traits::{ToPrimitive, FromPrimitive, Float, Num, Unsigned, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, Zero, One}; +use big_digit::{self, BigDigit, DoubleBigDigit}; + #[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, __sub2rev, add2, sub2, sub2rev}; @@ -39,9 +39,6 @@ use UsizePromotion; use ParseBigIntError; /// 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)] pub struct BigUint { data: Vec, @@ -1379,7 +1376,7 @@ impl BigUint { /// /// The digits are in little-endian base 232. #[inline] - pub fn new(digits: Vec) -> BigUint { + pub fn new(digits: Vec) -> BigUint { BigUint { data: digits }.normalized() } @@ -1387,7 +1384,7 @@ impl BigUint { /// /// The digits are in little-endian base 232. #[inline] - pub fn from_slice(slice: &[BigDigit]) -> BigUint { + pub fn from_slice(slice: &[u32]) -> BigUint { BigUint::new(slice.to_vec()) } @@ -1395,7 +1392,7 @@ impl BigUint { /// /// The digits are in little-endian base 232. #[inline] - pub fn assign_from_slice(&mut self, slice: &[BigDigit]) { + pub fn assign_from_slice(&mut self, slice: &[u32]) { self.data.resize(slice.len(), 0); self.data.clone_from_slice(slice); self.normalize(); diff --git a/src/lib.rs b/src/lib.rs index 13f53871..197e1dd4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -152,10 +152,46 @@ 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; + +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; + + /// A `SignedDoubleBigDigit` is the signed version of `DoubleBigDigit`. + pub type SignedDoubleBigDigit = i64; + + // `DoubleBigDigit` size dependent + pub const BITS: usize = 32; + + 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) + } +} diff --git a/tests/bigint.rs b/tests/bigint.rs index eae94054..9bf91f99 100644 --- a/tests/bigint.rs +++ b/tests/bigint.rs @@ -3,7 +3,7 @@ extern crate num_integer; extern crate num_traits; extern crate rand; -use num_bigint::{BigDigit, BigUint, big_digit}; +use num_bigint::BigUint; use num_bigint::{BigInt, ToBigInt}; use num_bigint::Sign::{Minus, NoSign, Plus}; @@ -163,7 +163,7 @@ fn test_from_signed_bytes_be() { #[test] fn test_cmp() { - let vs: [&[BigDigit]; 4] = [&[2 as BigDigit], &[1, 1], &[2, 1], &[1, 1, 1]]; + let vs: [&[u32]; 4] = [&[2 as u32], &[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)); @@ -244,7 +244,7 @@ fn test_convert_i64() { None); assert_eq!(BigInt::from_biguint(Minus, - BigUint::new(vec![1, 0, 0, 1 << (big_digit::BITS - 1)])) + BigUint::new(vec![1, 0, 0, 1 << 31])) .to_i64(), None); @@ -458,11 +458,11 @@ fn test_convert_from_uint() { } } - 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!(u8, BigInt::from_slice(Plus, &[u8::MAX as u32])); + check!(u16, BigInt::from_slice(Plus, &[u16::MAX as u32])); + check!(u32, BigInt::from_slice(Plus, &[u32::MAX])); check!(u64, - BigInt::from_slice(Plus, &[u32::MAX as BigDigit, u32::MAX as BigDigit])); + BigInt::from_slice(Plus, &[u32::MAX, u32::MAX])); check!(usize, BigInt::from(usize::MAX as u64)); } @@ -482,16 +482,16 @@ fn test_convert_from_int() { check!(i8, BigInt::from_slice(Minus, &[1 << 7]), - BigInt::from_slice(Plus, &[i8::MAX as BigDigit])); + BigInt::from_slice(Plus, &[i8::MAX as u32])); check!(i16, BigInt::from_slice(Minus, &[1 << 15]), - BigInt::from_slice(Plus, &[i16::MAX as BigDigit])); + BigInt::from_slice(Plus, &[i16::MAX as u32])); check!(i32, BigInt::from_slice(Minus, &[1 << 31]), - BigInt::from_slice(Plus, &[i32::MAX as BigDigit])); + BigInt::from_slice(Plus, &[i32::MAX as u32])); check!(i64, BigInt::from_slice(Minus, &[0, 1 << 31]), - BigInt::from_slice(Plus, &[u32::MAX as BigDigit, i32::MAX as BigDigit])); + BigInt::from_slice(Plus, &[u32::MAX, i32::MAX as u32])); check!(isize, BigInt::from(isize::MIN as i64), BigInt::from(isize::MAX as i64)); diff --git a/tests/bigint_bitwise.rs b/tests/bigint_bitwise.rs index e0df9f37..db60e980 100644 --- a/tests/bigint_bitwise.rs +++ b/tests/bigint_bitwise.rs @@ -1,14 +1,14 @@ extern crate num_bigint; extern crate num_traits; -use num_bigint::{BigDigit, BigInt, Sign, ToBigInt}; +use num_bigint::{BigInt, Sign, ToBigInt}; use num_traits::ToPrimitive; use std::{i32, i64, u32}; enum ValueVec { N, - P(&'static [BigDigit]), - M(&'static [BigDigit]), + P(&'static [u32]), + M(&'static [u32]), } use ValueVec::*; diff --git a/tests/bigint_scalar.rs b/tests/bigint_scalar.rs index bd80f99d..4c2fe83d 100644 --- a/tests/bigint_scalar.rs +++ b/tests/bigint_scalar.rs @@ -1,7 +1,7 @@ extern crate num_bigint; extern crate num_traits; -use num_bigint::{BigDigit, BigInt}; +use num_bigint::BigInt; use num_bigint::Sign::Plus; use num_traits::{Zero, Signed, ToPrimitive}; @@ -88,7 +88,7 @@ fn test_scalar_mul() { #[test] fn test_scalar_div_rem() { - fn check_sub(a: &BigInt, b: BigDigit, ans_q: &BigInt, ans_r: &BigInt) { + fn check_sub(a: &BigInt, b: u32, ans_q: &BigInt, ans_r: &BigInt) { let (q, r) = (a / b, a % b); if !r.is_zero() { assert_eq!(r.sign(), a.sign()); @@ -109,7 +109,7 @@ fn test_scalar_div_rem() { } } - fn check(a: &BigInt, b: BigDigit, q: &BigInt, r: &BigInt) { + fn check(a: &BigInt, b: u32, q: &BigInt, r: &BigInt) { check_sub(a, b, q, r); check_sub(&a.neg(), b, &q.neg(), &r.neg()); } diff --git a/tests/biguint.rs b/tests/biguint.rs index fe2111f5..b62edde3 100644 --- a/tests/biguint.rs +++ b/tests/biguint.rs @@ -4,7 +4,7 @@ extern crate num_traits; extern crate rand; use num_integer::Integer; -use num_bigint::{BigDigit, BigUint, ToBigUint, big_digit}; +use num_bigint::{BigUint, ToBigUint}; use num_bigint::{BigInt, ToBigInt}; use num_bigint::Sign::Plus; @@ -146,19 +146,25 @@ fn test_hash() { 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])]; +// LEFT, RIGHT, AND, OR, XOR +const BIT_TESTS: &'static [( + &'static [u32], + &'static [u32], + &'static [u32], + &'static [u32], + &'static [u32], +)] = &[ + (&[], &[], &[], &[], &[]), + (&[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() { @@ -473,9 +479,9 @@ fn test_convert_i64() { 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![1]), 1); + check(BigUint::new(vec![N1]), (1 << 32) - 1); + check(BigUint::new(vec![0, 1]), 1 << 32); check(BigUint::new(vec![N1, N1 >> 1]), i64::MAX); assert_eq!(i64::MIN.to_biguint(), None); @@ -499,9 +505,9 @@ fn test_convert_u64() { 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![1]), 1); + check(BigUint::new(vec![N1]), (1 << 32) - 1); + check(BigUint::new(vec![0, 1]), 1 << 32); check(BigUint::new(vec![N1, N1]), u64::MAX); assert_eq!(BigUint::new(vec![0, 0, 1]).to_u64(), None); @@ -667,8 +673,8 @@ fn test_convert_from_uint() { } } - check!(u8, BigUint::from_slice(&[u8::MAX as BigDigit])); - check!(u16, BigUint::from_slice(&[u16::MAX as BigDigit])); + check!(u8, BigUint::from_slice(&[u8::MAX as u32])); + check!(u16, BigUint::from_slice(&[u16::MAX as u32])); check!(u32, BigUint::from_slice(&[u32::MAX])); check!(u64, BigUint::from_slice(&[u32::MAX, u32::MAX])); check!(usize, BigUint::from(usize::MAX as u64)); @@ -915,7 +921,7 @@ fn test_is_even() { } fn to_str_pairs() -> Vec<(BigUint, Vec<(u32, String)>)> { - let bits = big_digit::BITS; + let bits = 32; vec![(Zero::zero(), vec![(2, "0".to_string()), (3, "0".to_string())]), (BigUint::from_slice(&[0xff]), diff --git a/tests/consts/mod.rs b/tests/consts/mod.rs index 72ea786c..8b9653ac 100644 --- a/tests/consts/mod.rs +++ b/tests/consts/mod.rs @@ -1,14 +1,12 @@ #![allow(unused)] -use num_bigint::BigDigit; - -pub const N1: BigDigit = -1i32 as BigDigit; -pub const N2: BigDigit = -2i32 as BigDigit; +pub const N1: u32 = -1i32 as u32; +pub const N2: u32 = -2i32 as u32; pub const SUM_TRIPLES: &'static [( - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], + &'static [u32], + &'static [u32], + &'static [u32], )] = &[ (&[], &[], &[]), (&[], &[1], &[1]), @@ -23,9 +21,9 @@ pub const SUM_TRIPLES: &'static [( pub const M: u32 = ::std::u32::MAX; pub const MUL_TRIPLES: &'static [( - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], + &'static [u32], + &'static [u32], + &'static [u32], )] = &[ (&[], &[], &[]), (&[], &[1], &[]), @@ -51,10 +49,10 @@ pub const MUL_TRIPLES: &'static [( ]; pub const DIV_REM_QUADRUPLES: &'static [( - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], - &'static [BigDigit], + &'static [u32], + &'static [u32], + &'static [u32], + &'static [u32], )] = &[ (&[1], &[2], &[], &[1]), (&[3], &[2], &[1], &[1]),