From db29f5fe60d196c36949b5eb042574261e3bd049 Mon Sep 17 00:00:00 2001 From: Sebastien Chapuis Date: Mon, 9 Dec 2024 23:54:03 +0100 Subject: [PATCH 1/6] use tinyvec --- Cargo.toml | 1 + src/bigint.rs | 42 ++++++++++++--------- src/bigint/addition.rs | 16 ++++---- src/bigint/bits.rs | 19 +++++----- src/bigint/convert.rs | 16 ++++---- src/bigint/power.rs | 2 +- src/bigint/subtraction.rs | 16 ++++---- src/bigrand.rs | 7 ++-- src/biguint.rs | 69 +++++++++++++++++++++++++---------- src/biguint/convert.rs | 27 ++++++++------ src/biguint/division.rs | 37 ++++++++++--------- src/biguint/monty.rs | 8 ++-- src/biguint/multiplication.rs | 21 ++++++----- src/biguint/power.rs | 4 +- src/biguint/serde.rs | 10 ++--- src/biguint/shift.rs | 30 ++++++++++----- src/biguint/subtraction.rs | 2 +- src/lib.rs | 16 ++++---- src/macros.rs | 9 +++-- 19 files changed, 206 insertions(+), 146 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 720512a6..4c0d12ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ harness = false name = "shootout-pidigits" [dependencies] +tinyvec = { version = "1", features = [ "alloc" ] } [dependencies.num-integer] version = "0.1.46" diff --git a/src/bigint.rs b/src/bigint.rs index b4f84b9e..6d564fb6 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -3,6 +3,7 @@ use alloc::string::String; use alloc::vec::Vec; +use tinyvec::TinyVec; use core::cmp::Ordering::{self, Equal}; use core::default::Default; use core::fmt; @@ -16,7 +17,7 @@ use num_traits::{ConstZero, Num, One, Pow, Signed, Zero}; use self::Sign::{Minus, NoSign, Plus}; use crate::big_digit::BigDigit; -use crate::biguint::to_str_radix_reversed; +use crate::biguint::{to_str_radix_reversed, NDIGITS}; use crate::biguint::{BigUint, IntDigits, U32Digits, U64Digits}; mod addition; @@ -127,7 +128,7 @@ impl Ord for BigInt { impl Default for BigInt { #[inline] fn default() -> BigInt { - Self::ZERO + Self::zero() } } @@ -206,7 +207,7 @@ impl Not for &BigInt { impl Zero for BigInt { #[inline] fn zero() -> BigInt { - Self::ZERO + Self::zero() } #[inline] @@ -221,10 +222,10 @@ impl Zero for BigInt { } } -impl ConstZero for BigInt { - // forward to the inherent const - const ZERO: Self = Self::ZERO; -} +// impl ConstZero for BigInt { +// // forward to the inherent const +// const ZERO: Self = Self::zero(); +// } impl One for BigInt { #[inline] @@ -259,7 +260,7 @@ impl Signed for BigInt { #[inline] fn abs_sub(&self, other: &BigInt) -> BigInt { if *self <= *other { - Self::ZERO + Self::zero() } else { self - other } @@ -270,7 +271,7 @@ impl Signed for BigInt { match self.sign { Plus => BigInt::one(), Minus => -BigInt::one(), - NoSign => Self::ZERO, + NoSign => Self::zero(), } } @@ -450,7 +451,7 @@ impl Integer for BigInt { fn extended_gcd_lcm(&self, other: &BigInt) -> (num_integer::ExtendedGcd, BigInt) { let egcd = self.extended_gcd(other); let lcm = if egcd.gcd.is_zero() { - Self::ZERO + Self::zero() } else { BigInt::from(&self.data / &egcd.gcd.data * &other.data) }; @@ -534,7 +535,7 @@ impl IntDigits for BigInt { self.data.digits() } #[inline] - fn digits_mut(&mut self) -> &mut Vec { + fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; NDIGITS]> { self.data.digits_mut() } #[inline] @@ -563,11 +564,18 @@ pub trait ToBigInt { } impl BigInt { - /// A constant `BigInt` with value 0, useful for static initialization. - pub const ZERO: Self = BigInt { - sign: NoSign, - data: BigUint::ZERO, - }; + // A constant `BigInt` with value 0, useful for static initialization. + // pub const ZERO: Self = BigInt { + // sign: NoSign, + // data: BigUint::zero(), + // }; + + pub fn zero() -> Self { + Self { + sign: NoSign, + data: BigUint::zero(), + } + } /// Creates and initializes a [`BigInt`]. /// @@ -980,7 +988,7 @@ impl BigInt { pub fn to_biguint(&self) -> Option { match self.sign { Plus => Some(self.data.clone()), - NoSign => Some(BigUint::ZERO), + NoSign => Some(BigUint::zero()), Minus => None, } } diff --git a/src/bigint/addition.rs b/src/bigint/addition.rs index 0d3a0e2a..721d3199 100644 --- a/src/bigint/addition.rs +++ b/src/bigint/addition.rs @@ -24,7 +24,7 @@ macro_rules! bigint_add { (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 => BigInt::ZERO, + Equal => BigInt::zero(), }, } }; @@ -76,7 +76,7 @@ impl Add for BigInt { impl AddAssign<&BigInt> for BigInt { #[inline] fn add_assign(&mut self, other: &BigInt) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n + other; } } @@ -97,7 +97,7 @@ impl Add for BigInt { NoSign => From::from(other), Plus => BigInt::from(self.data + other), Minus => match self.data.cmp(&From::from(other)) { - Equal => Self::ZERO, + Equal => Self::zero(), Less => BigInt::from(other - self.data), Greater => -BigInt::from(self.data - other), }, @@ -108,7 +108,7 @@ impl Add for BigInt { impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u32) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n + other; } } @@ -122,7 +122,7 @@ impl Add for BigInt { NoSign => From::from(other), Plus => BigInt::from(self.data + other), Minus => match self.data.cmp(&From::from(other)) { - Equal => Self::ZERO, + Equal => Self::zero(), Less => BigInt::from(other - self.data), Greater => -BigInt::from(self.data - other), }, @@ -133,7 +133,7 @@ impl Add for BigInt { impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u64) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n + other; } } @@ -147,7 +147,7 @@ impl Add for BigInt { NoSign => BigInt::from(other), Plus => BigInt::from(self.data + other), Minus => match self.data.cmp(&From::from(other)) { - Equal => Self::ZERO, + Equal => Self::zero(), Less => BigInt::from(other - self.data), Greater => -BigInt::from(self.data - other), }, @@ -157,7 +157,7 @@ impl Add for BigInt { impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u128) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n + other; } } diff --git a/src/bigint/bits.rs b/src/bigint/bits.rs index ac4fe1de..bd9e2209 100644 --- a/src/bigint/bits.rs +++ b/src/bigint/bits.rs @@ -2,9 +2,10 @@ use super::BigInt; use super::Sign::{Minus, NoSign, Plus}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; -use crate::biguint::IntDigits; +use crate::biguint::{IntDigits, NDIGITS}; use alloc::vec::Vec; +use tinyvec::TinyVec; use core::cmp::Ordering::{Equal, Greater, Less}; use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; use num_traits::{ToPrimitive, Zero}; @@ -48,7 +49,7 @@ fn bitand_pos_neg(a: &mut [BigDigit], b: &[BigDigit]) { // - 1 & +ff = ...f ff & ...0 ff = ...0 ff = +ff // -ff & + 1 = ...f 01 & ...0 01 = ...0 01 = + 1 // answer is pos, has length of b -fn bitand_neg_pos(a: &mut Vec, b: &[BigDigit]) { +fn bitand_neg_pos(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { let mut carry_a = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { let twos_a = negate_carry(*ai, &mut carry_a); @@ -69,7 +70,7 @@ fn bitand_neg_pos(a: &mut Vec, b: &[BigDigit]) { // -ff & - 1 = ...f 01 & ...f ff = ...f 01 = - ff // -ff & -fe = ...f 01 & ...f 02 = ...f 00 = -100 // answer is neg, has length of longest with a possible carry -fn bitand_neg_neg(a: &mut Vec, b: &[BigDigit]) { +fn bitand_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_b = 1; let mut carry_and = 1; @@ -114,7 +115,7 @@ impl BitAnd<&BigInt> for &BigInt { #[inline] fn bitand(self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { - (NoSign, _) | (_, NoSign) => BigInt::ZERO, + (NoSign, _) | (_, NoSign) => BigInt::zero(), (Plus, Plus) => BigInt::from(&self.data & &other.data), (Plus, Minus) => self.clone() & other, (Minus, Plus) => other.clone() & self, @@ -173,7 +174,7 @@ impl BitAndAssign<&BigInt> for BigInt { // + 1 | -ff = ...0 01 | ...f 01 = ...f 01 = -ff // +ff | - 1 = ...0 ff | ...f ff = ...f ff = - 1 // answer is neg, has length of b -fn bitor_pos_neg(a: &mut Vec, b: &[BigDigit]) { +fn bitor_pos_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { let mut carry_b = 1; let mut carry_or = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { @@ -224,7 +225,7 @@ fn bitor_neg_pos(a: &mut [BigDigit], b: &[BigDigit]) { // - 1 | -ff = ...f ff | ...f 01 = ...f ff = -1 // -ff | - 1 = ...f 01 | ...f ff = ...f ff = -1 // answer is neg, has length of shortest -fn bitor_neg_neg(a: &mut Vec, b: &[BigDigit]) { +fn bitor_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_b = 1; let mut carry_or = 1; @@ -308,7 +309,7 @@ impl BitOrAssign<&BigInt> for BigInt { // + 1 ^ -ff = ...0 01 ^ ...f 01 = ...f 00 = -100 // +ff ^ - 1 = ...0 ff ^ ...f ff = ...f 00 = -100 // answer is neg, has length of longest with a possible carry -fn bitxor_pos_neg(a: &mut Vec, b: &[BigDigit]) { +fn bitxor_pos_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { let mut carry_b = 1; let mut carry_xor = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { @@ -341,7 +342,7 @@ fn bitxor_pos_neg(a: &mut Vec, b: &[BigDigit]) { // - 1 ^ +ff = ...f ff ^ ...0 ff = ...f 00 = -100 // -ff ^ + 1 = ...f 01 ^ ...0 01 = ...f 00 = -100 // answer is neg, has length of longest with a possible carry -fn bitxor_neg_pos(a: &mut Vec, b: &[BigDigit]) { +fn bitxor_neg_pos(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_xor = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { @@ -374,7 +375,7 @@ fn bitxor_neg_pos(a: &mut Vec, b: &[BigDigit]) { // - 1 ^ -ff = ...f ff ^ ...f 01 = ...0 fe = +fe // -ff & - 1 = ...f 01 ^ ...f ff = ...0 fe = +fe // answer is pos, has length of longest -fn bitxor_neg_neg(a: &mut Vec, b: &[BigDigit]) { +fn bitxor_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_b = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { diff --git a/src/bigint/convert.rs b/src/bigint/convert.rs index d0e28b67..ac4481d4 100644 --- a/src/bigint/convert.rs +++ b/src/bigint/convert.rs @@ -227,7 +227,7 @@ impl From for BigInt { data: BigUint::from(n), } } else { - Self::ZERO + Self::zero() } } } @@ -241,7 +241,7 @@ impl From for BigInt { data: BigUint::from(n), } } else { - Self::ZERO + Self::zero() } } } @@ -266,7 +266,7 @@ impl From for BigInt { #[inline] fn from(n: BigUint) -> Self { if n.is_zero() { - Self::ZERO + Self::zero() } else { BigInt { sign: Plus, @@ -287,7 +287,7 @@ impl ToBigInt for BigUint { #[inline] fn to_bigint(&self) -> Option { if self.is_zero() { - Some(BigInt::ZERO) + Some(BigInt::zero()) } else { Some(BigInt { sign: Plus, @@ -302,7 +302,7 @@ impl ToBigUint for BigInt { fn to_biguint(&self) -> Option { match self.sign() { Plus => Some(self.data.clone()), - NoSign => Some(BigUint::ZERO), + NoSign => Some(BigUint::zero()), Minus => None, } } @@ -365,7 +365,7 @@ impl From for BigInt { if x { One::one() } else { - Self::ZERO + Self::zero() } } } @@ -375,7 +375,7 @@ pub(super) 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, + None => return BigInt::zero(), }; if sign == Sign::Minus { @@ -393,7 +393,7 @@ pub(super) 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, + None => return BigInt::zero(), }; if sign == Sign::Minus { diff --git a/src/bigint/power.rs b/src/bigint/power.rs index ef254c89..4b41f4f2 100644 --- a/src/bigint/power.rs +++ b/src/bigint/power.rs @@ -80,7 +80,7 @@ pub(super) fn modpow(x: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt let result = x.data.modpow(&exponent.data, &modulus.data); if result.is_zero() { - return BigInt::ZERO; + return BigInt::zero(); } // The sign of the result follows the modulus, like `mod_floor`. diff --git a/src/bigint/subtraction.rs b/src/bigint/subtraction.rs index ef778549..1fb240d8 100644 --- a/src/bigint/subtraction.rs +++ b/src/bigint/subtraction.rs @@ -23,7 +23,7 @@ macro_rules! bigint_sub { (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 => BigInt::ZERO, + Equal => BigInt::zero(), }, } }; @@ -75,7 +75,7 @@ impl Sub for BigInt { impl SubAssign<&BigInt> for BigInt { #[inline] fn sub_assign(&mut self, other: &BigInt) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n - other; } } @@ -96,7 +96,7 @@ impl Sub for BigInt { NoSign => -BigInt::from(other), Minus => -BigInt::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { - Equal => Self::ZERO, + Equal => Self::zero(), Greater => BigInt::from(self.data - other), Less => -BigInt::from(other - self.data), }, @@ -106,7 +106,7 @@ impl Sub for BigInt { impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u32) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n - other; } } @@ -147,7 +147,7 @@ impl Sub for BigInt { NoSign => -BigInt::from(other), Minus => -BigInt::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { - Equal => Self::ZERO, + Equal => Self::zero(), Greater => BigInt::from(self.data - other), Less => -BigInt::from(other - self.data), }, @@ -158,7 +158,7 @@ impl Sub for BigInt { impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u64) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n - other; } } @@ -172,7 +172,7 @@ impl Sub for BigInt { NoSign => -BigInt::from(other), Minus => -BigInt::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { - Equal => Self::ZERO, + Equal => Self::zero(), Greater => BigInt::from(self.data - other), Less => -BigInt::from(other - self.data), }, @@ -183,7 +183,7 @@ impl Sub for BigInt { impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u128) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n - other; } } diff --git a/src/bigrand.rs b/src/bigrand.rs index e5cbacdb..29e0b046 100644 --- a/src/bigrand.rs +++ b/src/bigrand.rs @@ -9,7 +9,7 @@ use crate::BigInt; use crate::BigUint; use crate::Sign::*; -use crate::biguint::biguint_from_vec; +use crate::biguint::biguint_from_tinyvec; use num_integer::Integer; use num_traits::{ToPrimitive, Zero}; @@ -69,7 +69,8 @@ impl RandBigInt for R { .expect("capacity overflow"); let native_digits = Integer::div_ceil(&bit_size, &64); let native_len = native_digits.to_usize().expect("capacity overflow"); - let mut data = vec![0u64; native_len]; + let mut data = tinyvec::TinyVec::new(); + // let mut data = vec![0u64; native_len]; unsafe { // Generate bits in a `&mut [u32]` slice for value stability let ptr = data.as_mut_ptr() as *mut u32; @@ -82,7 +83,7 @@ impl RandBigInt for R { // swap u32 digits into u64 endianness *digit = (*digit << 32) | (*digit >> 32); } - biguint_from_vec(data) + biguint_from_tinyvec(data) } ); diff --git a/src/biguint.rs b/src/biguint.rs index 196fa323..2e63d01b 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2,6 +2,9 @@ use crate::big_digit::{self, BigDigit}; use alloc::string::String; use alloc::vec::Vec; +use tinyvec::tiny_vec; +use tinyvec::ArrayVec; +use tinyvec::TinyVec; use core::cmp; use core::cmp::Ordering; use core::default::Default; @@ -30,11 +33,28 @@ mod shift; pub(crate) use self::convert::to_str_radix_reversed; pub use self::iter::{U32Digits, U64Digits}; +pub const NDIGITS: usize = 32; + /// A big unsigned integer type. -pub struct BigUint { - data: Vec, +pub struct BigUint { + data: TinyVec<[u64; N]>, } +// impl Drop for BigUint { +// fn drop(&mut self) { +// if self.data.capacity() > NDIGITS { +// eprintln!("len={:?}", self.data.capacity()); +// } +// } +// } + +// impl BigUint { +// pub fn take_data(self) -> TinyVec<[u64; NDIGITS]> { +// let Self { data } = self; +// data +// } +// } + // Note: derived `Clone` doesn't specialize `clone_from`, // but we want to keep the allocation in `data`. impl Clone for BigUint { @@ -97,7 +117,7 @@ fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { impl Default for BigUint { #[inline] fn default() -> BigUint { - Self::ZERO + Self::zero() } } @@ -142,7 +162,7 @@ impl fmt::Octal for BigUint { impl Zero for BigUint { #[inline] fn zero() -> BigUint { - Self::ZERO + Self::zero() } #[inline] @@ -156,15 +176,15 @@ impl Zero for BigUint { } } -impl ConstZero for BigUint { - // forward to the inherent const - const ZERO: Self = Self::ZERO; // BigUint { data: Vec::new() }; -} +// impl ConstZero for BigUint { +// // forward to the inherent const +// const ZERO: Self = Self::ZERO; // BigUint { data: Vec::new() }; +// } impl One for BigUint { #[inline] fn one() -> BigUint { - BigUint { data: vec![1] } + BigUint { data: tiny_vec![1] } } #[inline] @@ -256,7 +276,7 @@ impl Integer for BigUint { #[inline] fn lcm(&self, other: &BigUint) -> BigUint { if self.is_zero() && other.is_zero() { - Self::ZERO + Self::zero() } else { self / self.gcd(other) * other } @@ -268,7 +288,7 @@ impl Integer for BigUint { fn gcd_lcm(&self, other: &Self) -> (Self, Self) { let gcd = self.gcd(other); let lcm = if gcd.is_zero() { - Self::ZERO + Self::zero() } else { self / &gcd * other }; @@ -522,21 +542,30 @@ pub trait ToBigUint { /// Creates and initializes a [`BigUint`]. /// /// The digits are in little-endian base matching `BigDigit`. +// #[inline] +// pub(crate) fn biguint_from_vec(digits: Vec) -> BigUint { +// BigUint { data: digits.into_iter().collect() }.normalized() +// } + #[inline] -pub(crate) fn biguint_from_vec(digits: Vec) -> BigUint { +pub(crate) fn biguint_from_tinyvec(digits: TinyVec<[BigDigit; NDIGITS]>) -> BigUint { BigUint { data: digits }.normalized() } impl BigUint { - /// A constant `BigUint` with value 0, useful for static initialization. - pub const ZERO: Self = BigUint { data: Vec::new() }; + pub fn zero() -> Self { + BigUint { data: [].into_iter().collect() } + } + + // /// A constant `BigUint` with value 0, useful for static initialization. + // pub const ZERO: Self = BigUint { data: TinyVec::Inline(ArrayVec::from_array_empty([0; 8])) }; /// Creates and initializes a [`BigUint`]. /// /// The base 232 digits are ordered least significant digit first. #[inline] pub fn new(digits: Vec) -> BigUint { - let mut big = Self::ZERO; + let mut big = Self::zero(); cfg_digit_expr!( { @@ -554,7 +583,7 @@ impl BigUint { /// The base 232 digits are ordered least significant digit first. #[inline] pub fn from_slice(slice: &[u32]) -> BigUint { - let mut big = Self::ZERO; + let mut big = Self::zero(); big.assign_from_slice(slice); big } @@ -595,7 +624,7 @@ impl BigUint { #[inline] pub fn from_bytes_be(bytes: &[u8]) -> BigUint { if bytes.is_empty() { - Self::ZERO + Self::zero() } else { let mut v = bytes.to_vec(); v.reverse(); @@ -609,7 +638,7 @@ impl BigUint { #[inline] pub fn from_bytes_le(bytes: &[u8]) -> BigUint { if bytes.is_empty() { - Self::ZERO + Self::zero() } else { convert::from_bitwise_digits_le(bytes, 8) } @@ -1070,7 +1099,7 @@ impl num_traits::ToBytes for BigUint { pub(crate) trait IntDigits { fn digits(&self) -> &[BigDigit]; - fn digits_mut(&mut self) -> &mut Vec; + fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; NDIGITS]>; fn normalize(&mut self); fn capacity(&self) -> usize; fn len(&self) -> usize; @@ -1082,7 +1111,7 @@ impl IntDigits for BigUint { &self.data } #[inline] - fn digits_mut(&mut self) -> &mut Vec { + fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; NDIGITS]> { &mut self.data } #[inline] diff --git a/src/biguint/convert.rs b/src/biguint/convert.rs index 3daf3dcb..5b783929 100644 --- a/src/biguint/convert.rs +++ b/src/biguint/convert.rs @@ -1,7 +1,7 @@ // This uses stdlib features higher than the MSRV #![allow(clippy::manual_range_contains)] // 1.35 -use super::{biguint_from_vec, BigUint, ToBigUint}; +use super::{biguint_from_tinyvec, BigUint, ToBigUint}; use super::addition::add2; use super::division::{div_rem_digit, FAST_DIV_WIDE}; @@ -12,6 +12,7 @@ use crate::ParseBigIntError; use crate::TryFromBigIntError; use alloc::vec::Vec; +use tinyvec::TinyVec; use core::cmp::Ordering::{Equal, Greater, Less}; use core::convert::TryFrom; use core::mem; @@ -57,7 +58,7 @@ pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { }) .collect(); - biguint_from_vec(data) + biguint_from_tinyvec(data) } // Convert from a power of two radix (bits == ilog2(radix)) where bits doesn't evenly divide @@ -70,7 +71,8 @@ fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { let big_digits = Integer::div_ceil(&total_bits, &big_digit::BITS.into()) .to_usize() .unwrap_or(usize::MAX); - let mut data = Vec::with_capacity(big_digits); + let mut data = TinyVec::new(); + // let mut data = Vec::with_capacity(big_digits); let mut d = 0; let mut dbits = 0; // number of bits we currently have in d @@ -95,7 +97,7 @@ fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { data.push(d as BigDigit); } - biguint_from_vec(data) + biguint_from_tinyvec(data) } // Read little-endian radix digits @@ -117,7 +119,8 @@ fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { (bits / big_digit::BITS as usize) + 1 }; - let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0)); + let mut data = TinyVec::new(); + // let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0)); let (base, power) = get_radix_base(radix); let radix = radix as BigDigit; @@ -149,7 +152,7 @@ fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { add2(&mut data, &[n]); } - biguint_from_vec(data) + biguint_from_tinyvec(data) } pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option { @@ -159,7 +162,7 @@ pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option { ); if buf.is_empty() { - return Some(BigUint::ZERO); + return Some(BigUint::zero()); } if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { @@ -190,7 +193,7 @@ pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option { ); if buf.is_empty() { - return Some(BigUint::ZERO); + return Some(BigUint::zero()); } if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { @@ -468,7 +471,7 @@ impl FromPrimitive for BigUint { // handle 0.x, -0.x if n.is_zero() { - return Some(Self::ZERO); + return Some(Self::zero()); } let (mantissa, exponent, sign) = FloatCore::integer_decode(n); @@ -490,7 +493,7 @@ impl FromPrimitive for BigUint { impl From for BigUint { #[inline] fn from(mut n: u64) -> Self { - let mut ret: BigUint = Self::ZERO; + let mut ret: BigUint = Self::zero(); while n != 0 { ret.data.push(n as BigDigit); @@ -505,7 +508,7 @@ impl From for BigUint { impl From for BigUint { #[inline] fn from(mut n: u128) -> Self { - let mut ret: BigUint = Self::ZERO; + let mut ret: BigUint = Self::zero(); while n != 0 { ret.data.push(n as BigDigit); @@ -592,7 +595,7 @@ impl From for BigUint { if x { One::one() } else { - Self::ZERO + Self::zero() } } } diff --git a/src/biguint/division.rs b/src/biguint/division.rs index 3dfb0bbb..5a633fbb 100644 --- a/src/biguint/division.rs +++ b/src/biguint/division.rs @@ -163,12 +163,12 @@ fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { panic!("attempt to divide by zero") } if u.is_zero() { - return (BigUint::ZERO, BigUint::ZERO); + return (BigUint::zero(), BigUint::zero()); } if d.data.len() == 1 { - if d.data == [1] { - return (u, BigUint::ZERO); + if *d.data == [1] { + return (u, BigUint::zero()); } let (div, rem) = div_rem_digit(u, d.data[0]); // reuse d @@ -179,10 +179,10 @@ fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { // Required or the q_len calculation below can underflow: match u.cmp(&d) { - Less => return (BigUint::ZERO, u), + Less => return (BigUint::zero(), u), Equal => { u.set_one(); - return (u, BigUint::ZERO); + return (u, BigUint::zero()); } Greater => {} // Do nothing } @@ -205,17 +205,20 @@ fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { } } + pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { if d.is_zero() { panic!("attempt to divide by zero") } if u.is_zero() { - return (BigUint::ZERO, BigUint::ZERO); + return (BigUint::zero(), BigUint::zero()); } + assert!(u.data.is_inline(), "u.data.len={:?} u={:?}", u.data.len(), u); + if d.data.len() == 1 { - if d.data == [1] { - return (u.clone(), BigUint::ZERO); + if *d.data == [1] { + return (u.clone(), BigUint::zero()); } let (div, rem) = div_rem_digit(u.clone(), d.data[0]); @@ -224,8 +227,8 @@ pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { // Required or the q_len calculation below can underflow: match u.cmp(d) { - Less => return (BigUint::ZERO, u.clone()), - Equal => return (One::one(), BigUint::ZERO), + Less => return (BigUint::zero(), u.clone()), + Equal => return (One::one(), BigUint::zero()), Greater => {} // Do nothing } @@ -279,7 +282,7 @@ fn div_rem_core(mut a: BigUint, b: &[BigDigit]) -> (BigUint, BigUint) { let q_len = a.data.len() - b.len() + 1; let mut q = BigUint { - data: vec![0; q_len], + data: core::iter::repeat(0).take(q_len).collect(), }; for j in (0..q_len).rev() { @@ -402,7 +405,7 @@ impl Div for u32 { match other.data.len() { 0 => panic!("attempt to divide by zero"), 1 => From::from(self as BigDigit / other.data[0]), - _ => BigUint::ZERO, + _ => BigUint::zero(), } } } @@ -420,7 +423,7 @@ impl DivAssign for BigUint { #[inline] fn div_assign(&mut self, other: u64) { // a vec of size 0 does not allocate, so this is fairly cheap - let temp = mem::replace(self, Self::ZERO); + let temp = mem::replace(self, Self::zero()); *self = temp / other; } } @@ -435,7 +438,7 @@ impl Div for u64 { 0 => panic!("attempt to divide by zero"), 1 => From::from(self / u64::from(other.data[0])), 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), - _ => BigUint::ZERO, + _ => BigUint::zero(), } } @@ -444,7 +447,7 @@ impl Div for u64 { match other.data.len() { 0 => panic!("attempt to divide by zero"), 1 => From::from(self / other.data[0]), - _ => BigUint::ZERO, + _ => BigUint::zero(), } } ); @@ -484,7 +487,7 @@ impl Div for u128 { 4 => From::from( self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]), ), - _ => BigUint::ZERO, + _ => BigUint::zero(), } } @@ -494,7 +497,7 @@ impl Div for u128 { 0 => panic!("attempt to divide by zero"), 1 => From::from(self / other.data[0] as u128), 2 => From::from(self / big_digit::to_doublebigdigit(other.data[1], other.data[0])), - _ => BigUint::ZERO, + _ => BigUint::zero(), } } ); diff --git a/src/biguint/monty.rs b/src/biguint/monty.rs index a0b26b54..da53fb2c 100644 --- a/src/biguint/monty.rs +++ b/src/biguint/monty.rs @@ -57,7 +57,7 @@ fn montgomery(x: &BigUint, y: &BigUint, m: &BigUint, k: BigDigit, n: usize) -> B n ); - let mut z = BigUint::ZERO; + let mut z = BigUint::zero(); z.data.resize(n * 2, 0); let mut c: BigDigit = 0; @@ -76,13 +76,13 @@ fn montgomery(x: &BigUint, y: &BigUint, m: &BigUint, k: BigDigit, n: usize) -> B } if c == 0 { - z.data = z.data[n..].to_vec(); + z.data = z.data[n..].into_iter().copied().collect(); } else { { let (first, second) = z.data.split_at_mut(n); sub_vv(first, second, &m.data); } - z.data = z.data[..n].to_vec(); + z.data = z.data[..n].into_iter().copied().collect(); } z @@ -174,7 +174,7 @@ pub(super) fn monty_modpow(x: &BigUint, y: &BigUint, m: &BigUint) -> BigUint { // initialize z = 1 (Montgomery 1) let mut z = powers[0].clone(); z.data.resize(num_words, 0); - let mut zz = BigUint::ZERO; + let mut zz = BigUint::zero(); zz.data.resize(num_words, 0); // same windowed exponent, but with Montgomery multiplications diff --git a/src/biguint/multiplication.rs b/src/biguint/multiplication.rs index e9d21384..7a50a75f 100644 --- a/src/biguint/multiplication.rs +++ b/src/biguint/multiplication.rs @@ -1,6 +1,6 @@ use super::addition::{__add2, add2}; use super::subtraction::sub2; -use super::{biguint_from_vec, cmp_slice, BigUint, IntDigits}; +use super::{biguint_from_tinyvec, cmp_slice, BigUint, IntDigits}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; use crate::Sign::{self, Minus, NoSign, Plus}; @@ -10,6 +10,7 @@ use core::cmp::Ordering; use core::iter::Product; use core::ops::{Mul, MulAssign}; use num_traits::{CheckedMul, FromPrimitive, One, Zero}; +use tinyvec::{tiny_vec, TinyVec}; #[inline] pub(super) fn mac_with_carry( @@ -58,7 +59,7 @@ fn mac_digit(acc: &mut [BigDigit], b: &[BigDigit], c: BigDigit) { } fn bigint_from_slice(slice: &[BigDigit]) -> BigInt { - BigInt::from(biguint_from_vec(slice.to_vec())) + BigInt::from(biguint_from_tinyvec(slice.iter().copied().collect())) } /// Three argument multiply accumulate: @@ -233,7 +234,7 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { // 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] }; + let mut p = BigUint { data: core::iter::repeat(0).take(len).collect() }; // p2 = x1 * y1 mac3(&mut p.data, x1, y1); @@ -409,7 +410,7 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { let len = x.len() + y.len() + 1; - let mut prod = BigUint { data: vec![0; len] }; + let mut prod = BigUint { data: core::iter::repeat(0).take(len).collect() }; mac3(&mut prod.data, x, y); prod.normalized() @@ -446,16 +447,16 @@ fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { match cmp_slice(a, b) { Ordering::Greater => { - let mut a = a.to_vec(); + let mut a: TinyVec<_> = a.iter().copied().collect(); sub2(&mut a, b); - (Plus, biguint_from_vec(a)) + (Plus, biguint_from_tinyvec(a)) } Ordering::Less => { - let mut b = b.to_vec(); + let mut b: TinyVec<_> = b.iter().copied().collect(); sub2(&mut b, a); - (Minus, biguint_from_vec(b)) + (Minus, biguint_from_tinyvec(b)) } - Ordering::Equal => (NoSign, BigUint::ZERO), + Ordering::Equal => (NoSign, BigUint::zero()), } } @@ -468,7 +469,7 @@ macro_rules! impl_mul { fn mul(self, other: $Other) -> BigUint { match (&*self.data, &*other.data) { // multiply by zero - (&[], _) | (_, &[]) => BigUint::ZERO, + (&[], _) | (_, &[]) => BigUint::zero(), // multiply by a scalar (_, &[digit]) => self * digit, (&[digit], _) => other * digit, diff --git a/src/biguint/power.rs b/src/biguint/power.rs index fa1c4926..c6e5efa5 100644 --- a/src/biguint/power.rs +++ b/src/biguint/power.rs @@ -14,7 +14,7 @@ impl Pow<&BigUint> for BigUint { if self.is_one() || exp.is_zero() { BigUint::one() } else if self.is_zero() { - Self::ZERO + Self::zero() } else if let Some(exp) = exp.to_u64() { self.pow(exp) } else if let Some(exp) = exp.to_u128() { @@ -44,7 +44,7 @@ impl Pow<&BigUint> for &BigUint { if self.is_one() || exp.is_zero() { BigUint::one() } else if self.is_zero() { - BigUint::ZERO + BigUint::zero() } else { self.clone().pow(exp) } diff --git a/src/biguint/serde.rs b/src/biguint/serde.rs index 84bdf505..9ea4aeef 100644 --- a/src/biguint/serde.rs +++ b/src/biguint/serde.rs @@ -1,7 +1,7 @@ #![cfg(feature = "serde")] #![cfg_attr(docsrs, doc(cfg(feature = "serde")))] -use super::{biguint_from_vec, BigUint}; +use super::{biguint_from_tinyvec, BigUint}; use alloc::vec::Vec; use core::{cmp, fmt, mem}; @@ -84,13 +84,13 @@ impl<'de> Visitor<'de> for U32Visitor { S: SeqAccess<'de>, { let len = cautious(seq.size_hint()); - let mut data = Vec::with_capacity(len); + let mut data = tinyvec::TinyVec::new(); while let Some(value) = seq.next_element::()? { data.push(value); } - Ok(biguint_from_vec(data)) + Ok(biguint_from_tinyvec(data)) } fn visit_seq(self, mut seq: S) -> Result @@ -102,7 +102,7 @@ impl<'de> Visitor<'de> for U32Visitor { let u32_len = cautious(seq.size_hint()); let len = Integer::div_ceil(&u32_len, &2); - let mut data = Vec::with_capacity(len); + let mut data = tinyvec::TinyVec::new(); while let Some(lo) = seq.next_element::()? { let mut value = BigDigit::from(lo); @@ -115,7 +115,7 @@ impl<'de> Visitor<'de> for U32Visitor { } } - Ok(biguint_from_vec(data)) + Ok(biguint_from_tinyvec(data)) } ); } diff --git a/src/biguint/shift.rs b/src/biguint/shift.rs index 51483cd0..422bf2cf 100644 --- a/src/biguint/shift.rs +++ b/src/biguint/shift.rs @@ -1,9 +1,10 @@ -use super::{biguint_from_vec, BigUint}; +use super::{biguint_from_tinyvec, BigUint}; use crate::big_digit; use alloc::borrow::Cow; use alloc::vec::Vec; +use tinyvec::TinyVec; use core::mem; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use num_traits::{PrimInt, Zero}; @@ -27,9 +28,9 @@ fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { 0 => n.into_owned().data, _ => { let len = digits.saturating_add(n.data.len() + 1); - let mut data = Vec::with_capacity(len); + let mut data = TinyVec::with_capacity(len); data.resize(digits, 0); - data.extend(n.data.iter()); + data.extend(n.data.iter().copied()); data } }; @@ -47,7 +48,7 @@ fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { } } - biguint_from_vec(data) + biguint_from_tinyvec(data) } #[inline] @@ -70,10 +71,18 @@ fn biguint_shr2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { n.set_zero(); return n; } + let n_data_len = n.data.len(); + // if n.data.len() > 6 { + // eprintln!("{:?}", n.data.len()); + // } + // dbg!(n.data.len()); let mut data = match n { - Cow::Borrowed(n) => n.data[digits..].to_vec(), + Cow::Borrowed(n) => n.data[digits..].into_iter().copied().collect(), Cow::Owned(mut n) => { - n.data.drain(..digits); + if digits != 0 { + // eprintln!("draining digits={:?}", digits); + n.data.drain(..digits); + } n.data } }; @@ -88,7 +97,10 @@ fn biguint_shr2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { } } - biguint_from_vec(data) + // if n_data_len > 6 || data.len() > 6 { + // eprintln!("n.data={:?} data={:?}", n_data_len, data.len()); + // } + biguint_from_tinyvec(data) } macro_rules! impl_shift { @@ -136,7 +148,7 @@ macro_rules! impl_shift { impl ShlAssign<$rhs> for BigUint { #[inline] fn shl_assign(&mut self, rhs: $rhs) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n << rhs; } } @@ -161,7 +173,7 @@ macro_rules! impl_shift { impl ShrAssign<$rhs> for BigUint { #[inline] fn shr_assign(&mut self, rhs: $rhs) { - let n = mem::replace(self, Self::ZERO); + let n = mem::replace(self, Self::zero()); *self = n >> rhs; } } diff --git a/src/biguint/subtraction.rs b/src/biguint/subtraction.rs index 47a5015f..b1c036d8 100644 --- a/src/biguint/subtraction.rs +++ b/src/biguint/subtraction.rs @@ -305,7 +305,7 @@ impl CheckedSub for BigUint { fn checked_sub(&self, v: &BigUint) -> Option { match self.cmp(v) { Less => None, - Equal => Some(Self::ZERO), + Equal => Some(Self::zero()), Greater => Some(self.sub(v)), } } diff --git a/src/lib.rs b/src/lib.rs index 6e47479d..086afc09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,12 +98,12 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![doc(html_root_url = "https://docs.rs/num-bigint/0.4")] #![warn(rust_2018_idioms)] -#![no_std] +// #![no_std] #[macro_use] extern crate alloc; -#[cfg(feature = "std")] +// #[cfg(feature = "std")] extern crate std; use core::fmt; @@ -115,14 +115,14 @@ mod bigint; mod bigrand; mod biguint; -#[cfg(target_pointer_width = "32")] -type UsizePromotion = u32; -#[cfg(target_pointer_width = "64")] +// #[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")] +// #[cfg(target_pointer_width = "32")] +// type IsizePromotion = i32; +// #[cfg(target_pointer_width = "64")] type IsizePromotion = i64; #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/macros.rs b/src/macros.rs index f2e21e3b..4b3d8829 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -14,20 +14,21 @@ macro_rules! cfg_32_or_test { macro_rules! cfg_64 { ($($any:tt)+) => { - #[cfg(target_pointer_width = "64")] $($any)+ + $($any)+ + // #[cfg(target_pointer_width = "64")] $($any)+ } } macro_rules! cfg_digit { ($item32:item $item64:item) => { - cfg_32!($item32); + // cfg_32!($item32); cfg_64!($item64); }; } macro_rules! cfg_digit_expr { ($expr32:expr, $expr64:expr) => { - cfg_32!($expr32); + // cfg_32!($expr32); cfg_64!($expr64); }; } @@ -450,7 +451,7 @@ macro_rules! impl_sum_iter_type { where I: Iterator, { - iter.fold(Self::ZERO, <$res>::add) + iter.fold(Self::zero(), <$res>::add) } } }; From a2cb032defb0de105db516cd70fb2e9d4fc8a9bc Mon Sep 17 00:00:00 2001 From: Sebastien Chapuis Date: Tue, 10 Dec 2024 17:43:22 +0100 Subject: [PATCH 2/6] Allocate numbers on stack by default --- Cargo.toml | 2 +- src/bigint.rs | 162 ++++++++++++---------- src/bigint/addition.rs | 123 +++++++++-------- src/bigint/bits.rs | 85 ++++++------ src/bigint/convert.rs | 102 +++++++++----- src/bigint/division.rs | 250 +++++++++++++++++----------------- src/bigint/multiplication.rs | 166 ++++++++++++---------- src/bigint/power.rs | 40 +++--- src/bigint/shift.rs | 48 +++---- src/bigint/subtraction.rs | 150 ++++++++++---------- src/biguint.rs | 159 +++++++++++---------- src/biguint/addition.rs | 54 ++++---- src/biguint/arbitrary.rs | 4 +- src/biguint/bits.rs | 52 +++---- src/biguint/convert.rs | 94 ++++++------- src/biguint/division.rs | 202 ++++++++++++++------------- src/biguint/monty.rs | 16 ++- src/biguint/multiplication.rs | 185 ++++++++++++++----------- src/biguint/power.rs | 64 +++++---- src/biguint/shift.rs | 93 ++++++------- src/biguint/subtraction.rs | 84 ++++++------ src/macros.rs | 50 +++---- 22 files changed, 1150 insertions(+), 1035 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4c0d12ca..42f005e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ harness = false name = "shootout-pidigits" [dependencies] -tinyvec = { version = "1", features = [ "alloc" ] } +tinyvec = { version = "1", features = [ "alloc", "rustc_1_55" ] } [dependencies.num-integer] version = "0.1.46" diff --git a/src/bigint.rs b/src/bigint.rs index 6d564fb6..083624e8 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -3,22 +3,22 @@ use alloc::string::String; use alloc::vec::Vec; -use tinyvec::TinyVec; use core::cmp::Ordering::{self, Equal}; use core::default::Default; use core::fmt; use core::hash; use core::ops::{Neg, Not}; use core::str; +use tinyvec::TinyVec; use num_integer::{Integer, Roots}; -use num_traits::{ConstZero, Num, One, Pow, Signed, Zero}; +use num_traits::{Num, One, Pow, Signed, Zero}; use self::Sign::{Minus, NoSign, Plus}; use crate::big_digit::BigDigit; -use crate::biguint::{to_str_radix_reversed, NDIGITS}; -use crate::biguint::{BigUint, IntDigits, U32Digits, U64Digits}; +use crate::biguint::{to_str_radix_reversed, NLIMBS}; +use crate::biguint::{BigUint, U32Digits, U64Digits}; mod addition; mod division; @@ -54,15 +54,24 @@ impl Neg for Sign { } } +impl BigInt { + pub fn to_digits(&self) -> BigInt { + BigInt { + sign: self.sign, + data: self.data.to_digits(), + } + } +} + /// A big signed integer type. -pub struct BigInt { +pub struct BigInt { sign: Sign, - data: BigUint, + data: BigUint, } // Note: derived `Clone` doesn't specialize `clone_from`, // but we want to keep the allocation in `data`. -impl Clone for BigInt { +impl Clone for BigInt { #[inline] fn clone(&self) -> Self { BigInt { @@ -78,7 +87,7 @@ impl Clone for BigInt { } } -impl hash::Hash for BigInt { +impl hash::Hash for BigInt { #[inline] fn hash(&self, state: &mut H) { debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); @@ -89,27 +98,27 @@ impl hash::Hash for BigInt { } } -impl PartialEq for BigInt { +impl PartialEq for BigInt { #[inline] - fn eq(&self, other: &BigInt) -> bool { + fn eq(&self, other: &BigInt) -> bool { debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); debug_assert!((other.sign != NoSign) ^ other.data.is_zero()); self.sign == other.sign && (self.sign == NoSign || self.data == other.data) } } -impl Eq for BigInt {} +impl Eq for BigInt {} -impl PartialOrd for BigInt { +impl PartialOrd for BigInt { #[inline] - fn partial_cmp(&self, other: &BigInt) -> Option { + fn partial_cmp(&self, other: &BigInt) -> Option { Some(self.cmp(other)) } } -impl Ord for BigInt { +impl Ord for BigInt { #[inline] - fn cmp(&self, other: &BigInt) -> Ordering { + fn cmp(&self, other: &BigInt) -> Ordering { debug_assert!((self.sign != NoSign) ^ self.data.is_zero()); debug_assert!((other.sign != NoSign) ^ other.data.is_zero()); let scmp = self.sign.cmp(&other.sign); @@ -125,20 +134,20 @@ impl Ord for BigInt { } } -impl Default for BigInt { +impl Default for BigInt { #[inline] - fn default() -> BigInt { + fn default() -> BigInt { Self::zero() } } -impl fmt::Debug for BigInt { +impl fmt::Debug for BigInt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } -impl fmt::Display for BigInt { +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)) } @@ -174,10 +183,10 @@ impl fmt::UpperHex for BigInt { // !-1 = !...f ff = ...0 00 = 0 // ! 0 = !...0 00 = ...f ff = -1 // !+1 = !...0 01 = ...f fe = -2 -impl Not for BigInt { - type Output = BigInt; +impl Not for BigInt { + type Output = BigInt; - fn not(mut self) -> BigInt { + fn not(mut self) -> BigInt { match self.sign { NoSign | Plus => { self.data += 1u32; @@ -192,10 +201,10 @@ impl Not for BigInt { } } -impl Not for &BigInt { - type Output = BigInt; +impl Not for &BigInt { + type Output = BigInt; - fn not(self) -> BigInt { + fn not(self) -> BigInt { match self.sign { NoSign => -BigInt::one(), Plus => -BigInt::from(&self.data + 1u32), @@ -204,9 +213,9 @@ impl Not for &BigInt { } } -impl Zero for BigInt { +impl Zero for BigInt { #[inline] - fn zero() -> BigInt { + fn zero() -> BigInt { Self::zero() } @@ -227,9 +236,9 @@ impl Zero for BigInt { // const ZERO: Self = Self::zero(); // } -impl One for BigInt { +impl One for BigInt { #[inline] - fn one() -> BigInt { + fn one() -> BigInt { BigInt { sign: Plus, data: BigUint::one(), @@ -248,9 +257,9 @@ impl One for BigInt { } } -impl Signed for BigInt { +impl Signed for BigInt { #[inline] - fn abs(&self) -> BigInt { + fn abs(&self) -> BigInt { match self.sign { Plus | NoSign => self.clone(), Minus => BigInt::from(self.data.clone()), @@ -258,7 +267,7 @@ impl Signed for BigInt { } #[inline] - fn abs_sub(&self, other: &BigInt) -> BigInt { + fn abs_sub(&self, other: &BigInt) -> BigInt { if *self <= *other { Self::zero() } else { @@ -267,7 +276,7 @@ impl Signed for BigInt { } #[inline] - fn signum(&self) -> BigInt { + fn signum(&self) -> BigInt { match self.sign { Plus => BigInt::one(), Minus => -BigInt::one(), @@ -321,28 +330,28 @@ impl_unsigned_abs!(i64, u64); impl_unsigned_abs!(i128, u128); impl_unsigned_abs!(isize, usize); -impl Neg for BigInt { - type Output = BigInt; +impl Neg for BigInt { + type Output = BigInt; #[inline] - fn neg(mut self) -> BigInt { + fn neg(mut self) -> BigInt { self.sign = -self.sign; self } } -impl Neg for &BigInt { - type Output = BigInt; +impl Neg for &BigInt { + type Output = BigInt; #[inline] - fn neg(self) -> BigInt { + fn neg(self) -> BigInt { -self.clone() } } -impl Integer for BigInt { +impl Integer for BigInt { #[inline] - fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { + fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { // r.sign == self.sign let (d_ui, r_ui) = self.data.div_rem(&other.data); let d = BigInt::from_biguint(self.sign, d_ui); @@ -355,7 +364,7 @@ impl Integer for BigInt { } #[inline] - fn div_floor(&self, other: &BigInt) -> BigInt { + fn div_floor(&self, other: &BigInt) -> BigInt { let (d_ui, m) = self.data.div_mod_floor(&other.data); let d = BigInt::from(d_ui); match (self.sign, other.sign) { @@ -372,7 +381,7 @@ impl Integer for BigInt { } #[inline] - fn mod_floor(&self, other: &BigInt) -> BigInt { + fn mod_floor(&self, other: &BigInt) -> BigInt { // m.sign == other.sign let m_ui = self.data.mod_floor(&other.data); let m = BigInt::from_biguint(other.sign, m_ui); @@ -389,7 +398,7 @@ impl Integer for BigInt { } } - fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { + fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { // m.sign == other.sign let (d_ui, m_ui) = self.data.div_mod_floor(&other.data); let d = BigInt::from(d_ui); @@ -428,27 +437,30 @@ impl Integer for BigInt { /// /// The result is always positive. #[inline] - fn gcd(&self, other: &BigInt) -> BigInt { + fn gcd(&self, other: &BigInt) -> BigInt { BigInt::from(self.data.gcd(&other.data)) } /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] - fn lcm(&self, other: &BigInt) -> BigInt { + fn lcm(&self, other: &BigInt) -> BigInt { BigInt::from(self.data.lcm(&other.data)) } /// Calculates the Greatest Common Divisor (GCD) and /// Lowest Common Multiple (LCM) together. #[inline] - fn gcd_lcm(&self, other: &BigInt) -> (BigInt, BigInt) { + fn gcd_lcm(&self, other: &BigInt) -> (BigInt, BigInt) { let (gcd, lcm) = self.data.gcd_lcm(&other.data); (BigInt::from(gcd), BigInt::from(lcm)) } /// Greatest common divisor, least common multiple, and Bézout coefficients. #[inline] - fn extended_gcd_lcm(&self, other: &BigInt) -> (num_integer::ExtendedGcd, BigInt) { + fn extended_gcd_lcm( + &self, + other: &BigInt, + ) -> (num_integer::ExtendedGcd>, BigInt) { let egcd = self.extended_gcd(other); let lcm = if egcd.gcd.is_zero() { Self::zero() @@ -460,13 +472,13 @@ impl Integer for BigInt { /// Deprecated, use `is_multiple_of` instead. #[inline] - fn divides(&self, other: &BigInt) -> bool { + fn divides(&self, other: &BigInt) -> bool { self.is_multiple_of(other) } /// Returns `true` if the number is a multiple of `other`. #[inline] - fn is_multiple_of(&self, other: &BigInt) -> bool { + fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) } @@ -507,7 +519,7 @@ impl Integer for BigInt { } } -impl Roots for BigInt { +impl Roots for BigInt { fn nth_root(&self, n: u32) -> Self { assert!( !(self.is_negative() && n.is_even()), @@ -529,28 +541,28 @@ impl Roots for BigInt { } } -impl IntDigits for BigInt { +impl BigInt { #[inline] - fn digits(&self) -> &[BigDigit] { + pub(crate) fn digits(&self) -> &[BigDigit] { self.data.digits() } #[inline] - fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; NDIGITS]> { + pub(crate) fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; N]> { self.data.digits_mut() } #[inline] - fn normalize(&mut self) { + pub(crate) fn normalize(&mut self) { self.data.normalize(); if self.data.is_zero() { self.sign = NoSign; } } #[inline] - fn capacity(&self) -> usize { + pub(crate) fn capacity(&self) -> usize { self.data.capacity() } #[inline] - fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.data.len() } } @@ -563,7 +575,7 @@ pub trait ToBigInt { fn to_bigint(&self) -> Option; } -impl BigInt { +impl BigInt { // A constant `BigInt` with value 0, useful for static initialization. // pub const ZERO: Self = BigInt { // sign: NoSign, @@ -581,15 +593,15 @@ impl BigInt { /// /// 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)) + pub fn new(sign: Sign, digits: Vec) -> BigInt { + BigInt::from_biguint(sign, BigUint::::new(digits)) } /// Creates and initializes a [`BigInt`]. /// /// The base 232 digits are ordered least significant digit first. #[inline] - pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt { + pub fn from_biguint(mut sign: Sign, mut data: BigUint) -> BigInt { if sign == NoSign { data.assign_from_slice(&[]); } else if data.is_zero() { @@ -603,8 +615,8 @@ impl 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)) + pub fn from_slice(sign: Sign, slice: &[u32]) -> BigInt { + BigInt::from_biguint(sign, BigUint::::from_slice(slice)) } /// Reinitializes a [`BigInt`]. @@ -680,9 +692,9 @@ impl BigInt { /// assert_eq!(BigInt::parse_bytes(b"G", 16), None); /// ``` #[inline] - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { + pub fn parse_bytes(buf: &[u8], radix: u32) -> Option> { let s = str::from_utf8(buf).ok()?; - BigInt::from_str_radix(s, radix).ok() + BigInt::::from_str_radix(s, radix).ok() } /// Creates and initializes a [`BigInt`]. Each `u8` of the input slice is @@ -701,7 +713,7 @@ impl BigInt { /// 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 { + pub fn from_radix_be(sign: Sign, buf: &[u8], radix: u32) -> Option> { let u = BigUint::from_radix_be(buf, radix)?; Some(BigInt::from_biguint(sign, u)) } @@ -722,7 +734,7 @@ impl BigInt { /// 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 { + pub fn from_radix_le(sign: Sign, buf: &[u8], radix: u32) -> Option> { let u = BigUint::from_radix_le(buf, radix)?; Some(BigInt::from_biguint(sign, u)) } @@ -955,7 +967,7 @@ impl BigInt { /// assert!(BigInt::ZERO.magnitude().is_zero()); /// ``` #[inline] - pub fn magnitude(&self) -> &BigUint { + pub fn magnitude(&self) -> &BigUint { &self.data } @@ -972,7 +984,7 @@ impl BigInt { /// assert_eq!(BigInt::ZERO.into_parts(), (Sign::NoSign, BigUint::ZERO)); /// ``` #[inline] - pub fn into_parts(self) -> (Sign, BigUint) { + pub fn into_parts(self) -> (Sign, BigUint) { (self.sign, self.data) } @@ -985,7 +997,7 @@ impl BigInt { /// Converts this [`BigInt`] into a [`BigUint`], if it's not negative. #[inline] - pub fn to_biguint(&self) -> Option { + pub fn to_biguint(&self) -> Option> { match self.sign { Plus => Some(self.data.clone()), NoSign => Some(BigUint::zero()), @@ -994,22 +1006,22 @@ impl BigInt { } #[inline] - pub fn checked_add(&self, v: &BigInt) -> Option { + pub fn checked_add(&self, v: &BigInt) -> Option> { Some(self + v) } #[inline] - pub fn checked_sub(&self, v: &BigInt) -> Option { + pub fn checked_sub(&self, v: &BigInt) -> Option> { Some(self - v) } #[inline] - pub fn checked_mul(&self, v: &BigInt) -> Option { + pub fn checked_mul(&self, v: &BigInt) -> Option> { Some(self * v) } #[inline] - pub fn checked_div(&self, v: &BigInt) -> Option { + pub fn checked_div(&self, v: &BigInt) -> Option> { if v.is_zero() { return None; } @@ -1030,7 +1042,7 @@ impl BigInt { /// /// Panics if the exponent is negative or the modulus is zero. pub fn modpow(&self, exponent: &Self, modulus: &Self) -> Self { - power::modpow(self, exponent, modulus) + power::modpow::(self, exponent, modulus) } /// Returns the modular multiplicative inverse if it exists, otherwise `None`. diff --git a/src/bigint/addition.rs b/src/bigint/addition.rs index 721d3199..4670c74c 100644 --- a/src/bigint/addition.rs +++ b/src/bigint/addition.rs @@ -30,11 +30,11 @@ macro_rules! bigint_add { }; } -impl Add<&BigInt> for &BigInt { - type Output = BigInt; +impl Add<&BigInt> for &BigInt { + type Output = BigInt; #[inline] - fn add(self, other: &BigInt) -> BigInt { + fn add(self, other: &BigInt) -> BigInt { bigint_add!( self, self.clone(), @@ -46,66 +46,71 @@ impl Add<&BigInt> for &BigInt { } } -impl Add for &BigInt { - type Output = BigInt; +impl Add> for &BigInt { + type Output = BigInt; #[inline] - fn add(self, other: BigInt) -> BigInt { + fn add(self, other: BigInt) -> BigInt { bigint_add!(self, self.clone(), &self.data, other, other, other.data) } } -impl Add<&BigInt> for BigInt { - type Output = BigInt; +impl Add<&BigInt> for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: &BigInt) -> BigInt { + fn add(self, other: &BigInt) -> BigInt { bigint_add!(self, self, self.data, other, other.clone(), &other.data) } } -impl Add for BigInt { - type Output = BigInt; +impl Add> for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: BigInt) -> BigInt { + fn add(self, other: BigInt) -> BigInt { bigint_add!(self, self, self.data, other, other, other.data) } } -impl AddAssign<&BigInt> for BigInt { +impl AddAssign<&BigInt> for BigInt { #[inline] - fn add_assign(&mut self, other: &BigInt) { + fn add_assign(&mut self, other: &BigInt) { let n = mem::replace(self, Self::zero()); *self = n + other; } } -forward_val_assign!(impl AddAssign for BigInt, add_assign); +impl AddAssign> for BigInt { + #[inline] + fn add_assign(&mut self, other: BigInt) { + self.add_assign(&other); + } +} -promote_all_scalars!(impl Add for BigInt, add); -promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign); -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); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); +promote_all_scalars!(impl Add for BigInt, add); +promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign); +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); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigInt, add); -impl Add for BigInt { - type Output = BigInt; +impl Add for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: u32) -> BigInt { + fn add(self, other: u32) -> BigInt { match self.sign { NoSign => From::from(other), - Plus => BigInt::from(self.data + other), + Plus => BigInt::::from(self.data + other), Minus => match self.data.cmp(&From::from(other)) { Equal => Self::zero(), - Less => BigInt::from(other - self.data), - Greater => -BigInt::from(self.data - other), + Less => BigInt::::from(other - self.data), + Greater => -BigInt::::from(self.data - other), }, } } } -impl AddAssign for BigInt { +impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u32) { let n = mem::replace(self, Self::zero()); @@ -113,24 +118,24 @@ impl AddAssign for BigInt { } } -impl Add for BigInt { - type Output = BigInt; +impl Add for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: u64) -> BigInt { + fn add(self, other: u64) -> BigInt { match self.sign { NoSign => From::from(other), - Plus => BigInt::from(self.data + other), + Plus => BigInt::::from(self.data + other), Minus => match self.data.cmp(&From::from(other)) { Equal => Self::zero(), - Less => BigInt::from(other - self.data), - Greater => -BigInt::from(self.data - other), + Less => BigInt::::from(other - self.data), + Greater => -BigInt::::from(self.data - other), }, } } } -impl AddAssign for BigInt { +impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u64) { let n = mem::replace(self, Self::zero()); @@ -138,23 +143,23 @@ impl AddAssign for BigInt { } } -impl Add for BigInt { - type Output = BigInt; +impl Add for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: u128) -> BigInt { + fn add(self, other: u128) -> BigInt { match self.sign { - NoSign => BigInt::from(other), - Plus => BigInt::from(self.data + other), + NoSign => BigInt::::from(other), + Plus => BigInt::::from(self.data + other), Minus => match self.data.cmp(&From::from(other)) { Equal => Self::zero(), - Less => BigInt::from(other - self.data), - Greater => -BigInt::from(self.data - other), + Less => BigInt::::from(other - self.data), + Greater => -BigInt::::from(self.data - other), }, } } } -impl AddAssign for BigInt { +impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: u128) { let n = mem::replace(self, Self::zero()); @@ -162,22 +167,22 @@ impl AddAssign for BigInt { } } -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); -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); +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; +impl Add for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: i32) -> BigInt { + fn add(self, other: i32) -> BigInt { match other.checked_uabs() { Positive(u) => self + u, Negative(u) => self - u, } } } -impl AddAssign for BigInt { +impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: i32) { match other.checked_uabs() { @@ -187,18 +192,18 @@ impl AddAssign for BigInt { } } -impl Add for BigInt { - type Output = BigInt; +impl Add for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: i64) -> BigInt { + fn add(self, other: i64) -> BigInt { match other.checked_uabs() { Positive(u) => self + u, Negative(u) => self - u, } } } -impl AddAssign for BigInt { +impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: i64) { match other.checked_uabs() { @@ -208,18 +213,18 @@ impl AddAssign for BigInt { } } -impl Add for BigInt { - type Output = BigInt; +impl Add for BigInt { + type Output = BigInt; #[inline] - fn add(self, other: i128) -> BigInt { + fn add(self, other: i128) -> BigInt { match other.checked_uabs() { Positive(u) => self + u, Negative(u) => self - u, } } } -impl AddAssign for BigInt { +impl AddAssign for BigInt { #[inline] fn add_assign(&mut self, other: i128) { match other.checked_uabs() { @@ -229,9 +234,9 @@ impl AddAssign for BigInt { } } -impl CheckedAdd for BigInt { +impl CheckedAdd for BigInt { #[inline] - fn checked_add(&self, v: &BigInt) -> Option { + fn checked_add(&self, v: &BigInt) -> Option> { Some(self.add(v)) } } diff --git a/src/bigint/bits.rs b/src/bigint/bits.rs index bd9e2209..d840fc01 100644 --- a/src/bigint/bits.rs +++ b/src/bigint/bits.rs @@ -2,13 +2,11 @@ use super::BigInt; use super::Sign::{Minus, NoSign, Plus}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; -use crate::biguint::{IntDigits, NDIGITS}; -use alloc::vec::Vec; -use tinyvec::TinyVec; use core::cmp::Ordering::{Equal, Greater, Less}; use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; use num_traits::{ToPrimitive, Zero}; +use tinyvec::TinyVec; // Negation in two's complement. // acc must be initialized as 1 for least-significant digit. @@ -49,7 +47,7 @@ fn bitand_pos_neg(a: &mut [BigDigit], b: &[BigDigit]) { // - 1 & +ff = ...f ff & ...0 ff = ...0 ff = +ff // -ff & + 1 = ...f 01 & ...0 01 = ...0 01 = + 1 // answer is pos, has length of b -fn bitand_neg_pos(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { +fn bitand_neg_pos(a: &mut TinyVec<[BigDigit; N]>, b: &[BigDigit]) { let mut carry_a = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { let twos_a = negate_carry(*ai, &mut carry_a); @@ -70,7 +68,7 @@ fn bitand_neg_pos(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { // -ff & - 1 = ...f 01 & ...f ff = ...f 01 = - ff // -ff & -fe = ...f 01 & ...f 02 = ...f 00 = -100 // answer is neg, has length of longest with a possible carry -fn bitand_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { +fn bitand_neg_neg(a: &mut TinyVec<[BigDigit; N]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_b = 1; let mut carry_and = 1; @@ -104,16 +102,16 @@ fn bitand_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { } } -forward_val_val_binop!(impl BitAnd for BigInt, bitand); -forward_ref_val_binop!(impl BitAnd for BigInt, bitand); +forward_val_val_binop!(impl BitAnd for BigInt, bitand); +forward_ref_val_binop!(impl BitAnd for BigInt, bitand); // do not use forward_ref_ref_binop_commutative! for bitand so that we can // clone as needed, avoiding over-allocation -impl BitAnd<&BigInt> for &BigInt { - type Output = BigInt; +impl BitAnd<&BigInt> for &BigInt { + type Output = BigInt; #[inline] - fn bitand(self, other: &BigInt) -> BigInt { + fn bitand(self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { (NoSign, _) | (_, NoSign) => BigInt::zero(), (Plus, Plus) => BigInt::from(&self.data & &other.data), @@ -131,20 +129,25 @@ impl BitAnd<&BigInt> for &BigInt { } } -impl BitAnd<&BigInt> for BigInt { - type Output = BigInt; +impl BitAnd<&BigInt> for BigInt { + type Output = BigInt; #[inline] - fn bitand(mut self, other: &BigInt) -> BigInt { + fn bitand(mut self, other: &BigInt) -> BigInt { self &= other; self } } -forward_val_assign!(impl BitAndAssign for BigInt, bitand_assign); +impl BitAndAssign> for BigInt { + #[inline] + fn bitand_assign(&mut self, other: BigInt) { + self.bitand_assign(&other); + } +} -impl BitAndAssign<&BigInt> for BigInt { - fn bitand_assign(&mut self, other: &BigInt) { +impl BitAndAssign<&BigInt> for BigInt { + fn bitand_assign(&mut self, other: &BigInt) { match (self.sign, other.sign) { (NoSign, _) => {} (_, NoSign) => self.set_zero(), @@ -174,7 +177,7 @@ impl BitAndAssign<&BigInt> for BigInt { // + 1 | -ff = ...0 01 | ...f 01 = ...f 01 = -ff // +ff | - 1 = ...0 ff | ...f ff = ...f ff = - 1 // answer is neg, has length of b -fn bitor_pos_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { +fn bitor_pos_neg(a: &mut TinyVec<[BigDigit; N]>, b: &[BigDigit]) { let mut carry_b = 1; let mut carry_or = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { @@ -225,7 +228,7 @@ fn bitor_neg_pos(a: &mut [BigDigit], b: &[BigDigit]) { // - 1 | -ff = ...f ff | ...f 01 = ...f ff = -1 // -ff | - 1 = ...f 01 | ...f ff = ...f ff = -1 // answer is neg, has length of shortest -fn bitor_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { +fn bitor_neg_neg(a: &mut TinyVec<[BigDigit; N]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_b = 1; let mut carry_or = 1; @@ -243,20 +246,20 @@ fn bitor_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { debug_assert!(carry_or == 0); } -forward_val_val_binop!(impl BitOr for BigInt, bitor); -forward_ref_val_binop!(impl BitOr for BigInt, bitor); +forward_val_val_binop!(impl BitOr for BigInt, bitor); +forward_ref_val_binop!(impl BitOr for BigInt, bitor); // do not use forward_ref_ref_binop_commutative! for bitor so that we can // clone as needed, avoiding over-allocation -impl BitOr<&BigInt> for &BigInt { - type Output = BigInt; +impl BitOr<&BigInt> for &BigInt { + type Output = BigInt; #[inline] - fn bitor(self, other: &BigInt) -> BigInt { + fn bitor(self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { (NoSign, _) => other.clone(), (_, NoSign) => self.clone(), - (Plus, Plus) => BigInt::from(&self.data | &other.data), + (Plus, Plus) => BigInt::::from(&self.data | &other.data), (Plus, Minus) => other.clone() | self, (Minus, Plus) => self.clone() | other, (Minus, Minus) => { @@ -271,20 +274,20 @@ impl BitOr<&BigInt> for &BigInt { } } -impl BitOr<&BigInt> for BigInt { - type Output = BigInt; +impl BitOr<&BigInt> for BigInt { + type Output = BigInt; #[inline] - fn bitor(mut self, other: &BigInt) -> BigInt { + fn bitor(mut self, other: &BigInt) -> BigInt { self |= other; self } } -forward_val_assign!(impl BitOrAssign for BigInt, bitor_assign); +forward_val_assign!(impl BitOrAssign for BigInt, bitor_assign); -impl BitOrAssign<&BigInt> for BigInt { - fn bitor_assign(&mut self, other: &BigInt) { +impl BitOrAssign<&BigInt> for BigInt { + fn bitor_assign(&mut self, other: &BigInt) { match (self.sign, other.sign) { (_, NoSign) => {} (NoSign, _) => self.clone_from(other), @@ -309,7 +312,7 @@ impl BitOrAssign<&BigInt> for BigInt { // + 1 ^ -ff = ...0 01 ^ ...f 01 = ...f 00 = -100 // +ff ^ - 1 = ...0 ff ^ ...f ff = ...f 00 = -100 // answer is neg, has length of longest with a possible carry -fn bitxor_pos_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { +fn bitxor_pos_neg(a: &mut TinyVec<[BigDigit; N]>, b: &[BigDigit]) { let mut carry_b = 1; let mut carry_xor = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { @@ -342,7 +345,7 @@ fn bitxor_pos_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { // - 1 ^ +ff = ...f ff ^ ...0 ff = ...f 00 = -100 // -ff ^ + 1 = ...f 01 ^ ...0 01 = ...f 00 = -100 // answer is neg, has length of longest with a possible carry -fn bitxor_neg_pos(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { +fn bitxor_neg_pos(a: &mut TinyVec<[BigDigit; N]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_xor = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { @@ -375,7 +378,7 @@ fn bitxor_neg_pos(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { // - 1 ^ -ff = ...f ff ^ ...f 01 = ...0 fe = +fe // -ff & - 1 = ...f 01 ^ ...f ff = ...0 fe = +fe // answer is pos, has length of longest -fn bitxor_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { +fn bitxor_neg_neg(a: &mut TinyVec<[BigDigit; N]>, b: &[BigDigit]) { let mut carry_a = 1; let mut carry_b = 1; for (ai, &bi) in a.iter_mut().zip(b.iter()) { @@ -407,22 +410,22 @@ fn bitxor_neg_neg(a: &mut TinyVec<[BigDigit; NDIGITS]>, b: &[BigDigit]) { } } -forward_all_binop_to_val_ref_commutative!(impl BitXor for BigInt, bitxor); +forward_all_binop_to_val_ref_commutative!(impl BitXor for BigInt, bitxor); -impl BitXor<&BigInt> for BigInt { - type Output = BigInt; +impl BitXor<&BigInt> for BigInt { + type Output = BigInt; #[inline] - fn bitxor(mut self, other: &BigInt) -> BigInt { + fn bitxor(mut self, other: &BigInt) -> BigInt { self ^= other; self } } -forward_val_assign!(impl BitXorAssign for BigInt, bitxor_assign); +forward_val_assign!(impl BitXorAssign for BigInt, bitxor_assign); -impl BitXorAssign<&BigInt> for BigInt { - fn bitxor_assign(&mut self, other: &BigInt) { +impl BitXorAssign<&BigInt> for BigInt { + fn bitxor_assign(&mut self, other: &BigInt) { match (self.sign, other.sign) { (_, NoSign) => {} (NoSign, _) => self.clone_from(other), @@ -450,7 +453,7 @@ impl BitXorAssign<&BigInt> for BigInt { } } -pub(super) fn set_negative_bit(x: &mut BigInt, bit: u64, value: bool) { +pub(super) fn set_negative_bit(x: &mut BigInt, bit: u64, value: bool) { debug_assert_eq!(x.sign, Minus); let data = &mut x.data; diff --git a/src/bigint/convert.rs b/src/bigint/convert.rs index ac4481d4..4e2f4014 100644 --- a/src/bigint/convert.rs +++ b/src/bigint/convert.rs @@ -19,12 +19,12 @@ impl FromStr for BigInt { } } -impl Num for BigInt { +impl Num for BigInt { type FromStrRadixErr = ParseBigIntError; /// Creates and initializes a [`BigInt`]. #[inline] - fn from_str_radix(mut s: &str, radix: u32) -> Result { + fn from_str_radix(mut s: &str, radix: u32) -> Result, ParseBigIntError> { let sign = if let Some(tail) = s.strip_prefix('-') { if !tail.starts_with('+') { s = tail @@ -38,7 +38,7 @@ impl Num for BigInt { } } -impl ToPrimitive for BigInt { +impl ToPrimitive for BigInt { #[inline] fn to_i64(&self) -> Option { match self.sign { @@ -106,20 +106,20 @@ impl ToPrimitive for BigInt { macro_rules! impl_try_from_bigint { ($T:ty, $to_ty:path) => { - impl TryFrom<&BigInt> for $T { + impl TryFrom<&BigInt> for $T { type Error = TryFromBigIntError<()>; #[inline] - fn try_from(value: &BigInt) -> Result<$T, TryFromBigIntError<()>> { + fn try_from(value: &BigInt) -> Result<$T, TryFromBigIntError<()>> { $to_ty(value).ok_or(TryFromBigIntError::new(())) } } - impl TryFrom for $T { - type Error = TryFromBigIntError; + impl TryFrom> for $T { + type Error = TryFromBigIntError>; #[inline] - fn try_from(value: BigInt) -> Result<$T, TryFromBigIntError> { + fn try_from(value: BigInt) -> Result<$T, TryFromBigIntError>> { <$T>::try_from(&value).map_err(|_| TryFromBigIntError::new(value)) } } @@ -140,43 +140,43 @@ impl_try_from_bigint!(i64, ToPrimitive::to_i64); impl_try_from_bigint!(isize, ToPrimitive::to_isize); impl_try_from_bigint!(i128, ToPrimitive::to_i128); -impl FromPrimitive for BigInt { +impl FromPrimitive for BigInt { #[inline] - fn from_i64(n: i64) -> Option { - Some(BigInt::from(n)) + fn from_i64(n: i64) -> Option> { + Some(BigInt::::from(n)) } #[inline] - fn from_i128(n: i128) -> Option { - Some(BigInt::from(n)) + fn from_i128(n: i128) -> Option> { + Some(BigInt::::from(n)) } #[inline] - fn from_u64(n: u64) -> Option { - Some(BigInt::from(n)) + fn from_u64(n: u64) -> Option> { + Some(BigInt::::from(n)) } #[inline] - fn from_u128(n: u128) -> Option { - Some(BigInt::from(n)) + fn from_u128(n: u128) -> Option> { + Some(BigInt::::from(n)) } #[inline] - fn from_f64(n: f64) -> Option { + fn from_f64(n: f64) -> Option> { if n >= 0.0 { - BigUint::from_f64(n).map(BigInt::from) + BigUint::::from_f64(n).map(BigInt::::from) } else { - let x = BigUint::from_f64(-n)?; - Some(-BigInt::from(x)) + let x = BigUint::::from_f64(-n)?; + Some(-BigInt::::from(x)) } } } -impl From for BigInt { +impl From for BigInt { #[inline] fn from(n: i64) -> Self { if n >= 0 { - BigInt::from(n as u64) + BigInt::::from(n as u64) } else { let u = u64::MAX - (n as u64) + 1; BigInt { @@ -187,16 +187,16 @@ impl From for BigInt { } } -impl From for BigInt { +impl From for BigInt { #[inline] fn from(n: i128) -> Self { if n >= 0 { - BigInt::from(n as u128) + BigInt::::from(n as u128) } else { let u = u128::MAX - (n as u128) + 1; BigInt { sign: Minus, - data: BigUint::from(u), + data: BigUint::::from(u), } } } @@ -204,7 +204,7 @@ impl From for BigInt { macro_rules! impl_bigint_from_int { ($T:ty) => { - impl From<$T> for BigInt { + impl From<$T> for BigInt { #[inline] fn from(n: $T) -> Self { BigInt::from(n as i64) @@ -218,7 +218,7 @@ impl_bigint_from_int!(i16); impl_bigint_from_int!(i32); impl_bigint_from_int!(isize); -impl From for BigInt { +impl From for BigInt { #[inline] fn from(n: u64) -> Self { if n > 0 { @@ -232,7 +232,7 @@ impl From for BigInt { } } -impl From for BigInt { +impl From for BigInt { #[inline] fn from(n: u128) -> Self { if n > 0 { @@ -248,7 +248,7 @@ impl From for BigInt { macro_rules! impl_bigint_from_uint { ($T:ty) => { - impl From<$T> for BigInt { + impl From<$T> for BigInt { #[inline] fn from(n: $T) -> Self { BigInt::from(n as u64) @@ -262,9 +262,9 @@ impl_bigint_from_uint!(u16); impl_bigint_from_uint!(u32); impl_bigint_from_uint!(usize); -impl From for BigInt { +impl From> for BigInt { #[inline] - fn from(n: BigUint) -> Self { + fn from(n: BigUint) -> Self { if n.is_zero() { Self::zero() } else { @@ -282,7 +282,6 @@ impl ToBigInt for BigInt { Some(self.clone()) } } - impl ToBigInt for BigUint { #[inline] fn to_bigint(&self) -> Option { @@ -296,7 +295,6 @@ impl ToBigInt for BigUint { } } } - impl ToBigUint for BigInt { #[inline] fn to_biguint(&self) -> Option { @@ -308,6 +306,38 @@ impl ToBigUint for BigInt { } } +// impl BigInt { +// #[inline] +// fn to_bigint(&self) -> Option> { +// Some(self.clone()) +// } +// } + +// impl BigUint { +// #[inline] +// fn to_bigint(&self) -> Option> { +// if self.is_zero() { +// Some(BigInt::zero()) +// } else { +// Some(BigInt { +// sign: Plus, +// data: self.clone(), +// }) +// } +// } +// } + +// impl BigInt { +// #[inline] +// fn to_biguint(&self) -> Option> { +// match self.sign() { +// Plus => Some(self.data.clone()), +// NoSign => Some(BigUint::zero()), +// Minus => None, +// } +// } +// } + impl TryFrom<&BigInt> for BigUint { type Error = TryFromBigIntError<()>; @@ -407,7 +437,7 @@ pub(super) fn from_signed_bytes_le(digits: &[u8]) -> BigInt { } #[inline] -pub(super) fn to_signed_bytes_be(x: &BigInt) -> Vec { +pub(super) fn to_signed_bytes_be(x: &BigInt) -> Vec { let mut bytes = x.data.to_bytes_be(); let first_byte = bytes.first().cloned().unwrap_or(0); if first_byte > 0x7f @@ -423,7 +453,7 @@ pub(super) fn to_signed_bytes_be(x: &BigInt) -> Vec { } #[inline] -pub(super) fn to_signed_bytes_le(x: &BigInt) -> Vec { +pub(super) fn to_signed_bytes_le(x: &BigInt) -> Vec { let mut bytes = x.data.to_bytes_le(); let last_byte = bytes.last().cloned().unwrap_or(0); if last_byte > 0x7f diff --git a/src/bigint/division.rs b/src/bigint/division.rs index 0d4d23f3..33ec50ed 100644 --- a/src/bigint/division.rs +++ b/src/bigint/division.rs @@ -8,42 +8,43 @@ use core::ops::{Div, DivAssign, Rem, RemAssign}; use num_integer::Integer; use num_traits::{CheckedDiv, CheckedEuclid, Euclid, Signed, ToPrimitive, Zero}; -forward_all_binop_to_ref_ref!(impl Div for BigInt, div); +forward_all_binop_to_ref_ref!(impl Div for BigInt, div); -impl Div<&BigInt> for &BigInt { - type Output = BigInt; +impl Div<&BigInt> for &BigInt { + type Output = BigInt; #[inline] - fn div(self, other: &BigInt) -> BigInt { + fn div(self, other: &BigInt) -> BigInt { let (q, _) = self.div_rem(other); q } } -impl DivAssign<&BigInt> for BigInt { +impl DivAssign<&BigInt> for BigInt { #[inline] - fn div_assign(&mut self, other: &BigInt) { + fn div_assign(&mut self, other: &BigInt) { *self = &*self / other; } } -forward_val_assign!(impl DivAssign for BigInt, div_assign); -promote_all_scalars!(impl Div for BigInt, div); -promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign); -forward_all_scalar_binop_to_val_val!(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); +forward_val_assign!(impl DivAssign for BigInt, div_assign); -impl Div for BigInt { - type Output = BigInt; +promote_all_scalars!(impl Div for BigInt, div); +promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign); +forward_all_scalar_binop_to_val_val!(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: u32) -> BigInt { + fn div(self, other: u32) -> BigInt { BigInt::from_biguint(self.sign, self.data / other) } } -impl DivAssign for BigInt { +impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: u32) { self.data /= other; @@ -53,25 +54,25 @@ impl DivAssign for BigInt { } } -impl Div for u32 { - type Output = BigInt; +impl Div> for u32 { + type Output = BigInt; #[inline] - fn div(self, other: BigInt) -> BigInt { + fn div(self, other: BigInt) -> BigInt { BigInt::from_biguint(other.sign, self / other.data) } } -impl Div for BigInt { - type Output = BigInt; +impl Div for BigInt { + type Output = BigInt; #[inline] - fn div(self, other: u64) -> BigInt { + fn div(self, other: u64) -> BigInt { BigInt::from_biguint(self.sign, self.data / other) } } -impl DivAssign for BigInt { +impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: u64) { self.data /= other; @@ -81,25 +82,25 @@ impl DivAssign for BigInt { } } -impl Div for u64 { - type Output = BigInt; +impl Div> for u64 { + type Output = BigInt; #[inline] - fn div(self, other: BigInt) -> BigInt { + fn div(self, other: BigInt) -> BigInt { BigInt::from_biguint(other.sign, self / other.data) } } -impl Div for BigInt { - type Output = BigInt; +impl Div for BigInt { + type Output = BigInt; #[inline] - fn div(self, other: u128) -> BigInt { + fn div(self, other: u128) -> BigInt { BigInt::from_biguint(self.sign, self.data / other) } } -impl DivAssign for BigInt { +impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: u128) { self.data /= other; @@ -109,24 +110,24 @@ impl DivAssign for BigInt { } } -impl Div for u128 { - type Output = BigInt; +impl Div> for u128 { + type Output = BigInt; #[inline] - fn div(self, other: BigInt) -> BigInt { + 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); -forward_all_scalar_binop_to_val_val!(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); +forward_all_scalar_binop_to_val_val!(impl Div for BigInt, div); -impl Div for BigInt { - type Output = BigInt; +impl Div for BigInt { + type Output = BigInt; #[inline] - fn div(self, other: i32) -> BigInt { + fn div(self, other: i32) -> BigInt { match other.checked_uabs() { Positive(u) => self / u, Negative(u) => -self / u, @@ -134,7 +135,7 @@ impl Div for BigInt { } } -impl DivAssign for BigInt { +impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: i32) { match other.checked_uabs() { @@ -147,11 +148,11 @@ impl DivAssign for BigInt { } } -impl Div for i32 { - type Output = BigInt; +impl Div> for i32 { + type Output = BigInt; #[inline] - fn div(self, other: BigInt) -> BigInt { + fn div(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u / other, Negative(u) => u / -other, @@ -159,11 +160,11 @@ impl Div for i32 { } } -impl Div for BigInt { - type Output = BigInt; +impl Div for BigInt { + type Output = BigInt; #[inline] - fn div(self, other: i64) -> BigInt { + fn div(self, other: i64) -> BigInt { match other.checked_uabs() { Positive(u) => self / u, Negative(u) => -self / u, @@ -171,7 +172,7 @@ impl Div for BigInt { } } -impl DivAssign for BigInt { +impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: i64) { match other.checked_uabs() { @@ -184,11 +185,11 @@ impl DivAssign for BigInt { } } -impl Div for i64 { - type Output = BigInt; +impl Div> for i64 { + type Output = BigInt; #[inline] - fn div(self, other: BigInt) -> BigInt { + fn div(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u / other, Negative(u) => u / -other, @@ -196,11 +197,11 @@ impl Div for i64 { } } -impl Div for BigInt { - type Output = BigInt; +impl Div for BigInt { + type Output = BigInt; #[inline] - fn div(self, other: i128) -> BigInt { + fn div(self, other: i128) -> BigInt { match other.checked_uabs() { Positive(u) => self / u, Negative(u) => -self / u, @@ -208,7 +209,7 @@ impl Div for BigInt { } } -impl DivAssign for BigInt { +impl DivAssign for BigInt { #[inline] fn div_assign(&mut self, other: i128) { match other.checked_uabs() { @@ -221,11 +222,11 @@ impl DivAssign for BigInt { } } -impl Div for i128 { - type Output = BigInt; +impl Div> for i128 { + type Output = BigInt; #[inline] - fn div(self, other: BigInt) -> BigInt { + fn div(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u / other, Negative(u) => u / -other, @@ -233,13 +234,13 @@ impl Div for i128 { } } -forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem); +forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem); -impl Rem<&BigInt> for &BigInt { - type Output = BigInt; +impl Rem<&BigInt> for &BigInt { + type Output = BigInt; #[inline] - fn rem(self, other: &BigInt) -> BigInt { + fn rem(self, other: &BigInt) -> BigInt { if let Some(other) = other.to_u32() { self % other } else if let Some(other) = other.to_i32() { @@ -251,30 +252,35 @@ impl Rem<&BigInt> for &BigInt { } } -impl RemAssign<&BigInt> for BigInt { +impl RemAssign<&BigInt> for BigInt { #[inline] - fn rem_assign(&mut self, other: &BigInt) { + fn rem_assign(&mut self, other: &BigInt) { *self = &*self % other; } } -forward_val_assign!(impl RemAssign for BigInt, rem_assign); +impl RemAssign> for BigInt { + #[inline] + fn rem_assign(&mut self, other: BigInt) { + self.rem_assign(&other); + } +} -promote_all_scalars!(impl Rem for BigInt, rem); -promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign); -forward_all_scalar_binop_to_val_val!(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); +promote_all_scalars!(impl Rem for BigInt, rem); +promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign); +forward_all_scalar_binop_to_val_val!(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; +impl Rem for BigInt { + type Output = BigInt; #[inline] - fn rem(self, other: u32) -> BigInt { + fn rem(self, other: u32) -> BigInt { BigInt::from_biguint(self.sign, self.data % other) } } -impl RemAssign for BigInt { +impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: u32) { self.data %= other; @@ -284,25 +290,25 @@ impl RemAssign for BigInt { } } -impl Rem for u32 { - type Output = BigInt; +impl Rem> for u32 { + type Output = BigInt; #[inline] - fn rem(self, other: BigInt) -> BigInt { + fn rem(self, other: BigInt) -> BigInt { BigInt::from(self % other.data) } } -impl Rem for BigInt { - type Output = BigInt; +impl Rem for BigInt { + type Output = BigInt; #[inline] - fn rem(self, other: u64) -> BigInt { + fn rem(self, other: u64) -> BigInt { BigInt::from_biguint(self.sign, self.data % other) } } -impl RemAssign for BigInt { +impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: u64) { self.data %= other; @@ -312,25 +318,25 @@ impl RemAssign for BigInt { } } -impl Rem for u64 { - type Output = BigInt; +impl Rem> for u64 { + type Output = BigInt; #[inline] - fn rem(self, other: BigInt) -> BigInt { + fn rem(self, other: BigInt) -> BigInt { BigInt::from(self % other.data) } } -impl Rem for BigInt { - type Output = BigInt; +impl Rem for BigInt { + type Output = BigInt; #[inline] - fn rem(self, other: u128) -> BigInt { + fn rem(self, other: u128) -> BigInt { BigInt::from_biguint(self.sign, self.data % other) } } -impl RemAssign for BigInt { +impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: u128) { self.data %= other; @@ -340,40 +346,40 @@ impl RemAssign for BigInt { } } -impl Rem for u128 { - type Output = BigInt; +impl Rem> for u128 { + type Output = BigInt; #[inline] - fn rem(self, other: BigInt) -> BigInt { + fn rem(self, other: BigInt) -> BigInt { BigInt::from(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); -forward_all_scalar_binop_to_val_val!(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); +forward_all_scalar_binop_to_val_val!(impl Rem for BigInt, rem); -impl Rem for BigInt { - type Output = BigInt; +impl Rem for BigInt { + type Output = BigInt; #[inline] - fn rem(self, other: i32) -> BigInt { + fn rem(self, other: i32) -> BigInt { self % other.unsigned_abs() } } -impl RemAssign for BigInt { +impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: i32) { *self %= other.unsigned_abs(); } } -impl Rem for i32 { - type Output = BigInt; +impl Rem> for i32 { + type Output = BigInt; #[inline] - fn rem(self, other: BigInt) -> BigInt { + fn rem(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u % other, Negative(u) => -(u % other), @@ -381,27 +387,27 @@ impl Rem for i32 { } } -impl Rem for BigInt { - type Output = BigInt; +impl Rem for BigInt { + type Output = BigInt; #[inline] - fn rem(self, other: i64) -> BigInt { + fn rem(self, other: i64) -> BigInt { self % other.unsigned_abs() } } -impl RemAssign for BigInt { +impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: i64) { *self %= other.unsigned_abs(); } } -impl Rem for i64 { - type Output = BigInt; +impl Rem> for i64 { + type Output = BigInt; #[inline] - fn rem(self, other: BigInt) -> BigInt { + fn rem(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u % other, Negative(u) => -(u % other), @@ -409,27 +415,27 @@ impl Rem for i64 { } } -impl Rem for BigInt { - type Output = BigInt; +impl Rem for BigInt { + type Output = BigInt; #[inline] - fn rem(self, other: i128) -> BigInt { + fn rem(self, other: i128) -> BigInt { self % other.unsigned_abs() } } -impl RemAssign for BigInt { +impl RemAssign for BigInt { #[inline] fn rem_assign(&mut self, other: i128) { *self %= other.unsigned_abs(); } } -impl Rem for i128 { - type Output = BigInt; +impl Rem> for i128 { + type Output = BigInt; #[inline] - fn rem(self, other: BigInt) -> BigInt { + fn rem(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u % other, Negative(u) => -(u % other), @@ -437,9 +443,9 @@ impl Rem for i128 { } } -impl CheckedDiv for BigInt { +impl CheckedDiv for BigInt { #[inline] - fn checked_div(&self, v: &BigInt) -> Option { + fn checked_div(&self, v: &BigInt) -> Option> { if v.is_zero() { return None; } @@ -447,9 +453,9 @@ impl CheckedDiv for BigInt { } } -impl CheckedEuclid for BigInt { +impl CheckedEuclid for BigInt { #[inline] - fn checked_div_euclid(&self, v: &BigInt) -> Option { + fn checked_div_euclid(&self, v: &BigInt) -> Option> { if v.is_zero() { return None; } @@ -457,7 +463,7 @@ impl CheckedEuclid for BigInt { } #[inline] - fn checked_rem_euclid(&self, v: &BigInt) -> Option { + fn checked_rem_euclid(&self, v: &BigInt) -> Option> { if v.is_zero() { return None; } @@ -469,9 +475,9 @@ impl CheckedEuclid for BigInt { } } -impl Euclid for BigInt { +impl Euclid for BigInt { #[inline] - fn div_euclid(&self, v: &BigInt) -> BigInt { + fn div_euclid(&self, v: &BigInt) -> BigInt { let (q, r) = self.div_rem(v); if r.is_negative() { if v.is_positive() { @@ -485,7 +491,7 @@ impl Euclid for BigInt { } #[inline] - fn rem_euclid(&self, v: &BigInt) -> BigInt { + fn rem_euclid(&self, v: &BigInt) -> BigInt { let r = self % v; if r.is_negative() { if v.is_positive() { diff --git a/src/bigint/multiplication.rs b/src/bigint/multiplication.rs index 82e64c28..6a983bd1 100644 --- a/src/bigint/multiplication.rs +++ b/src/bigint/multiplication.rs @@ -21,66 +21,84 @@ impl Mul for Sign { } } -macro_rules! impl_mul { - ($(impl Mul<$Other:ty> for $Self:ty;)*) => {$( - impl Mul<$Other> for $Self { - type Output = BigInt; - - #[inline] - fn mul(self, other: $Other) -> BigInt { - // automatically match value/ref - let BigInt { data: x, .. } = self; - let BigInt { data: y, .. } = other; - BigInt::from_biguint(self.sign * other.sign, x * y) - } - } - )*} -} -impl_mul! { - impl Mul for BigInt; - impl Mul for &BigInt; - impl Mul<&BigInt> for BigInt; - impl Mul<&BigInt> for &BigInt; -} - -macro_rules! impl_mul_assign { - ($(impl MulAssign<$Other:ty> for BigInt;)*) => {$( - impl MulAssign<$Other> for BigInt { - #[inline] - fn mul_assign(&mut self, other: $Other) { - // automatically match value/ref - let BigInt { data: y, .. } = other; - self.data *= y; - if self.data.is_zero() { - self.sign = NoSign; - } else { - self.sign = self.sign * other.sign; - } - } +impl Mul> for BigInt { + type Output = BigInt; + #[inline] + fn mul(self, other: BigInt) -> BigInt { + let BigInt { data: x, .. } = self; + let BigInt { data: y, .. } = other; + BigInt::from_biguint(self.sign * other.sign, x * y) + } +} +impl Mul> for &BigInt { + type Output = BigInt; + #[inline] + fn mul(self, other: BigInt) -> BigInt { + let BigInt { data: x, .. } = self; + let BigInt { data: y, .. } = other; + BigInt::from_biguint(self.sign * other.sign, x * y) + } +} +impl Mul<&BigInt> for BigInt { + type Output = BigInt; + #[inline] + fn mul(self, other: &BigInt) -> BigInt { + let BigInt { data: x, .. } = self; + let BigInt { data: y, .. } = other; + BigInt::from_biguint(self.sign * other.sign, x * y) + } +} +impl Mul<&BigInt> for &BigInt { + type Output = BigInt; + #[inline] + fn mul(self, other: &BigInt) -> BigInt { + let BigInt { data: x, .. } = self; + let BigInt { data: y, .. } = other; + BigInt::from_biguint(self.sign * other.sign, x * y) + } +} + +impl MulAssign> for BigInt { + #[inline] + fn mul_assign(&mut self, other: BigInt) { + let BigInt { data: y, .. } = other; + self.data *= y; + if self.data.is_zero() { + self.sign = NoSign; + } else { + self.sign = self.sign * other.sign; } - )*} + } } -impl_mul_assign! { - impl MulAssign for BigInt; - impl MulAssign<&BigInt> for BigInt; +impl MulAssign<&BigInt> for BigInt { + #[inline] + fn mul_assign(&mut self, other: &BigInt) { + let BigInt { data: y, .. } = other; + self.data *= y; + if self.data.is_zero() { + self.sign = NoSign; + } else { + self.sign = self.sign * other.sign; + } + } } -promote_all_scalars!(impl Mul for BigInt, mul); -promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign); -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); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); +promote_all_scalars!(impl Mul for BigInt, mul); +promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign); +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); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigInt, mul); -impl Mul for BigInt { - type Output = BigInt; +impl Mul for BigInt { + type Output = BigInt; #[inline] - fn mul(self, other: u32) -> BigInt { + fn mul(self, other: u32) -> BigInt { BigInt::from_biguint(self.sign, self.data * other) } } -impl MulAssign for BigInt { +impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: u32) { self.data *= other; @@ -90,16 +108,16 @@ impl MulAssign for BigInt { } } -impl Mul for BigInt { - type Output = BigInt; +impl Mul for BigInt { + type Output = BigInt; #[inline] - fn mul(self, other: u64) -> BigInt { + fn mul(self, other: u64) -> BigInt { BigInt::from_biguint(self.sign, self.data * other) } } -impl MulAssign for BigInt { +impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: u64) { self.data *= other; @@ -109,16 +127,16 @@ impl MulAssign for BigInt { } } -impl Mul for BigInt { - type Output = BigInt; +impl Mul for BigInt { + type Output = BigInt; #[inline] - fn mul(self, other: u128) -> BigInt { + fn mul(self, other: u128) -> BigInt { BigInt::from_biguint(self.sign, self.data * other) } } -impl MulAssign for BigInt { +impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: u128) { self.data *= other; @@ -128,15 +146,15 @@ impl MulAssign for BigInt { } } -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); -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); +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; +impl Mul for BigInt { + type Output = BigInt; #[inline] - fn mul(self, other: i32) -> BigInt { + fn mul(self, other: i32) -> BigInt { match other.checked_uabs() { Positive(u) => self * u, Negative(u) => -self * u, @@ -144,7 +162,7 @@ impl Mul for BigInt { } } -impl MulAssign for BigInt { +impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: i32) { match other.checked_uabs() { @@ -157,11 +175,11 @@ impl MulAssign for BigInt { } } -impl Mul for BigInt { - type Output = BigInt; +impl Mul for BigInt { + type Output = BigInt; #[inline] - fn mul(self, other: i64) -> BigInt { + fn mul(self, other: i64) -> BigInt { match other.checked_uabs() { Positive(u) => self * u, Negative(u) => -self * u, @@ -169,7 +187,7 @@ impl Mul for BigInt { } } -impl MulAssign for BigInt { +impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: i64) { match other.checked_uabs() { @@ -182,11 +200,11 @@ impl MulAssign for BigInt { } } -impl Mul for BigInt { - type Output = BigInt; +impl Mul for BigInt { + type Output = BigInt; #[inline] - fn mul(self, other: i128) -> BigInt { + fn mul(self, other: i128) -> BigInt { match other.checked_uabs() { Positive(u) => self * u, Negative(u) => -self * u, @@ -194,7 +212,7 @@ impl Mul for BigInt { } } -impl MulAssign for BigInt { +impl MulAssign for BigInt { #[inline] fn mul_assign(&mut self, other: i128) { match other.checked_uabs() { @@ -207,9 +225,9 @@ impl MulAssign for BigInt { } } -impl CheckedMul for BigInt { +impl CheckedMul for BigInt { #[inline] - fn checked_mul(&self, v: &BigInt) -> Option { + fn checked_mul(&self, v: &BigInt) -> Option> { Some(self.mul(v)) } } diff --git a/src/bigint/power.rs b/src/bigint/power.rs index 4b41f4f2..4ec43f0f 100644 --- a/src/bigint/power.rs +++ b/src/bigint/power.rs @@ -22,39 +22,39 @@ fn powsign(sign: Sign, other: &T) -> Sign { macro_rules! pow_impl { ($T:ty) => { - impl Pow<$T> for BigInt { - type Output = BigInt; + impl Pow<$T> for BigInt { + type Output = BigInt; #[inline] - fn pow(self, rhs: $T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, &rhs), self.data.pow(rhs)) + fn pow(self, rhs: $T) -> BigInt { + BigInt::::from_biguint(powsign(self.sign, &rhs), self.data.pow(rhs)) } } - impl Pow<&$T> for BigInt { - type Output = BigInt; + impl Pow<&$T> for BigInt { + type Output = BigInt; #[inline] - fn pow(self, rhs: &$T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, rhs), self.data.pow(rhs)) + fn pow(self, rhs: &$T) -> BigInt { + BigInt::::from_biguint(powsign(self.sign, rhs), self.data.pow(rhs)) } } - impl Pow<$T> for &BigInt { - type Output = BigInt; + impl Pow<$T> for &BigInt { + type Output = BigInt; #[inline] - fn pow(self, rhs: $T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, &rhs), Pow::pow(&self.data, rhs)) + fn pow(self, rhs: $T) -> BigInt { + BigInt::::from_biguint(powsign(self.sign, &rhs), Pow::pow(&self.data, rhs)) } } - impl Pow<&$T> for &BigInt { - type Output = BigInt; + impl Pow<&$T> for &BigInt { + type Output = BigInt; #[inline] - fn pow(self, rhs: &$T) -> BigInt { - BigInt::from_biguint(powsign(self.sign, rhs), Pow::pow(&self.data, rhs)) + fn pow(self, rhs: &$T) -> BigInt { + BigInt::::from_biguint(powsign(self.sign, rhs), Pow::pow(&self.data, rhs)) } } }; @@ -66,9 +66,13 @@ pow_impl!(u32); pow_impl!(u64); pow_impl!(usize); pow_impl!(u128); -pow_impl!(BigUint); +pow_impl!(BigUint); -pub(super) fn modpow(x: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt { +pub(super) fn modpow( + x: &BigInt, + exponent: &BigInt, + modulus: &BigInt, +) -> BigInt { assert!( !exponent.is_negative(), "negative exponentiation is not supported!" diff --git a/src/bigint/shift.rs b/src/bigint/shift.rs index 22bb7443..865ec701 100644 --- a/src/bigint/shift.rs +++ b/src/bigint/shift.rs @@ -6,23 +6,23 @@ use num_traits::{PrimInt, Signed, Zero}; macro_rules! impl_shift { (@ref $Shx:ident :: $shx:ident, $ShxAssign:ident :: $shx_assign:ident, $rhs:ty) => { - impl $Shx<&$rhs> for BigInt { - type Output = BigInt; + impl $Shx<&$rhs> for BigInt { + type Output = BigInt; #[inline] - fn $shx(self, rhs: &$rhs) -> BigInt { + fn $shx(self, rhs: &$rhs) -> BigInt { $Shx::$shx(self, *rhs) } } - impl $Shx<&$rhs> for &BigInt { - type Output = BigInt; + impl $Shx<&$rhs> for &BigInt { + type Output = BigInt; #[inline] - fn $shx(self, rhs: &$rhs) -> BigInt { + fn $shx(self, rhs: &$rhs) -> BigInt { $Shx::$shx(self, *rhs) } } - impl $ShxAssign<&$rhs> for BigInt { + impl $ShxAssign<&$rhs> for BigInt { #[inline] fn $shx_assign(&mut self, rhs: &$rhs) { $ShxAssign::$shx_assign(self, *rhs); @@ -30,23 +30,23 @@ macro_rules! impl_shift { } }; ($($rhs:ty),+) => {$( - impl Shl<$rhs> for BigInt { - type Output = BigInt; + impl Shl<$rhs> for BigInt { + type Output = BigInt; #[inline] - fn shl(self, rhs: $rhs) -> BigInt { - BigInt::from_biguint(self.sign, self.data << rhs) + fn shl(self, rhs: $rhs) -> BigInt { + BigInt::::from_biguint(self.sign, self.data << rhs) } } - impl Shl<$rhs> for &BigInt { - type Output = BigInt; + impl Shl<$rhs> for &BigInt { + type Output = BigInt; #[inline] - fn shl(self, rhs: $rhs) -> BigInt { - BigInt::from_biguint(self.sign, &self.data << rhs) + fn shl(self, rhs: $rhs) -> BigInt { + BigInt::::from_biguint(self.sign, &self.data << rhs) } } - impl ShlAssign<$rhs> for BigInt { + impl ShlAssign<$rhs> for BigInt { #[inline] fn shl_assign(&mut self, rhs: $rhs) { self.data <<= rhs @@ -54,29 +54,29 @@ macro_rules! impl_shift { } impl_shift! { @ref Shl::shl, ShlAssign::shl_assign, $rhs } - impl Shr<$rhs> for BigInt { - type Output = BigInt; + impl Shr<$rhs> for BigInt { + type Output = BigInt; #[inline] - fn shr(self, rhs: $rhs) -> BigInt { + fn shr(self, rhs: $rhs) -> BigInt { let round_down = shr_round_down(&self, rhs); let data = self.data >> rhs; let data = if round_down { data + 1u8 } else { data }; BigInt::from_biguint(self.sign, data) } } - impl Shr<$rhs> for &BigInt { - type Output = BigInt; + impl Shr<$rhs> for &BigInt { + type Output = BigInt; #[inline] - fn shr(self, rhs: $rhs) -> BigInt { + fn shr(self, rhs: $rhs) -> BigInt { let round_down = shr_round_down(self, rhs); let data = &self.data >> rhs; let data = if round_down { data + 1u8 } else { data }; BigInt::from_biguint(self.sign, data) } } - impl ShrAssign<$rhs> for BigInt { + impl ShrAssign<$rhs> for BigInt { #[inline] fn shr_assign(&mut self, rhs: $rhs) { let round_down = shr_round_down(self, rhs); @@ -97,7 +97,7 @@ impl_shift! { i8, i16, i32, i64, i128, isize } // Negative values need a rounding adjustment if there are any ones in the // bits that are getting shifted out. -fn shr_round_down(i: &BigInt, shift: T) -> bool { +fn shr_round_down(i: &BigInt, shift: T) -> bool { if i.is_negative() { let zeros = i.trailing_zeros().expect("negative values are non-zero"); shift > T::zero() && shift.to_u64().map(|shift| zeros < shift).unwrap_or(true) diff --git a/src/bigint/subtraction.rs b/src/bigint/subtraction.rs index 1fb240d8..a9e05aef 100644 --- a/src/bigint/subtraction.rs +++ b/src/bigint/subtraction.rs @@ -29,11 +29,11 @@ macro_rules! bigint_sub { }; } -impl Sub<&BigInt> for &BigInt { - type Output = BigInt; +impl Sub<&BigInt> for &BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: &BigInt) -> BigInt { + fn sub(self, other: &BigInt) -> BigInt { bigint_sub!( self, self.clone(), @@ -45,65 +45,65 @@ impl Sub<&BigInt> for &BigInt { } } -impl Sub for &BigInt { - type Output = BigInt; +impl Sub> for &BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { bigint_sub!(self, self.clone(), &self.data, other, other, other.data) } } -impl Sub<&BigInt> for BigInt { - type Output = BigInt; +impl Sub<&BigInt> for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: &BigInt) -> BigInt { + fn sub(self, other: &BigInt) -> BigInt { bigint_sub!(self, self, self.data, other, other.clone(), &other.data) } } -impl Sub for BigInt { - type Output = BigInt; +impl Sub> for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { bigint_sub!(self, self, self.data, other, other, other.data) } } -impl SubAssign<&BigInt> for BigInt { +impl SubAssign<&BigInt> for BigInt { #[inline] - fn sub_assign(&mut self, other: &BigInt) { + fn sub_assign(&mut self, other: &BigInt) { let n = mem::replace(self, Self::zero()); *self = n - other; } } -forward_val_assign!(impl SubAssign for BigInt, sub_assign); +forward_val_assign!(impl SubAssign for BigInt, sub_assign); -promote_all_scalars!(impl Sub for BigInt, sub); -promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign); -forward_all_scalar_binop_to_val_val!(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); +promote_all_scalars!(impl Sub for BigInt, sub); +promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign); +forward_all_scalar_binop_to_val_val!(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; +impl Sub for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: u32) -> BigInt { + fn sub(self, other: u32) -> BigInt { match self.sign { - NoSign => -BigInt::from(other), - Minus => -BigInt::from(self.data + other), + NoSign => -BigInt::::from(other), + Minus => -BigInt::::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Self::zero(), - Greater => BigInt::from(self.data - other), - Less => -BigInt::from(other - self.data), + Greater => BigInt::::from(self.data - other), + Less => -BigInt::::from(other - self.data), }, } } } -impl SubAssign for BigInt { +impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u32) { let n = mem::replace(self, Self::zero()); @@ -111,51 +111,51 @@ impl SubAssign for BigInt { } } -impl Sub for u32 { - type Output = BigInt; +impl Sub> for u32 { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { -(other - self) } } -impl Sub for u64 { - type Output = BigInt; +impl Sub> for u64 { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { -(other - self) } } -impl Sub for u128 { - type Output = BigInt; +impl Sub> for u128 { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { -(other - self) } } -impl Sub for BigInt { - type Output = BigInt; +impl Sub for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: u64) -> BigInt { + fn sub(self, other: u64) -> BigInt { match self.sign { - NoSign => -BigInt::from(other), - Minus => -BigInt::from(self.data + other), + NoSign => -BigInt::::from(other), + Minus => -BigInt::::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Self::zero(), - Greater => BigInt::from(self.data - other), - Less => -BigInt::from(other - self.data), + Greater => BigInt::::from(self.data - other), + Less => -BigInt::::from(other - self.data), }, } } } -impl SubAssign for BigInt { +impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u64) { let n = mem::replace(self, Self::zero()); @@ -163,11 +163,11 @@ impl SubAssign for BigInt { } } -impl Sub for BigInt { - type Output = BigInt; +impl Sub for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: u128) -> BigInt { + fn sub(self, other: u128) -> BigInt { match self.sign { NoSign => -BigInt::from(other), Minus => -BigInt::from(self.data + other), @@ -180,7 +180,7 @@ impl Sub for BigInt { } } -impl SubAssign for BigInt { +impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u128) { let n = mem::replace(self, Self::zero()); @@ -188,22 +188,22 @@ impl SubAssign for BigInt { } } -forward_all_scalar_binop_to_val_val!(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); +forward_all_scalar_binop_to_val_val!(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; +impl Sub for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: i32) -> BigInt { + fn sub(self, other: i32) -> BigInt { match other.checked_uabs() { Positive(u) => self - u, Negative(u) => self + u, } } } -impl SubAssign for BigInt { +impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: i32) { match other.checked_uabs() { @@ -213,11 +213,11 @@ impl SubAssign for BigInt { } } -impl Sub for i32 { - type Output = BigInt; +impl Sub> for i32 { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u - other, Negative(u) => -other - u, @@ -225,18 +225,18 @@ impl Sub for i32 { } } -impl Sub for BigInt { - type Output = BigInt; +impl Sub for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: i64) -> BigInt { + fn sub(self, other: i64) -> BigInt { match other.checked_uabs() { Positive(u) => self - u, Negative(u) => self + u, } } } -impl SubAssign for BigInt { +impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: i64) { match other.checked_uabs() { @@ -246,11 +246,11 @@ impl SubAssign for BigInt { } } -impl Sub for i64 { - type Output = BigInt; +impl Sub> for i64 { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u - other, Negative(u) => -other - u, @@ -258,11 +258,11 @@ impl Sub for i64 { } } -impl Sub for BigInt { - type Output = BigInt; +impl Sub for BigInt { + type Output = BigInt; #[inline] - fn sub(self, other: i128) -> BigInt { + fn sub(self, other: i128) -> BigInt { match other.checked_uabs() { Positive(u) => self - u, Negative(u) => self + u, @@ -270,7 +270,7 @@ impl Sub for BigInt { } } -impl SubAssign for BigInt { +impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: i128) { match other.checked_uabs() { @@ -280,11 +280,11 @@ impl SubAssign for BigInt { } } -impl Sub for i128 { - type Output = BigInt; +impl Sub> for i128 { + type Output = BigInt; #[inline] - fn sub(self, other: BigInt) -> BigInt { + fn sub(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u - other, Negative(u) => -other - u, @@ -292,9 +292,9 @@ impl Sub for i128 { } } -impl CheckedSub for BigInt { +impl CheckedSub for BigInt { #[inline] - fn checked_sub(&self, v: &BigInt) -> Option { + fn checked_sub(&self, v: &BigInt) -> Option> { Some(self.sub(v)) } } diff --git a/src/biguint.rs b/src/biguint.rs index 2e63d01b..3871c5cb 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2,9 +2,6 @@ use crate::big_digit::{self, BigDigit}; use alloc::string::String; use alloc::vec::Vec; -use tinyvec::tiny_vec; -use tinyvec::ArrayVec; -use tinyvec::TinyVec; use core::cmp; use core::cmp::Ordering; use core::default::Default; @@ -12,9 +9,11 @@ use core::fmt; use core::hash; use core::mem; use core::str; +use tinyvec::tiny_vec; +use tinyvec::TinyVec; use num_integer::{Integer, Roots}; -use num_traits::{ConstZero, Num, One, Pow, ToPrimitive, Unsigned, Zero}; +use num_traits::{Num, One, Pow, ToPrimitive, Unsigned, Zero}; mod addition; mod division; @@ -33,31 +32,24 @@ mod shift; pub(crate) use self::convert::to_str_radix_reversed; pub use self::iter::{U32Digits, U64Digits}; -pub const NDIGITS: usize = 32; +pub const NLIMBS: usize = 32; /// A big unsigned integer type. -pub struct BigUint { +pub struct BigUint { data: TinyVec<[u64; N]>, } -// impl Drop for BigUint { -// fn drop(&mut self) { -// if self.data.capacity() > NDIGITS { -// eprintln!("len={:?}", self.data.capacity()); -// } -// } -// } - -// impl BigUint { -// pub fn take_data(self) -> TinyVec<[u64; NDIGITS]> { -// let Self { data } = self; -// data -// } -// } +impl BigUint { + pub fn to_digits(&self) -> BigUint { + BigUint { + data: self.data.iter().copied().collect(), + } + } +} // Note: derived `Clone` doesn't specialize `clone_from`, // but we want to keep the allocation in `data`. -impl Clone for BigUint { +impl Clone for BigUint { #[inline] fn clone(&self) -> Self { BigUint { @@ -71,7 +63,7 @@ impl Clone for BigUint { } } -impl hash::Hash for BigUint { +impl hash::Hash for BigUint { #[inline] fn hash(&self, state: &mut H) { debug_assert!(self.data.last() != Some(&0)); @@ -79,26 +71,26 @@ impl hash::Hash for BigUint { } } -impl PartialEq for BigUint { +impl PartialEq for BigUint { #[inline] - fn eq(&self, other: &BigUint) -> bool { + fn eq(&self, other: &BigUint) -> bool { debug_assert!(self.data.last() != Some(&0)); debug_assert!(other.data.last() != Some(&0)); self.data == other.data } } -impl Eq for BigUint {} +impl Eq for BigUint {} -impl PartialOrd for BigUint { +impl PartialOrd for BigUint { #[inline] - fn partial_cmp(&self, other: &BigUint) -> Option { + fn partial_cmp(&self, other: &BigUint) -> Option { Some(self.cmp(other)) } } -impl Ord for BigUint { +impl Ord for BigUint { #[inline] - fn cmp(&self, other: &BigUint) -> Ordering { + fn cmp(&self, other: &BigUint) -> Ordering { cmp_slice(&self.data[..], &other.data[..]) } } @@ -114,20 +106,20 @@ fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { } } -impl Default for BigUint { +impl Default for BigUint { #[inline] - fn default() -> BigUint { + fn default() -> BigUint { Self::zero() } } -impl fmt::Debug for BigUint { +impl fmt::Debug for BigUint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } -impl fmt::Display for BigUint { +impl fmt::Display for BigUint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad_integral(true, "", &self.to_str_radix(10)) } @@ -159,9 +151,9 @@ impl fmt::Octal for BigUint { } } -impl Zero for BigUint { +impl Zero for BigUint { #[inline] - fn zero() -> BigUint { + fn zero() -> BigUint { Self::zero() } @@ -181,9 +173,9 @@ impl Zero for BigUint { // const ZERO: Self = Self::ZERO; // BigUint { data: Vec::new() }; // } -impl One for BigUint { +impl One for BigUint { #[inline] - fn one() -> BigUint { + fn one() -> BigUint { BigUint { data: tiny_vec![1] } } @@ -199,33 +191,33 @@ impl One for BigUint { } } -impl Unsigned for BigUint {} +impl Unsigned for BigUint {} -impl Integer for BigUint { +impl Integer for BigUint { #[inline] - fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { + fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { division::div_rem_ref(self, other) } #[inline] - fn div_floor(&self, other: &BigUint) -> BigUint { + fn div_floor(&self, other: &BigUint) -> BigUint { let (d, _) = division::div_rem_ref(self, other); d } #[inline] - fn mod_floor(&self, other: &BigUint) -> BigUint { + fn mod_floor(&self, other: &BigUint) -> BigUint { let (_, m) = division::div_rem_ref(self, other); m } #[inline] - fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) { + fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) { division::div_rem_ref(self, other) } #[inline] - fn div_ceil(&self, other: &BigUint) -> BigUint { + fn div_ceil(&self, other: &BigUint) -> BigUint { let (d, m) = division::div_rem_ref(self, other); if m.is_zero() { d @@ -240,7 +232,7 @@ impl Integer for BigUint { #[inline] fn gcd(&self, other: &Self) -> Self { #[inline] - fn twos(x: &BigUint) -> u64 { + fn twos(x: &BigUint) -> u64 { x.trailing_zeros().unwrap_or(0) } @@ -274,7 +266,7 @@ impl Integer for BigUint { /// Calculates the Lowest Common Multiple (LCM) of the number and `other`. #[inline] - fn lcm(&self, other: &BigUint) -> BigUint { + fn lcm(&self, other: &BigUint) -> BigUint { if self.is_zero() && other.is_zero() { Self::zero() } else { @@ -297,13 +289,13 @@ impl Integer for BigUint { /// Deprecated, use `is_multiple_of` instead. #[inline] - fn divides(&self, other: &BigUint) -> bool { + 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 { + fn is_multiple_of(&self, other: &BigUint) -> bool { if other.is_zero() { return self.is_zero(); } @@ -352,9 +344,9 @@ impl Integer for BigUint { } #[inline] -fn fixpoint(mut x: BigUint, max_bits: u64, f: F) -> BigUint +fn fixpoint(mut x: BigUint, max_bits: u64, f: F) -> BigUint where - F: Fn(&BigUint) -> BigUint, + F: Fn(&BigUint) -> BigUint, { let mut xn = f(&x); @@ -380,7 +372,7 @@ where x } -impl Roots for BigUint { +impl Roots for BigUint { // nth_root, sqrt and cbrt use Newton's method to compute // principal root of a given degree for a given integer. @@ -548,13 +540,15 @@ pub trait ToBigUint { // } #[inline] -pub(crate) fn biguint_from_tinyvec(digits: TinyVec<[BigDigit; NDIGITS]>) -> BigUint { +pub(crate) fn biguint_from_tinyvec(digits: TinyVec<[BigDigit; N]>) -> BigUint { BigUint { data: digits }.normalized() } -impl BigUint { +impl BigUint { pub fn zero() -> Self { - BigUint { data: [].into_iter().collect() } + BigUint { + data: [].into_iter().collect(), + } } // /// A constant `BigUint` with value 0, useful for static initialization. @@ -564,7 +558,7 @@ impl BigUint { /// /// The base 232 digits are ordered least significant digit first. #[inline] - pub fn new(digits: Vec) -> BigUint { + pub fn new(digits: Vec) -> BigUint { let mut big = Self::zero(); cfg_digit_expr!( @@ -582,7 +576,7 @@ impl BigUint { /// /// The base 232 digits are ordered least significant digit first. #[inline] - pub fn from_slice(slice: &[u32]) -> BigUint { + pub fn from_slice(slice: &[u32]) -> BigUint { let mut big = Self::zero(); big.assign_from_slice(slice); big @@ -622,7 +616,7 @@ impl BigUint { /// BigUint::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); /// ``` #[inline] - pub fn from_bytes_be(bytes: &[u8]) -> BigUint { + pub fn from_bytes_be(bytes: &[u8]) -> BigUint { if bytes.is_empty() { Self::zero() } else { @@ -636,11 +630,11 @@ impl BigUint { /// /// The bytes are in little-endian byte order. #[inline] - pub fn from_bytes_le(bytes: &[u8]) -> BigUint { + pub fn from_bytes_le(bytes: &[u8]) -> BigUint { if bytes.is_empty() { Self::zero() } else { - convert::from_bitwise_digits_le(bytes, 8) + convert::from_bitwise_digits_le::(bytes, 8) } } @@ -661,7 +655,7 @@ impl BigUint { /// assert_eq!(BigUint::parse_bytes(b"G", 16), None); /// ``` #[inline] - pub fn parse_bytes(buf: &[u8], radix: u32) -> Option { + pub fn parse_bytes(buf: &[u8], radix: u32) -> Option> { let s = str::from_utf8(buf).ok()?; BigUint::from_str_radix(s, radix).ok() } @@ -682,7 +676,7 @@ impl BigUint { /// 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 { + pub fn from_radix_be(buf: &[u8], radix: u32) -> Option> { convert::from_radix_be(buf, radix) } @@ -702,7 +696,7 @@ impl BigUint { /// 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 { + pub fn from_radix_le(buf: &[u8], radix: u32) -> Option> { convert::from_radix_le(buf, radix) } @@ -887,7 +881,7 @@ impl BigUint { /// Strips off trailing zero bigdigits - comparisons require the last element in the vector to /// be nonzero. #[inline] - fn normalize(&mut self) { + pub(crate) fn normalize(&mut self) { if let Some(&0) = self.data.last() { let len = self.data.iter().rposition(|&d| d != 0).map_or(0, |i| i + 1); self.data.truncate(len); @@ -899,7 +893,7 @@ impl BigUint { /// Returns a normalized [`BigUint`]. #[inline] - fn normalized(mut self) -> BigUint { + fn normalized(mut self) -> BigUint { self.normalize(); self } @@ -1097,33 +1091,36 @@ impl num_traits::ToBytes for BigUint { } } -pub(crate) trait IntDigits { - fn digits(&self) -> &[BigDigit]; - fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; NDIGITS]>; - fn normalize(&mut self); - fn capacity(&self) -> usize; - fn len(&self) -> usize; -} +// pub(crate) trait IntDigits { +// fn digits(&self) -> &[BigDigit]; +// fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; NLIMBS]>; +// fn normalize(&mut self); +// fn capacity(&self) -> usize; +// fn len(&self) -> usize; +// } + +// impl IntDigits for BigUint { +impl BigUint { + // const N: usize = N; -impl IntDigits for BigUint { #[inline] - fn digits(&self) -> &[BigDigit] { + pub(crate) fn digits(&self) -> &[BigDigit] { &self.data } #[inline] - fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; NDIGITS]> { + pub(crate) fn digits_mut(&mut self) -> &mut TinyVec<[BigDigit; N]> { &mut self.data } + // #[inline] + // pub(crate) fn normalize(&mut self) { + // self.normalize(); + // } #[inline] - fn normalize(&mut self) { - self.normalize(); - } - #[inline] - fn capacity(&self) -> usize { + pub(crate) fn capacity(&self) -> usize { self.data.capacity() } #[inline] - fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.data.len() } } @@ -1178,7 +1175,7 @@ cfg_digit!( fn test_from_slice() { fn check(slice: &[u32], data: &[BigDigit]) { assert_eq!( - BigUint::from_slice(slice).data, + BigUint::<32>::from_slice(slice).data, data, "from {:?}, to {:?}", slice, diff --git a/src/biguint/addition.rs b/src/biguint/addition.rs index b6711314..89026ba3 100644 --- a/src/biguint/addition.rs +++ b/src/biguint/addition.rs @@ -1,4 +1,4 @@ -use super::{BigUint, IntDigits}; +use super::BigUint; use crate::big_digit::{self, BigDigit}; use crate::UsizePromotion; @@ -85,20 +85,20 @@ pub(super) fn add2(a: &mut [BigDigit], b: &[BigDigit]) { debug_assert!(carry == 0); } -forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); -forward_val_assign!(impl AddAssign for BigUint, add_assign); +forward_all_binop_to_val_ref_commutative!(impl Add for BigUint, add); +forward_val_assign!(impl AddAssign for BigUint, add_assign); -impl Add<&BigUint> for BigUint { - type Output = BigUint; +impl Add<&BigUint> for BigUint { + type Output = BigUint; - fn add(mut self, other: &BigUint) -> BigUint { + fn add(mut self, other: &BigUint) -> BigUint { self += other; self } } -impl AddAssign<&BigUint> for BigUint { +impl AddAssign<&BigUint> for BigUint { #[inline] - fn add_assign(&mut self, other: &BigUint) { + fn add_assign(&mut self, other: &BigUint) { let self_len = self.data.len(); let carry = if self_len < other.data.len() { let lo_carry = __add2(&mut self.data[..], &other.data[..self_len]); @@ -113,23 +113,23 @@ impl AddAssign<&BigUint> for BigUint { } } -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); -forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); +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); +forward_all_scalar_binop_to_val_val_commutative!(impl Add for BigUint, add); -impl Add for BigUint { - type Output = BigUint; +impl Add for BigUint { + type Output = BigUint; #[inline] - fn add(mut self, other: u32) -> BigUint { + fn add(mut self, other: u32) -> BigUint { self += other; self } } -impl AddAssign for BigUint { +impl AddAssign for BigUint { #[inline] fn add_assign(&mut self, other: u32) { if other != 0 { @@ -145,17 +145,17 @@ impl AddAssign for BigUint { } } -impl Add for BigUint { - type Output = BigUint; +impl Add for BigUint { + type Output = BigUint; #[inline] - fn add(mut self, other: u64) -> BigUint { + fn add(mut self, other: u64) -> BigUint { self += other; self } } -impl AddAssign for BigUint { +impl AddAssign for BigUint { cfg_digit!( #[inline] fn add_assign(&mut self, other: u64) { @@ -190,17 +190,17 @@ impl AddAssign for BigUint { ); } -impl Add for BigUint { - type Output = BigUint; +impl Add for BigUint { + type Output = BigUint; #[inline] - fn add(mut self, other: u128) -> BigUint { + fn add(mut self, other: u128) -> BigUint { self += other; self } } -impl AddAssign for BigUint { +impl AddAssign for BigUint { cfg_digit!( #[inline] fn add_assign(&mut self, other: u128) { @@ -246,9 +246,9 @@ impl AddAssign for BigUint { ); } -impl CheckedAdd for BigUint { +impl CheckedAdd for BigUint { #[inline] - fn checked_add(&self, v: &BigUint) -> Option { + fn checked_add(&self, v: &BigUint) -> Option> { Some(self.add(v)) } } diff --git a/src/biguint/arbitrary.rs b/src/biguint/arbitrary.rs index 9d5c5ccf..11e523f2 100644 --- a/src/biguint/arbitrary.rs +++ b/src/biguint/arbitrary.rs @@ -9,7 +9,7 @@ use alloc::vec::Vec; #[cfg(feature = "quickcheck")] #[cfg_attr(docsrs, doc(cfg(feature = "quickcheck")))] -impl quickcheck::Arbitrary for BigUint { +impl quickcheck::Arbitrary for BigUint { fn arbitrary(g: &mut quickcheck::Gen) -> Self { // Use arbitrary from Vec biguint_from_vec(Vec::::arbitrary(g)) @@ -23,7 +23,7 @@ impl quickcheck::Arbitrary for BigUint { #[cfg(feature = "arbitrary")] #[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))] -impl arbitrary::Arbitrary<'_> for BigUint { +impl arbitrary::Arbitrary<'_> for BigUint { fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result { Ok(biguint_from_vec(Vec::::arbitrary(u)?)) } diff --git a/src/biguint/bits.rs b/src/biguint/bits.rs index 42d7ec0c..28b27e37 100644 --- a/src/biguint/bits.rs +++ b/src/biguint/bits.rs @@ -1,17 +1,17 @@ -use super::{BigUint, IntDigits}; +use super::BigUint; use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; -forward_val_val_binop!(impl BitAnd for BigUint, bitand); -forward_ref_val_binop!(impl BitAnd for BigUint, bitand); +forward_val_val_binop!(impl BitAnd for BigUint, bitand); +forward_ref_val_binop!(impl BitAnd for BigUint, bitand); // do not use forward_ref_ref_binop_commutative! for bitand so that we can // clone the smaller value rather than the larger, avoiding over-allocation -impl BitAnd<&BigUint> for &BigUint { - type Output = BigUint; +impl BitAnd<&BigUint> for &BigUint { + type Output = BigUint; #[inline] - fn bitand(self, other: &BigUint) -> BigUint { + fn bitand(self, other: &BigUint) -> BigUint { // forward to val-ref, choosing the smaller to clone if self.data.len() <= other.data.len() { self.clone() & other @@ -21,20 +21,20 @@ impl BitAnd<&BigUint> for &BigUint { } } -forward_val_assign!(impl BitAndAssign for BigUint, bitand_assign); +forward_val_assign!(impl BitAndAssign for BigUint, bitand_assign); -impl BitAnd<&BigUint> for BigUint { - type Output = BigUint; +impl BitAnd<&BigUint> for BigUint { + type Output = BigUint; #[inline] - fn bitand(mut self, other: &BigUint) -> BigUint { + fn bitand(mut self, other: &BigUint) -> BigUint { self &= other; self } } -impl BitAndAssign<&BigUint> for BigUint { +impl BitAndAssign<&BigUint> for BigUint { #[inline] - fn bitand_assign(&mut self, other: &BigUint) { + fn bitand_assign(&mut self, other: &BigUint) { for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { *ai &= bi; } @@ -43,20 +43,20 @@ impl BitAndAssign<&BigUint> for BigUint { } } -forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor); -forward_val_assign!(impl BitOrAssign for BigUint, bitor_assign); +forward_all_binop_to_val_ref_commutative!(impl BitOr for BigUint, bitor); +forward_val_assign!(impl BitOrAssign for BigUint, bitor_assign); -impl BitOr<&BigUint> for BigUint { - type Output = BigUint; +impl BitOr<&BigUint> for BigUint { + type Output = BigUint; - fn bitor(mut self, other: &BigUint) -> BigUint { + fn bitor(mut self, other: &BigUint) -> BigUint { self |= other; self } } -impl BitOrAssign<&BigUint> for BigUint { +impl BitOrAssign<&BigUint> for BigUint { #[inline] - fn bitor_assign(&mut self, other: &BigUint) { + fn bitor_assign(&mut self, other: &BigUint) { for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { *ai |= bi; } @@ -67,20 +67,20 @@ impl BitOrAssign<&BigUint> for BigUint { } } -forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor); -forward_val_assign!(impl BitXorAssign for BigUint, bitxor_assign); +forward_all_binop_to_val_ref_commutative!(impl BitXor for BigUint, bitxor); +forward_val_assign!(impl BitXorAssign for BigUint, bitxor_assign); -impl BitXor<&BigUint> for BigUint { - type Output = BigUint; +impl BitXor<&BigUint> for BigUint { + type Output = BigUint; - fn bitxor(mut self, other: &BigUint) -> BigUint { + fn bitxor(mut self, other: &BigUint) -> BigUint { self ^= other; self } } -impl BitXorAssign<&BigUint> for BigUint { +impl BitXorAssign<&BigUint> for BigUint { #[inline] - fn bitxor_assign(&mut self, other: &BigUint) { + fn bitxor_assign(&mut self, other: &BigUint) { for (ai, &bi) in self.data.iter_mut().zip(other.data.iter()) { *ai ^= bi; } diff --git a/src/biguint/convert.rs b/src/biguint/convert.rs index 5b783929..31fa29fb 100644 --- a/src/biguint/convert.rs +++ b/src/biguint/convert.rs @@ -12,7 +12,6 @@ use crate::ParseBigIntError; use crate::TryFromBigIntError; use alloc::vec::Vec; -use tinyvec::TinyVec; use core::cmp::Ordering::{Equal, Greater, Less}; use core::convert::TryFrom; use core::mem; @@ -20,6 +19,7 @@ use core::str::FromStr; use num_integer::{Integer, Roots}; use num_traits::float::FloatCore; use num_traits::{FromPrimitive, Num, One, PrimInt, ToPrimitive, Zero}; +use tinyvec::TinyVec; /// Find last set bit /// fls(0) == 0, fls(u32::MAX) == 32 @@ -31,18 +31,18 @@ fn ilog2(v: T) -> u8 { fls(v) - 1 } -impl FromStr for BigUint { +impl FromStr for BigUint { type Err = ParseBigIntError; #[inline] - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result, ParseBigIntError> { BigUint::from_str_radix(s, 10) } } // Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides // BigDigit::BITS -pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { +pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits == 0); debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); @@ -63,14 +63,14 @@ pub(super) fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { // 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: u8) -> BigUint { +fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { debug_assert!(!v.is_empty() && bits <= 8 && big_digit::BITS % bits != 0); debug_assert!(v.iter().all(|&c| BigDigit::from(c) < (1 << bits))); - let total_bits = (v.len() as u64).saturating_mul(bits.into()); - let big_digits = Integer::div_ceil(&total_bits, &big_digit::BITS.into()) - .to_usize() - .unwrap_or(usize::MAX); + // let total_bits = (v.len() as u64).saturating_mul(bits.into()); + // let big_digits = Integer::div_ceil(&total_bits, &big_digit::BITS.into()) + // .to_usize() + // .unwrap_or(usize::MAX); let mut data = TinyVec::new(); // let mut data = Vec::with_capacity(big_digits); @@ -101,23 +101,23 @@ fn from_inexact_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { } // Read little-endian radix digits -fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { +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| u32::from(c) < radix)); // Estimate how big the result will be, so we can pre-allocate it. - #[cfg(feature = "std")] - let big_digits = { - let radix_log2 = f64::from(radix).log2(); - let bits = radix_log2 * v.len() as f64; - (bits / big_digit::BITS as f64).ceil() - }; - #[cfg(not(feature = "std"))] - let big_digits = { - let radix_log2 = ilog2(radix.next_power_of_two()) as usize; - let bits = radix_log2 * v.len(); - (bits / big_digit::BITS as usize) + 1 - }; + // #[cfg(feature = "std")] + // let big_digits = { + // let radix_log2 = f64::from(radix).log2(); + // let bits = radix_log2 * v.len() as f64; + // (bits / big_digit::BITS as f64).ceil() + // }; + // #[cfg(not(feature = "std"))] + // let big_digits = { + // let radix_log2 = ilog2(radix.next_power_of_two()) as usize; + // let bits = radix_log2 * v.len(); + // (bits / big_digit::BITS as usize) + 1 + // }; let mut data = TinyVec::new(); // let mut data = Vec::with_capacity(big_digits.to_usize().unwrap_or(0)); @@ -155,7 +155,7 @@ fn from_radix_digits_be(v: &[u8], radix: u32) -> BigUint { biguint_from_tinyvec(data) } -pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option { +pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option> { assert!( 2 <= radix && radix <= 256, "The radix must be within 2...256" @@ -186,7 +186,7 @@ pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option { Some(res) } -pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option { +pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option> { assert!( 2 <= radix && radix <= 256, "The radix must be within 2...256" @@ -217,11 +217,11 @@ pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option { Some(res) } -impl Num for BigUint { +impl Num for BigUint { type FromStrRadixErr = ParseBigIntError; /// Creates and initializes a `BigUint`. - fn from_str_radix(s: &str, radix: u32) -> Result { + fn from_str_radix(s: &str, radix: u32) -> Result, ParseBigIntError> { assert!(2 <= radix && radix <= 36, "The radix must be within 2...36"); let mut s = s; if let Some(tail) = s.strip_prefix('+') { @@ -272,7 +272,7 @@ impl Num for BigUint { } } -fn high_bits_to_u64(v: &BigUint) -> u64 { +fn high_bits_to_u64(v: &BigUint) -> u64 { match v.data.len() { 0 => 0, 1 => { @@ -322,7 +322,7 @@ fn high_bits_to_u64(v: &BigUint) -> u64 { } } -impl ToPrimitive for BigUint { +impl ToPrimitive for BigUint { #[inline] fn to_i64(&self) -> Option { self.to_u64().as_ref().and_then(u64::to_i64) @@ -430,9 +430,9 @@ impl_try_from_biguint!(i64, ToPrimitive::to_i64); impl_try_from_biguint!(isize, ToPrimitive::to_isize); impl_try_from_biguint!(i128, ToPrimitive::to_i128); -impl FromPrimitive for BigUint { +impl FromPrimitive for BigUint { #[inline] - fn from_i64(n: i64) -> Option { + fn from_i64(n: i64) -> Option> { if n >= 0 { Some(BigUint::from(n as u64)) } else { @@ -441,7 +441,7 @@ impl FromPrimitive for BigUint { } #[inline] - fn from_i128(n: i128) -> Option { + fn from_i128(n: i128) -> Option> { if n >= 0 { Some(BigUint::from(n as u128)) } else { @@ -450,17 +450,17 @@ impl FromPrimitive for BigUint { } #[inline] - fn from_u64(n: u64) -> Option { + fn from_u64(n: u64) -> Option> { Some(BigUint::from(n)) } #[inline] - fn from_u128(n: u128) -> Option { + fn from_u128(n: u128) -> Option> { Some(BigUint::from(n)) } #[inline] - fn from_f64(mut n: f64) -> Option { + fn from_f64(mut n: f64) -> Option> { // handle NAN, INFINITY, NEG_INFINITY if !n.is_finite() { return None; @@ -490,10 +490,10 @@ impl FromPrimitive for BigUint { } } -impl From for BigUint { +impl From for BigUint { #[inline] fn from(mut n: u64) -> Self { - let mut ret: BigUint = Self::zero(); + let mut ret: BigUint = Self::zero(); while n != 0 { ret.data.push(n as BigDigit); @@ -505,10 +505,10 @@ impl From for BigUint { } } -impl From for BigUint { +impl From for BigUint { #[inline] fn from(mut n: u128) -> Self { - let mut ret: BigUint = Self::zero(); + let mut ret: BigUint = Self::zero(); while n != 0 { ret.data.push(n as BigDigit); @@ -521,7 +521,7 @@ impl From for BigUint { macro_rules! impl_biguint_from_uint { ($T:ty) => { - impl From<$T> for BigUint { + impl From<$T> for BigUint { #[inline] fn from(n: $T) -> Self { BigUint::from(n as u64) @@ -537,11 +537,11 @@ impl_biguint_from_uint!(usize); macro_rules! impl_biguint_try_from_int { ($T:ty, $from_ty:path) => { - impl TryFrom<$T> for BigUint { + impl TryFrom<$T> for BigUint { type Error = TryFromBigIntError<()>; #[inline] - fn try_from(value: $T) -> Result> { + fn try_from(value: $T) -> Result, TryFromBigIntError<()>> { $from_ty(value).ok_or(TryFromBigIntError::new(())) } } @@ -590,7 +590,7 @@ impl_to_biguint!(u128, FromPrimitive::from_u128); impl_to_biguint!(f32, FromPrimitive::from_f32); impl_to_biguint!(f64, FromPrimitive::from_f64); -impl From for BigUint { +impl From for BigUint { fn from(x: bool) -> Self { if x { One::one() @@ -601,7 +601,7 @@ impl From for BigUint { } // Extract bitwise digits that evenly divide BigDigit -pub(super) fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { +pub(super) fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits == 0); let last_i = u.data.len() - 1; @@ -629,7 +629,7 @@ pub(super) fn to_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { } // Extract bitwise digits that don't evenly divide BigDigit -fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { +fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { debug_assert!(!u.is_zero() && bits <= 8 && big_digit::BITS % bits != 0); let mask: BigDigit = (1 << bits) - 1; @@ -671,7 +671,7 @@ fn to_inexact_bitwise_digits_le(u: &BigUint, bits: u8) -> Vec { // Extract little-endian radix digits #[inline(always)] // forced inline to get const-prop for radix=10 -pub(super) fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { +pub(super) fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { debug_assert!(!u.is_zero() && !radix.is_power_of_two()); #[cfg(feature = "std")] @@ -750,7 +750,7 @@ pub(super) fn to_radix_digits_le(u: &BigUint, radix: u32) -> Vec { res } -pub(super) fn to_radix_le(u: &BigUint, radix: u32) -> Vec { +pub(super) fn to_radix_le(u: &BigUint, radix: u32) -> Vec { if u.is_zero() { vec![0] } else if radix.is_power_of_two() { @@ -770,7 +770,7 @@ pub(super) fn to_radix_le(u: &BigUint, radix: u32) -> Vec { } } -pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { +pub(crate) 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() { diff --git a/src/biguint/division.rs b/src/biguint/division.rs index 5a633fbb..355e93b6 100644 --- a/src/biguint/division.rs +++ b/src/biguint/division.rs @@ -82,7 +82,10 @@ fn div_half(rem: BigDigit, digit: BigDigit, divisor: BigDigit) -> (BigDigit, Big } #[inline] -pub(super) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) { +pub(super) fn div_rem_digit( + mut a: BigUint, + b: BigDigit, +) -> (BigUint, BigDigit) { if b == 0 { panic!("attempt to divide by zero") } @@ -107,7 +110,7 @@ pub(super) fn div_rem_digit(mut a: BigUint, b: BigDigit) -> (BigUint, BigDigit) } #[inline] -fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit { +fn rem_digit(a: &BigUint, b: BigDigit) -> BigDigit { if b == 0 { panic!("attempt to divide by zero") } @@ -158,7 +161,7 @@ fn sub_mul_digit_same_len(a: &mut [BigDigit], b: &[BigDigit], c: BigDigit) -> Bi big_digit::MAX - offset_carry } -fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { +fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { if d.is_zero() { panic!("attempt to divide by zero") } @@ -205,8 +208,10 @@ fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { } } - -pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { +pub(super) fn div_rem_ref( + u: &BigUint, + d: &BigUint, +) -> (BigUint, BigUint) { if d.is_zero() { panic!("attempt to divide by zero") } @@ -214,7 +219,13 @@ pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { return (BigUint::zero(), BigUint::zero()); } - assert!(u.data.is_inline(), "u.data.len={:?} u={:?}", u.data.len(), u); + // if + assert!( + u.data.is_inline(), + "u.data.len={:?} u={:?}", + u.data.len(), + u + ); if d.data.len() == 1 { if *d.data == [1] { @@ -252,7 +263,7 @@ pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { /// An implementation of the base division algorithm. /// Knuth, TAOCP vol 2 section 4.3.1, algorithm D, with an improvement from exercises 19-21. -fn div_rem_core(mut a: BigUint, b: &[BigDigit]) -> (BigUint, BigUint) { +fn div_rem_core(mut a: BigUint, b: &[BigDigit]) -> (BigUint, BigUint) { debug_assert!(a.data.len() >= b.len() && b.len() > 1); debug_assert!(b.last().unwrap().leading_zeros() == 0); @@ -345,63 +356,63 @@ fn div_rem_core(mut a: BigUint, b: &[BigDigit]) -> (BigUint, BigUint) { (q.normalized(), a) } -forward_val_ref_binop!(impl Div for BigUint, div); -forward_ref_val_binop!(impl Div for BigUint, div); -forward_val_assign!(impl DivAssign for BigUint, div_assign); +forward_val_ref_binop!(impl Div for BigUint, div); +forward_ref_val_binop!(impl Div for BigUint, div); +forward_val_assign!(impl DivAssign for BigUint, div_assign); -impl Div for BigUint { - type Output = BigUint; +impl Div> for BigUint { + type Output = BigUint; #[inline] - fn div(self, other: BigUint) -> BigUint { + fn div(self, other: BigUint) -> BigUint { let (q, _) = div_rem(self, other); q } } -impl Div<&BigUint> for &BigUint { - type Output = BigUint; +impl Div<&BigUint> for &BigUint { + type Output = BigUint; #[inline] - fn div(self, other: &BigUint) -> BigUint { + fn div(self, other: &BigUint) -> BigUint { let (q, _) = self.div_rem(other); q } } -impl DivAssign<&BigUint> for BigUint { +impl DivAssign<&BigUint> for BigUint { #[inline] - fn div_assign(&mut self, other: &BigUint) { + fn div_assign(&mut self, other: &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); -forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); +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); +forward_all_scalar_binop_to_val_val!(impl Div for BigUint, div); -impl Div for BigUint { - type Output = BigUint; +impl Div for BigUint { + type Output = BigUint; #[inline] - fn div(self, other: u32) -> BigUint { + fn div(self, other: u32) -> BigUint { let (q, _) = div_rem_digit(self, other as BigDigit); q } } -impl DivAssign for BigUint { +impl DivAssign for BigUint { #[inline] fn div_assign(&mut self, other: u32) { *self = &*self / other; } } -impl Div for u32 { - type Output = BigUint; +impl Div> for u32 { + type Output = BigUint; #[inline] - fn div(self, other: BigUint) -> BigUint { + fn div(self, other: BigUint) -> BigUint { match other.data.len() { 0 => panic!("attempt to divide by zero"), 1 => From::from(self as BigDigit / other.data[0]), @@ -410,16 +421,16 @@ impl Div for u32 { } } -impl Div for BigUint { - type Output = BigUint; +impl Div for BigUint { + type Output = BigUint; #[inline] - fn div(self, other: u64) -> BigUint { + fn div(self, other: u64) -> BigUint { let (q, _) = div_rem(self, From::from(other)); q } } -impl DivAssign for BigUint { +impl DivAssign for BigUint { #[inline] fn div_assign(&mut self, other: u64) { // a vec of size 0 does not allocate, so this is fairly cheap @@ -428,12 +439,12 @@ impl DivAssign for BigUint { } } -impl Div for u64 { - type Output = BigUint; +impl Div> for u64 { + type Output = BigUint; cfg_digit!( #[inline] - fn div(self, other: BigUint) -> BigUint { + fn div(self, other: BigUint) -> BigUint { match other.data.len() { 0 => panic!("attempt to divide by zero"), 1 => From::from(self / u64::from(other.data[0])), @@ -443,7 +454,7 @@ impl Div for u64 { } #[inline] - fn div(self, other: BigUint) -> BigUint { + fn div(self, other: BigUint) -> BigUint { match other.data.len() { 0 => panic!("attempt to divide by zero"), 1 => From::from(self / other.data[0]), @@ -453,29 +464,29 @@ impl Div for u64 { ); } -impl Div for BigUint { - type Output = BigUint; +impl Div for BigUint { + type Output = BigUint; #[inline] - fn div(self, other: u128) -> BigUint { + fn div(self, other: u128) -> BigUint { let (q, _) = div_rem(self, From::from(other)); q } } -impl DivAssign for BigUint { +impl DivAssign for BigUint { #[inline] fn div_assign(&mut self, other: u128) { *self = &*self / other; } } -impl Div for u128 { - type Output = BigUint; +impl Div> for u128 { + type Output = BigUint; cfg_digit!( #[inline] - fn div(self, other: BigUint) -> BigUint { + fn div(self, other: BigUint) -> BigUint { use super::u32_to_u128; match other.data.len() { 0 => panic!("attempt to divide by zero"), @@ -492,7 +503,7 @@ impl Div for u128 { } #[inline] - fn div(self, other: BigUint) -> BigUint { + fn div(self, other: BigUint) -> BigUint { match other.data.len() { 0 => panic!("attempt to divide by zero"), 1 => From::from(self / other.data[0] as u128), @@ -503,15 +514,15 @@ impl Div for u128 { ); } -forward_val_ref_binop!(impl Rem for BigUint, rem); -forward_ref_val_binop!(impl Rem for BigUint, rem); -forward_val_assign!(impl RemAssign for BigUint, rem_assign); +forward_val_ref_binop!(impl Rem for BigUint, rem); +forward_ref_val_binop!(impl Rem for BigUint, rem); +forward_val_assign!(impl RemAssign for BigUint, rem_assign); -impl Rem for BigUint { - type Output = BigUint; +impl Rem> for BigUint { + type Output = BigUint; #[inline] - fn rem(self, other: BigUint) -> BigUint { + fn rem(self, other: BigUint) -> BigUint { if let Some(other) = other.to_u32() { &self % other } else { @@ -521,11 +532,11 @@ impl Rem for BigUint { } } -impl Rem<&BigUint> for &BigUint { - type Output = BigUint; +impl Rem<&BigUint> for &BigUint { + type Output = BigUint; #[inline] - fn rem(self, other: &BigUint) -> BigUint { + fn rem(self, other: &BigUint) -> BigUint { if let Some(other) = other.to_u32() { self % other } else { @@ -534,39 +545,36 @@ impl Rem<&BigUint> for &BigUint { } } } -impl RemAssign<&BigUint> for BigUint { +impl RemAssign<&BigUint> for BigUint { #[inline] - fn rem_assign(&mut self, other: &BigUint) { + 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_ref_val!(impl Rem for BigUint, rem); -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; +promote_unsigned_scalars!(impl Rem for BigUint, rem); +promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign); +forward_all_scalar_binop_to_ref_val!(impl Rem for BigUint, rem); +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: u32) -> BigUint { + fn rem(self, other: u32) -> BigUint { rem_digit(self, other as BigDigit).into() } } -impl RemAssign for BigUint { +impl RemAssign for BigUint { #[inline] fn rem_assign(&mut self, other: u32) { *self = &*self % other; } } - -impl Rem<&BigUint> for u32 { - type Output = BigUint; - +impl Rem<&BigUint> for u32 { + type Output = BigUint; #[inline] - fn rem(mut self, other: &BigUint) -> BigUint { + fn rem(mut self, other: &BigUint) -> BigUint { self %= other; From::from(self) } @@ -574,10 +582,10 @@ impl Rem<&BigUint> for u32 { macro_rules! impl_rem_assign_scalar { ($scalar:ty, $to_scalar:ident) => { - forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign); - impl RemAssign<&BigUint> for $scalar { + forward_val_assign_scalar!(impl RemAssign for BigUint, $scalar, rem_assign); + impl RemAssign<&BigUint> for $scalar { #[inline] - fn rem_assign(&mut self, other: &BigUint) { + fn rem_assign(&mut self, other: &BigUint) { *self = match other.$to_scalar() { None => *self, Some(0) => panic!("attempt to divide by zero"), @@ -602,62 +610,62 @@ 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; +impl Rem for BigUint { + type Output = BigUint; #[inline] - fn rem(self, other: u64) -> BigUint { + fn rem(self, other: u64) -> BigUint { let (_, r) = div_rem(self, From::from(other)); r } } -impl RemAssign for BigUint { +impl RemAssign for BigUint { #[inline] fn rem_assign(&mut self, other: u64) { *self = &*self % other; } } -impl Rem for u64 { - type Output = BigUint; +impl Rem> for u64 { + type Output = BigUint; #[inline] - fn rem(mut self, other: BigUint) -> BigUint { + fn rem(mut self, other: BigUint) -> BigUint { self %= other; From::from(self) } } -impl Rem for BigUint { - type Output = BigUint; +impl Rem for BigUint { + type Output = BigUint; #[inline] - fn rem(self, other: u128) -> BigUint { + fn rem(self, other: u128) -> BigUint { let (_, r) = div_rem(self, From::from(other)); r } } -impl RemAssign for BigUint { +impl RemAssign for BigUint { #[inline] fn rem_assign(&mut self, other: u128) { *self = &*self % other; } } -impl Rem for u128 { - type Output = BigUint; +impl Rem> for u128 { + type Output = BigUint; #[inline] - fn rem(mut self, other: BigUint) -> BigUint { + fn rem(mut self, other: BigUint) -> BigUint { self %= other; From::from(self) } } -impl CheckedDiv for BigUint { +impl CheckedDiv for BigUint { #[inline] - fn checked_div(&self, v: &BigUint) -> Option { + fn checked_div(&self, v: &BigUint) -> Option> { if v.is_zero() { return None; } @@ -665,9 +673,9 @@ impl CheckedDiv for BigUint { } } -impl CheckedEuclid for BigUint { +impl CheckedEuclid for BigUint { #[inline] - fn checked_div_euclid(&self, v: &BigUint) -> Option { + fn checked_div_euclid(&self, v: &BigUint) -> Option> { if v.is_zero() { return None; } @@ -675,7 +683,7 @@ impl CheckedEuclid for BigUint { } #[inline] - fn checked_rem_euclid(&self, v: &BigUint) -> Option { + fn checked_rem_euclid(&self, v: &BigUint) -> Option> { if v.is_zero() { return None; } @@ -687,15 +695,15 @@ impl CheckedEuclid for BigUint { } } -impl Euclid for BigUint { +impl Euclid for BigUint { #[inline] - fn div_euclid(&self, v: &BigUint) -> BigUint { + fn div_euclid(&self, v: &BigUint) -> BigUint { // trivially same as regular division self / v } #[inline] - fn rem_euclid(&self, v: &BigUint) -> BigUint { + fn rem_euclid(&self, v: &BigUint) -> BigUint { // trivially same as regular remainder self % v } diff --git a/src/biguint/monty.rs b/src/biguint/monty.rs index da53fb2c..8575b349 100644 --- a/src/biguint/monty.rs +++ b/src/biguint/monty.rs @@ -29,7 +29,7 @@ fn inv_mod_alt(b: BigDigit) -> BigDigit { } impl MontyReducer { - fn new(n: &BigUint) -> Self { + fn new(n: &BigUint) -> Self { let n0inv = inv_mod_alt(n.data[0]); MontyReducer { n0inv } } @@ -43,7 +43,13 @@ impl MontyReducer { /// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result /// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m. #[allow(clippy::many_single_char_names)] -fn montgomery(x: &BigUint, y: &BigUint, m: &BigUint, k: BigDigit, n: usize) -> BigUint { +fn montgomery( + x: &BigUint, + y: &BigUint, + m: &BigUint, + k: BigDigit, + n: usize, +) -> BigUint { // This code assumes x, y, m are all the same length, n. // (required by addMulVVW and the for loop). // It also assumes that x, y are already reduced mod m, @@ -134,7 +140,11 @@ fn mul_add_www(x: BigDigit, y: BigDigit, c: BigDigit) -> (BigDigit, BigDigit) { /// Calculates x ** y mod m using a fixed, 4-bit window. #[allow(clippy::many_single_char_names)] -pub(super) fn monty_modpow(x: &BigUint, y: &BigUint, m: &BigUint) -> BigUint { +pub(super) fn monty_modpow( + x: &BigUint, + y: &BigUint, + m: &BigUint, +) -> BigUint { assert!(m.data[0] & 1 == 1); let mr = MontyReducer::new(m); let num_words = m.data.len(); diff --git a/src/biguint/multiplication.rs b/src/biguint/multiplication.rs index 7a50a75f..bba85003 100644 --- a/src/biguint/multiplication.rs +++ b/src/biguint/multiplication.rs @@ -1,6 +1,6 @@ use super::addition::{__add2, add2}; use super::subtraction::sub2; -use super::{biguint_from_tinyvec, cmp_slice, BigUint, IntDigits}; +use super::{biguint_from_tinyvec, cmp_slice, BigUint}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; use crate::Sign::{self, Minus, NoSign, Plus}; @@ -10,7 +10,7 @@ use core::cmp::Ordering; use core::iter::Product; use core::ops::{Mul, MulAssign}; use num_traits::{CheckedMul, FromPrimitive, One, Zero}; -use tinyvec::{tiny_vec, TinyVec}; +use tinyvec::TinyVec; #[inline] pub(super) fn mac_with_carry( @@ -65,7 +65,7 @@ fn bigint_from_slice(slice: &[BigDigit]) -> BigInt { /// Three argument multiply accumulate: /// acc += b * c #[allow(clippy::many_single_char_names)] -fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { +fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { // Least-significant zeros have no effect on the output. if let Some(&0) = b.first() { if let Some(nz) = b.iter().position(|&d| d != 0) { @@ -161,8 +161,8 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { let (low2, high2) = y.split_at(m2); // (x * high2) * NBASE ^ m2 + z0 - mac3(acc, x, low2); - mac3(&mut acc[m2..], x, high2); + mac3::(acc, x, low2); + mac3::(&mut acc[m2..], x, high2); } else if x.len() <= 256 { // Karatsuba multiplication: // @@ -234,10 +234,12 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { // 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: core::iter::repeat(0).take(len).collect() }; + let mut p = BigUint:: { + data: core::iter::repeat(0).take(len).collect(), + }; // p2 = x1 * y1 - mac3(&mut p.data, 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(); @@ -250,7 +252,7 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { p.data.resize(len, 0); // p0 = x0 * y0 - mac3(&mut p.data, x0, y0); + mac3::(&mut p.data, x0, y0); p.normalize(); add2(acc, &p.data); @@ -258,21 +260,21 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { // 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); + 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.resize(len, 0); - mac3(&mut p.data, &j0.data, &j1.data); + 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); + mac3::(&mut acc[b..], &j0.data, &j1.data); } NoSign => (), } @@ -408,15 +410,17 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) { } } -fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { +fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint { let len = x.len() + y.len() + 1; - let mut prod = BigUint { data: core::iter::repeat(0).take(len).collect() }; + let mut prod = BigUint { + data: core::iter::repeat(0).take(len).collect(), + }; - mac3(&mut prod.data, x, y); + mac3::(&mut prod.data, x, y); prod.normalized() } -fn scalar_mul(a: &mut BigUint, b: BigDigit) { +fn scalar_mul(a: &mut BigUint, b: BigDigit) { match b { 0 => a.set_zero(), 1 => {} @@ -436,7 +440,7 @@ fn scalar_mul(a: &mut BigUint, b: BigDigit) { } } -fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { +fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { // Normalize: if let Some(&0) = a.last() { a = &a[..a.iter().rposition(|&x| x != 0).map_or(0, |i| i + 1)]; @@ -460,89 +464,112 @@ fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { } } -macro_rules! impl_mul { - ($(impl Mul<$Other:ty> for $Self:ty;)*) => {$( - impl Mul<$Other> for $Self { - type Output = BigUint; - - #[inline] - fn mul(self, other: $Other) -> BigUint { - match (&*self.data, &*other.data) { - // multiply by zero - (&[], _) | (_, &[]) => BigUint::zero(), - // multiply by a scalar - (_, &[digit]) => self * digit, - (&[digit], _) => other * digit, - // full multiplication - (x, y) => mul3(x, y), - } - } +impl Mul> for BigUint { + type Output = BigUint; + #[inline] + fn mul(self, other: BigUint) -> BigUint { + match (&*self.data, &*other.data) { + (&[], _) | (_, &[]) => BigUint::zero(), + (_, &[digit]) => self * digit, + (&[digit], _) => other * digit, + (x, y) => mul3(x, y), + } + } +} +impl Mul> for &BigUint { + type Output = BigUint; + #[inline] + fn mul(self, other: BigUint) -> BigUint { + match (&*self.data, &*other.data) { + (&[], _) | (_, &[]) => BigUint::zero(), + (_, &[digit]) => self * digit, + (&[digit], _) => other * digit, + (x, y) => mul3(x, y), } - )*} + } } -impl_mul! { - impl Mul for BigUint; - impl Mul for &BigUint; - impl Mul<&BigUint> for BigUint; - impl Mul<&BigUint> for &BigUint; +impl Mul<&BigUint> for BigUint { + type Output = BigUint; + #[inline] + fn mul(self, other: &BigUint) -> BigUint { + match (&*self.data, &*other.data) { + (&[], _) | (_, &[]) => BigUint::zero(), + (_, &[digit]) => self * digit, + (&[digit], _) => other * digit, + (x, y) => mul3(x, y), + } + } +} +impl Mul<&BigUint> for &BigUint { + type Output = BigUint; + #[inline] + fn mul(self, other: &BigUint) -> BigUint { + match (&*self.data, &*other.data) { + (&[], _) | (_, &[]) => BigUint::zero(), + (_, &[digit]) => self * digit, + (&[digit], _) => other * digit, + (x, y) => mul3(x, y), + } + } } -macro_rules! impl_mul_assign { - ($(impl MulAssign<$Other:ty> for BigUint;)*) => {$( - impl MulAssign<$Other> for BigUint { - #[inline] - fn mul_assign(&mut self, other: $Other) { - match (&*self.data, &*other.data) { - // multiply by zero - (&[], _) => {}, - (_, &[]) => self.set_zero(), - // multiply by a scalar - (_, &[digit]) => *self *= digit, - (&[digit], _) => *self = other * digit, - // full multiplication - (x, y) => *self = mul3(x, y), - } - } +impl MulAssign> for BigUint { + #[inline] + fn mul_assign(&mut self, other: BigUint) { + match (&*self.data, &*other.data) { + (&[], _) => {} + (_, &[]) => self.set_zero(), + (_, &[digit]) => *self *= digit, + (&[digit], _) => *self = other * digit, + (x, y) => *self = mul3(x, y), } - )*} + } } -impl_mul_assign! { - impl MulAssign for BigUint; - impl MulAssign<&BigUint> for BigUint; +impl MulAssign<&BigUint> for BigUint { + #[inline] + fn mul_assign(&mut self, other: &BigUint) { + match (&*self.data, &*other.data) { + (&[], _) => {} + (_, &[]) => self.set_zero(), + (_, &[digit]) => *self *= digit, + (&[digit], _) => *self = other * digit, + (x, y) => *self = mul3(x, y), + } + } } -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); -forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); +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); +forward_all_scalar_binop_to_val_val_commutative!(impl Mul for BigUint, mul); -impl Mul for BigUint { - type Output = BigUint; +impl Mul for BigUint { + type Output = BigUint; #[inline] - fn mul(mut self, other: u32) -> BigUint { + fn mul(mut self, other: u32) -> BigUint { self *= other; self } } -impl MulAssign for BigUint { +impl MulAssign for BigUint { #[inline] fn mul_assign(&mut self, other: u32) { scalar_mul(self, other as BigDigit); } } -impl Mul for BigUint { - type Output = BigUint; +impl Mul for BigUint { + type Output = BigUint; #[inline] - fn mul(mut self, other: u64) -> BigUint { + fn mul(mut self, other: u64) -> BigUint { self *= other; self } } -impl MulAssign for BigUint { +impl MulAssign for BigUint { cfg_digit!( #[inline] fn mul_assign(&mut self, other: u64) { @@ -561,17 +588,17 @@ impl MulAssign for BigUint { ); } -impl Mul for BigUint { - type Output = BigUint; +impl Mul for BigUint { + type Output = BigUint; #[inline] - fn mul(mut self, other: u128) -> BigUint { + fn mul(mut self, other: u128) -> BigUint { self *= other; self } } -impl MulAssign for BigUint { +impl MulAssign for BigUint { cfg_digit!( #[inline] fn mul_assign(&mut self, other: u128) { @@ -598,9 +625,9 @@ impl MulAssign for BigUint { ); } -impl CheckedMul for BigUint { +impl CheckedMul for BigUint { #[inline] - fn checked_mul(&self, v: &BigUint) -> Option { + fn checked_mul(&self, v: &BigUint) -> Option> { Some(self.mul(v)) } } diff --git a/src/biguint/power.rs b/src/biguint/power.rs index c6e5efa5..6593784f 100644 --- a/src/biguint/power.rs +++ b/src/biguint/power.rs @@ -6,11 +6,11 @@ use crate::big_digit::{self, BigDigit}; use num_integer::Integer; use num_traits::{One, Pow, ToPrimitive, Zero}; -impl Pow<&BigUint> for BigUint { - type Output = BigUint; +impl Pow<&BigUint> for BigUint { + type Output = BigUint; #[inline] - fn pow(self, exp: &BigUint) -> BigUint { + fn pow(self, exp: &BigUint) -> BigUint { if self.is_one() || exp.is_zero() { BigUint::one() } else if self.is_zero() { @@ -27,20 +27,20 @@ impl Pow<&BigUint> for BigUint { } } -impl Pow for BigUint { - type Output = BigUint; +impl Pow> for BigUint { + type Output = BigUint; #[inline] - fn pow(self, exp: BigUint) -> BigUint { + fn pow(self, exp: BigUint) -> BigUint { Pow::pow(self, &exp) } } -impl Pow<&BigUint> for &BigUint { - type Output = BigUint; +impl Pow<&BigUint> for &BigUint { + type Output = BigUint; #[inline] - fn pow(self, exp: &BigUint) -> BigUint { + fn pow(self, exp: &BigUint) -> BigUint { if self.is_one() || exp.is_zero() { BigUint::one() } else if self.is_zero() { @@ -51,21 +51,21 @@ impl Pow<&BigUint> for &BigUint { } } -impl Pow for &BigUint { - type Output = BigUint; +impl Pow> for &BigUint { + type Output = BigUint; #[inline] - fn pow(self, exp: BigUint) -> BigUint { + fn pow(self, exp: BigUint) -> BigUint { Pow::pow(self, &exp) } } macro_rules! pow_impl { ($T:ty) => { - impl Pow<$T> for BigUint { - type Output = BigUint; + impl Pow<$T> for BigUint { + type Output = BigUint; - fn pow(self, mut exp: $T) -> BigUint { + fn pow(self, mut exp: $T) -> BigUint { if exp == 0 { return BigUint::one(); } @@ -92,20 +92,20 @@ macro_rules! pow_impl { } } - impl Pow<&$T> for BigUint { - type Output = BigUint; + impl Pow<&$T> for BigUint { + type Output = BigUint; #[inline] - fn pow(self, exp: &$T) -> BigUint { + fn pow(self, exp: &$T) -> BigUint { Pow::pow(self, *exp) } } - impl Pow<$T> for &BigUint { - type Output = BigUint; + impl Pow<$T> for &BigUint { + type Output = BigUint; #[inline] - fn pow(self, exp: $T) -> BigUint { + fn pow(self, exp: $T) -> BigUint { if exp == 0 { return BigUint::one(); } @@ -113,11 +113,11 @@ macro_rules! pow_impl { } } - impl Pow<&$T> for &BigUint { - type Output = BigUint; + impl Pow<&$T> for &BigUint { + type Output = BigUint; #[inline] - fn pow(self, exp: &$T) -> BigUint { + fn pow(self, exp: &$T) -> BigUint { Pow::pow(self, *exp) } } @@ -131,7 +131,11 @@ pow_impl!(u64); pow_impl!(usize); pow_impl!(u128); -pub(super) fn modpow(x: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint { +pub(super) fn modpow( + x: &BigUint, + exponent: &BigUint, + modulus: &BigUint, +) -> BigUint { assert!( !modulus.is_zero(), "attempt to calculate with zero modulus!" @@ -146,7 +150,11 @@ pub(super) fn modpow(x: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigU } } -fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> BigUint { +fn plain_modpow( + base: &BigUint, + exp_data: &[BigDigit], + modulus: &BigUint, +) -> BigUint { assert!( !modulus.is_zero(), "attempt to calculate with zero modulus!" @@ -219,7 +227,7 @@ fn plain_modpow(base: &BigUint, exp_data: &[BigDigit], modulus: &BigUint) -> Big #[test] fn test_plain_modpow() { - let two = &BigUint::from(2u32); + let two = &BigUint::<32>::from(2u32); let modulus = BigUint::from(0x1100u32); let exp = vec![0, 0b1]; @@ -251,7 +259,7 @@ fn test_plain_modpow() { #[test] fn test_pow_biguint() { - let base = BigUint::from(5u8); + let base = BigUint::<32>::from(5u8); let exponent = BigUint::from(3u8); assert_eq!(BigUint::from(125u8), base.pow(exponent)); diff --git a/src/biguint/shift.rs b/src/biguint/shift.rs index 422bf2cf..f1323b97 100644 --- a/src/biguint/shift.rs +++ b/src/biguint/shift.rs @@ -3,14 +3,13 @@ use super::{biguint_from_tinyvec, BigUint}; use crate::big_digit; use alloc::borrow::Cow; -use alloc::vec::Vec; -use tinyvec::TinyVec; use core::mem; use core::ops::{Shl, ShlAssign, Shr, ShrAssign}; use num_traits::{PrimInt, Zero}; +use tinyvec::TinyVec; #[inline] -fn biguint_shl(n: Cow<'_, BigUint>, shift: T) -> BigUint { +fn biguint_shl(n: Cow<'_, BigUint>, shift: T) -> BigUint { if shift < T::zero() { panic!("attempt to shift left with negative"); } @@ -23,7 +22,7 @@ fn biguint_shl(n: Cow<'_, BigUint>, shift: T) -> BigUint { biguint_shl2(n, digits, shift) } -fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { +fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { let mut data = match digits { 0 => n.into_owned().data, _ => { @@ -52,12 +51,12 @@ fn biguint_shl2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { } #[inline] -fn biguint_shr(n: Cow<'_, BigUint>, shift: T) -> BigUint { +fn biguint_shr(n: &mut BigUint, shift: T) { if shift < T::zero() { panic!("attempt to shift right with negative"); } if n.is_zero() { - return n.into_owned(); + return; } let bits = T::from(big_digit::BITS).unwrap(); let digits = (shift / bits).to_usize().unwrap_or(usize::MAX); @@ -65,27 +64,13 @@ fn biguint_shr(n: Cow<'_, BigUint>, shift: T) -> BigUint { biguint_shr2(n, digits, shift) } -fn biguint_shr2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { +fn biguint_shr2(n: &mut BigUint, digits: usize, shift: u8) { if digits >= n.data.len() { - let mut n = n.into_owned(); n.set_zero(); - return n; + return; } - let n_data_len = n.data.len(); - // if n.data.len() > 6 { - // eprintln!("{:?}", n.data.len()); - // } - // dbg!(n.data.len()); - let mut data = match n { - Cow::Borrowed(n) => n.data[digits..].into_iter().copied().collect(), - Cow::Owned(mut n) => { - if digits != 0 { - // eprintln!("draining digits={:?}", digits); - n.data.drain(..digits); - } - n.data - } - }; + + let data = &mut n.data[digits..]; if shift > 0 { let mut borrow = 0; @@ -97,31 +82,31 @@ fn biguint_shr2(n: Cow<'_, BigUint>, digits: usize, shift: u8) -> BigUint { } } - // if n_data_len > 6 || data.len() > 6 { - // eprintln!("n.data={:?} data={:?}", n_data_len, data.len()); - // } - biguint_from_tinyvec(data) + let len = data.len(); + n.data.copy_within(digits.., 0); + n.data.truncate(len); + n.normalize(); } macro_rules! impl_shift { (@ref $Shx:ident :: $shx:ident, $ShxAssign:ident :: $shx_assign:ident, $rhs:ty) => { - impl $Shx<&$rhs> for BigUint { - type Output = BigUint; + impl $Shx<&$rhs> for BigUint { + type Output = BigUint; #[inline] - fn $shx(self, rhs: &$rhs) -> BigUint { + fn $shx(self, rhs: &$rhs) -> BigUint { $Shx::$shx(self, *rhs) } } - impl $Shx<&$rhs> for &BigUint { - type Output = BigUint; + impl $Shx<&$rhs> for &BigUint { + type Output = BigUint; #[inline] - fn $shx(self, rhs: &$rhs) -> BigUint { + fn $shx(self, rhs: &$rhs) -> BigUint { $Shx::$shx(self, *rhs) } } - impl $ShxAssign<&$rhs> for BigUint { + impl $ShxAssign<&$rhs> for BigUint { #[inline] fn $shx_assign(&mut self, rhs: &$rhs) { $ShxAssign::$shx_assign(self, *rhs); @@ -129,23 +114,23 @@ macro_rules! impl_shift { } }; ($($rhs:ty),+) => {$( - impl Shl<$rhs> for BigUint { - type Output = BigUint; + impl Shl<$rhs> for BigUint { + type Output = BigUint; #[inline] - fn shl(self, rhs: $rhs) -> BigUint { + fn shl(self, rhs: $rhs) -> BigUint { biguint_shl(Cow::Owned(self), rhs) } } - impl Shl<$rhs> for &BigUint { - type Output = BigUint; + impl Shl<$rhs> for &BigUint { + type Output = BigUint; #[inline] - fn shl(self, rhs: $rhs) -> BigUint { + fn shl(self, rhs: $rhs) -> BigUint { biguint_shl(Cow::Borrowed(self), rhs) } } - impl ShlAssign<$rhs> for BigUint { + impl ShlAssign<$rhs> for BigUint { #[inline] fn shl_assign(&mut self, rhs: $rhs) { let n = mem::replace(self, Self::zero()); @@ -154,27 +139,29 @@ macro_rules! impl_shift { } impl_shift! { @ref Shl::shl, ShlAssign::shl_assign, $rhs } - impl Shr<$rhs> for BigUint { - type Output = BigUint; + impl Shr<$rhs> for BigUint { + type Output = BigUint; #[inline] - fn shr(self, rhs: $rhs) -> BigUint { - biguint_shr(Cow::Owned(self), rhs) + fn shr(mut self, rhs: $rhs) -> BigUint { + biguint_shr(&mut self, rhs); + self } } - impl Shr<$rhs> for &BigUint { - type Output = BigUint; + impl Shr<$rhs> for &BigUint { + type Output = BigUint; #[inline] - fn shr(self, rhs: $rhs) -> BigUint { - biguint_shr(Cow::Borrowed(self), rhs) + fn shr(self, rhs: $rhs) -> BigUint { + let mut this = self.clone(); + biguint_shr(&mut this, rhs); + this } } - impl ShrAssign<$rhs> for BigUint { + impl ShrAssign<$rhs> for BigUint { #[inline] fn shr_assign(&mut self, rhs: $rhs) { - let n = mem::replace(self, Self::zero()); - *self = n >> rhs; + biguint_shr(self, rhs); } } impl_shift! { @ref Shr::shr, ShrAssign::shr_assign, $rhs } diff --git a/src/biguint/subtraction.rs b/src/biguint/subtraction.rs index b1c036d8..0ef73847 100644 --- a/src/biguint/subtraction.rs +++ b/src/biguint/subtraction.rs @@ -104,29 +104,29 @@ fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { ); } -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); +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 Sub<&BigUint> for BigUint { - type Output = BigUint; +impl Sub<&BigUint> for BigUint { + type Output = BigUint; - fn sub(mut self, other: &BigUint) -> BigUint { + fn sub(mut self, other: &BigUint) -> BigUint { self -= other; self } } -impl SubAssign<&BigUint> for BigUint { - fn sub_assign(&mut self, other: &BigUint) { +impl SubAssign<&BigUint> for BigUint { + fn sub_assign(&mut self, other: &BigUint) { sub2(&mut self.data[..], &other.data[..]); self.normalize(); } } -impl Sub for &BigUint { - type Output = BigUint; +impl Sub> for &BigUint { + type Output = BigUint; - fn sub(self, mut other: BigUint) -> BigUint { + fn sub(self, mut other: BigUint) -> BigUint { let other_len = other.data.len(); if other_len < self.data.len() { let lo_borrow = __sub2rev(&self.data[..other_len], &mut other.data); @@ -141,35 +141,35 @@ impl Sub for &BigUint { } } -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); -forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); +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); +forward_all_scalar_binop_to_val_val!(impl Sub for BigUint, sub); -impl Sub for BigUint { - type Output = BigUint; +impl Sub for BigUint { + type Output = BigUint; #[inline] - fn sub(mut self, other: u32) -> BigUint { + fn sub(mut self, other: u32) -> BigUint { self -= other; self } } -impl SubAssign for BigUint { +impl SubAssign for BigUint { fn sub_assign(&mut self, other: u32) { sub2(&mut self.data[..], &[other as BigDigit]); self.normalize(); } } -impl Sub for u32 { - type Output = BigUint; +impl Sub> for u32 { + type Output = BigUint; cfg_digit!( #[inline] - fn sub(self, mut other: BigUint) -> BigUint { + fn sub(self, mut other: BigUint) -> BigUint { if other.data.len() == 0 { other.data.push(self); } else { @@ -179,7 +179,7 @@ impl Sub for u32 { } #[inline] - fn sub(self, mut other: BigUint) -> BigUint { + fn sub(self, mut other: BigUint) -> BigUint { if other.data.is_empty() { other.data.push(self as BigDigit); } else { @@ -190,17 +190,17 @@ impl Sub for u32 { ); } -impl Sub for BigUint { - type Output = BigUint; +impl Sub for BigUint { + type Output = BigUint; #[inline] - fn sub(mut self, other: u64) -> BigUint { + fn sub(mut self, other: u64) -> BigUint { self -= other; self } } -impl SubAssign for BigUint { +impl SubAssign for BigUint { cfg_digit!( #[inline] fn sub_assign(&mut self, other: u64) { @@ -217,12 +217,12 @@ impl SubAssign for BigUint { ); } -impl Sub for u64 { - type Output = BigUint; +impl Sub> for u64 { + type Output = BigUint; cfg_digit!( #[inline] - fn sub(self, mut other: BigUint) -> BigUint { + fn sub(self, mut other: BigUint) -> BigUint { while other.data.len() < 2 { other.data.push(0); } @@ -233,7 +233,7 @@ impl Sub for u64 { } #[inline] - fn sub(self, mut other: BigUint) -> BigUint { + fn sub(self, mut other: BigUint) -> BigUint { if other.data.is_empty() { other.data.push(self); } else { @@ -244,17 +244,17 @@ impl Sub for u64 { ); } -impl Sub for BigUint { - type Output = BigUint; +impl Sub for BigUint { + type Output = BigUint; #[inline] - fn sub(mut self, other: u128) -> BigUint { + fn sub(mut self, other: u128) -> BigUint { self -= other; self } } -impl SubAssign for BigUint { +impl SubAssign for BigUint { cfg_digit!( #[inline] fn sub_assign(&mut self, other: u128) { @@ -272,12 +272,12 @@ impl SubAssign for BigUint { ); } -impl Sub for u128 { - type Output = BigUint; +impl Sub> for u128 { + type Output = BigUint; cfg_digit!( #[inline] - fn sub(self, mut other: BigUint) -> BigUint { + fn sub(self, mut other: BigUint) -> BigUint { while other.data.len() < 4 { other.data.push(0); } @@ -288,7 +288,7 @@ impl Sub for u128 { } #[inline] - fn sub(self, mut other: BigUint) -> BigUint { + fn sub(self, mut other: BigUint) -> BigUint { while other.data.len() < 2 { other.data.push(0); } @@ -300,9 +300,9 @@ impl Sub for u128 { ); } -impl CheckedSub for BigUint { +impl CheckedSub for BigUint { #[inline] - fn checked_sub(&self, v: &BigUint) -> Option { + fn checked_sub(&self, v: &BigUint) -> Option> { match self.cmp(v) { Less => None, Equal => Some(Self::zero()), diff --git a/src/macros.rs b/src/macros.rs index 4b3d8829..fba4133b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -35,7 +35,7 @@ macro_rules! cfg_digit_expr { macro_rules! forward_val_val_binop { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { + impl $imp<$res> for $res { type Output = $res; #[inline] @@ -49,7 +49,7 @@ macro_rules! forward_val_val_binop { macro_rules! forward_val_val_binop_commutative { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { + impl $imp<$res> for $res { type Output = $res; #[inline] @@ -67,7 +67,7 @@ macro_rules! forward_val_val_binop_commutative { macro_rules! forward_ref_val_binop { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for &$res { + impl $imp<$res> for &$res { type Output = $res; #[inline] @@ -81,7 +81,7 @@ macro_rules! forward_ref_val_binop { macro_rules! forward_ref_val_binop_commutative { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for &$res { + impl $imp<$res> for &$res { type Output = $res; #[inline] @@ -95,7 +95,7 @@ macro_rules! forward_ref_val_binop_commutative { macro_rules! forward_val_ref_binop { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<&$res> for $res { + impl $imp<&$res> for $res { type Output = $res; #[inline] @@ -109,7 +109,7 @@ macro_rules! forward_val_ref_binop { macro_rules! forward_ref_ref_binop { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<&$res> for &$res { + impl $imp<&$res> for &$res { type Output = $res; #[inline] @@ -123,7 +123,7 @@ macro_rules! forward_ref_ref_binop { macro_rules! forward_ref_ref_binop_commutative { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<&$res> for &$res { + impl $imp<&$res> for &$res { type Output = $res; #[inline] @@ -141,7 +141,7 @@ macro_rules! forward_ref_ref_binop_commutative { macro_rules! forward_val_assign { (impl $imp:ident for $res:ty, $method:ident) => { - impl $imp<$res> for $res { + impl $imp<$res> for $res { #[inline] fn $method(&mut self, other: $res) { self.$method(&other); @@ -152,7 +152,7 @@ macro_rules! forward_val_assign { macro_rules! forward_val_assign_scalar { (impl $imp:ident for $res:ty, $scalar:ty, $method:ident) => { - impl $imp<$res> for $scalar { + impl $imp<$res> for $scalar { #[inline] fn $method(&mut self, other: $res) { self.$method(&other); @@ -164,7 +164,7 @@ macro_rules! forward_val_assign_scalar { /// use this if val_val_binop is already implemented and the reversed order is required macro_rules! forward_scalar_val_val_binop_commutative { (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => { - impl $imp<$res> for $scalar { + impl $imp<$res> for $scalar { type Output = $res; #[inline] @@ -178,7 +178,7 @@ macro_rules! forward_scalar_val_val_binop_commutative { // Forward scalar to ref-val, when reusing storage is not helpful macro_rules! forward_scalar_val_val_binop_to_ref_val { (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl $imp<$scalar> for $res { + impl $imp<$scalar> for $res { type Output = $res; #[inline] @@ -187,7 +187,7 @@ macro_rules! forward_scalar_val_val_binop_to_ref_val { } } - impl $imp<$res> for $scalar { + impl $imp<$res> for $scalar { type Output = $res; #[inline] @@ -200,7 +200,7 @@ macro_rules! forward_scalar_val_val_binop_to_ref_val { macro_rules! forward_scalar_ref_ref_binop_to_ref_val { (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl $imp<&$scalar> for &$res { + impl $imp<&$scalar> for &$res { type Output = $res; #[inline] @@ -209,7 +209,7 @@ macro_rules! forward_scalar_ref_ref_binop_to_ref_val { } } - impl $imp<&$res> for &$scalar { + impl $imp<&$res> for &$scalar { type Output = $res; #[inline] @@ -222,7 +222,7 @@ macro_rules! forward_scalar_ref_ref_binop_to_ref_val { macro_rules! forward_scalar_val_ref_binop_to_ref_val { (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl $imp<&$scalar> for $res { + impl $imp<&$scalar> for $res { type Output = $res; #[inline] @@ -231,7 +231,7 @@ macro_rules! forward_scalar_val_ref_binop_to_ref_val { } } - impl $imp<$res> for &$scalar { + impl $imp<$res> for &$scalar { type Output = $res; #[inline] @@ -244,7 +244,7 @@ macro_rules! forward_scalar_val_ref_binop_to_ref_val { macro_rules! forward_scalar_val_ref_binop_to_val_val { (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl $imp<&$scalar> for $res { + impl $imp<&$scalar> for $res { type Output = $res; #[inline] @@ -253,7 +253,7 @@ macro_rules! forward_scalar_val_ref_binop_to_val_val { } } - impl $imp<$res> for &$scalar { + impl $imp<$res> for &$scalar { type Output = $res; #[inline] @@ -266,7 +266,7 @@ macro_rules! forward_scalar_val_ref_binop_to_val_val { macro_rules! forward_scalar_ref_val_binop_to_val_val { (impl $imp:ident < $scalar:ty > for $res:ty, $method:ident) => { - impl $imp<$scalar> for &$res { + impl $imp<$scalar> for &$res { type Output = $res; #[inline] @@ -275,7 +275,7 @@ macro_rules! forward_scalar_ref_val_binop_to_val_val { } } - impl $imp<&$res> for $scalar { + impl $imp<&$res> for $scalar { type Output = $res; #[inline] @@ -288,7 +288,7 @@ macro_rules! forward_scalar_ref_val_binop_to_val_val { macro_rules! forward_scalar_ref_ref_binop_to_val_val { (impl $imp:ident<$scalar:ty> for $res:ty, $method:ident) => { - impl $imp<&$scalar> for &$res { + impl $imp<&$scalar> for &$res { type Output = $res; #[inline] @@ -297,7 +297,7 @@ macro_rules! forward_scalar_ref_ref_binop_to_val_val { } } - impl $imp<&$res> for &$scalar { + impl $imp<&$res> for &$scalar { type Output = $res; #[inline] @@ -313,7 +313,7 @@ macro_rules! promote_scalars { $( forward_all_scalar_binop_to_val_val!(impl $imp<$scalar> for $res, $method); - impl $imp<$scalar> for $res { + impl $imp<$scalar> for $res { type Output = $res; #[allow(clippy::cast_lossless)] @@ -323,7 +323,7 @@ macro_rules! promote_scalars { } } - impl $imp<$res> for $scalar { + impl $imp<$res> for $scalar { type Output = $res; #[allow(clippy::cast_lossless)] @@ -338,7 +338,7 @@ macro_rules! promote_scalars { macro_rules! promote_scalars_assign { (impl $imp:ident<$promo:ty> for $res:ty, $method:ident, $( $scalar:ty ),*) => { $( - impl $imp<$scalar> for $res { + impl $imp<$scalar> for $res { #[allow(clippy::cast_lossless)] #[inline] fn $method(&mut self, other: $scalar) { From 7d868108353b9d8dd6013a075064e9a08e1ce88c Mon Sep 17 00:00:00 2001 From: Sebastien Chapuis Date: Wed, 11 Dec 2024 00:18:37 +0100 Subject: [PATCH 3/6] Fix --- src/bigint.rs | 40 +++++++++++++++++++++------------------- src/biguint.rs | 3 ++- src/biguint/serde.rs | 27 +++++++++++++-------------- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 083624e8..dee1dcac 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -651,7 +651,7 @@ impl BigInt { /// BigInt::parse_bytes(b"22405534230753963835153736737", 10).unwrap()); /// ``` #[inline] - pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> BigInt { + pub fn from_bytes_be(sign: Sign, bytes: &[u8]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_bytes_be(bytes)) } @@ -659,27 +659,10 @@ impl BigInt { /// /// The bytes are in little-endian byte order. #[inline] - pub fn from_bytes_le(sign: Sign, bytes: &[u8]) -> BigInt { + 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 { - convert::from_signed_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 { - convert::from_signed_bytes_le(digits) - } - /// Creates and initializes a [`BigInt`]. /// /// # Examples @@ -1175,6 +1158,25 @@ impl BigInt { } } +impl BigInt { + /// 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 { + convert::from_signed_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 { + convert::from_signed_bytes_le(digits) + } +} + impl num_traits::FromBytes for BigInt { type Bytes = [u8]; diff --git a/src/biguint.rs b/src/biguint.rs index 3871c5cb..b3971786 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -32,7 +32,8 @@ mod shift; pub(crate) use self::convert::to_str_radix_reversed; pub use self::iter::{U32Digits, U64Digits}; -pub const NLIMBS: usize = 32; +/// 4 limbs by default (256 bits) +pub const NLIMBS: usize = 4; /// A big unsigned integer type. pub struct BigUint { diff --git a/src/biguint/serde.rs b/src/biguint/serde.rs index 9ea4aeef..4c6d0b60 100644 --- a/src/biguint/serde.rs +++ b/src/biguint/serde.rs @@ -3,21 +3,20 @@ use super::{biguint_from_tinyvec, BigUint}; -use alloc::vec::Vec; -use core::{cmp, fmt, mem}; +use core::fmt; use serde::de::{SeqAccess, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -// `cautious` is based on the function of the same name in `serde`, but specialized to `u32`: -// https://github.com/dtolnay/serde/blob/399ef081ecc36d2f165ff1f6debdcbf6a1dc7efb/serde/src/private/size_hint.rs#L11-L22 -fn cautious(hint: Option) -> usize { - const MAX_PREALLOC_BYTES: usize = 1024 * 1024; +// // `cautious` is based on the function of the same name in `serde`, but specialized to `u32`: +// // https://github.com/dtolnay/serde/blob/399ef081ecc36d2f165ff1f6debdcbf6a1dc7efb/serde/src/private/size_hint.rs#L11-L22 +// fn cautious(hint: Option) -> usize { +// const MAX_PREALLOC_BYTES: usize = 1024 * 1024; - cmp::min( - hint.unwrap_or(0), - MAX_PREALLOC_BYTES / mem::size_of::(), - ) -} +// cmp::min( +// hint.unwrap_or(0), +// MAX_PREALLOC_BYTES / mem::size_of::(), +// ) +// } impl Serialize for BigUint { cfg_digit!( @@ -98,10 +97,10 @@ impl<'de> Visitor<'de> for U32Visitor { S: SeqAccess<'de>, { use crate::big_digit::BigDigit; - use num_integer::Integer; + // use num_integer::Integer; - let u32_len = cautious(seq.size_hint()); - let len = Integer::div_ceil(&u32_len, &2); + // let u32_len = cautious(seq.size_hint()); + // let len = Integer::div_ceil(&u32_len, &2); let mut data = tinyvec::TinyVec::new(); while let Some(lo) = seq.next_element::()? { From 6c1bb38a18f80f779d5aa7914c445a188c050a07 Mon Sep 17 00:00:00 2001 From: Sebastien Chapuis Date: Wed, 11 Dec 2024 12:04:43 +0100 Subject: [PATCH 4/6] Use 32 limbs on `ToBigInt` --- src/bigint.rs | 2 +- src/bigint/convert.rs | 14 +++++++------- src/biguint.rs | 2 +- src/biguint/convert.rs | 6 +++--- src/lib.rs | 1 + 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index dee1dcac..cf62ab53 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -572,7 +572,7 @@ impl BigInt { /// when converting from any integer or unsigned primitive, or [`BigUint`]. pub trait ToBigInt { /// Converts the value of `self` to a [`BigInt`]. - fn to_bigint(&self) -> Option; + fn to_bigint(&self) -> Option>; } impl BigInt { diff --git a/src/bigint/convert.rs b/src/bigint/convert.rs index 4e2f4014..cd6bc0a9 100644 --- a/src/bigint/convert.rs +++ b/src/bigint/convert.rs @@ -276,15 +276,15 @@ impl From> for BigInt { } } -impl ToBigInt for BigInt { +impl ToBigInt for BigInt<32> { #[inline] - fn to_bigint(&self) -> Option { + fn to_bigint(&self) -> Option> { Some(self.clone()) } } -impl ToBigInt for BigUint { +impl ToBigInt for BigUint<32> { #[inline] - fn to_bigint(&self) -> Option { + fn to_bigint(&self) -> Option> { if self.is_zero() { Some(BigInt::zero()) } else { @@ -295,9 +295,9 @@ impl ToBigInt for BigUint { } } } -impl ToBigUint for BigInt { +impl ToBigUint for BigInt<32> { #[inline] - fn to_biguint(&self) -> Option { + fn to_biguint(&self) -> Option> { match self.sign() { Plus => Some(self.data.clone()), NoSign => Some(BigUint::zero()), @@ -366,7 +366,7 @@ macro_rules! impl_to_bigint { ($T:ty, $from_ty:path) => { impl ToBigInt for $T { #[inline] - fn to_bigint(&self) -> Option { + fn to_bigint(&self) -> Option> { $from_ty(*self) } } diff --git a/src/biguint.rs b/src/biguint.rs index b3971786..631356aa 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -529,7 +529,7 @@ impl Roots for BigUint { /// 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; + fn to_biguint(&self) -> Option>; } /// Creates and initializes a [`BigUint`]. diff --git a/src/biguint/convert.rs b/src/biguint/convert.rs index 31fa29fb..df69803f 100644 --- a/src/biguint/convert.rs +++ b/src/biguint/convert.rs @@ -555,9 +555,9 @@ impl_biguint_try_from_int!(i64, FromPrimitive::from_i64); impl_biguint_try_from_int!(isize, FromPrimitive::from_isize); impl_biguint_try_from_int!(i128, FromPrimitive::from_i128); -impl ToBigUint for BigUint { +impl ToBigUint for BigUint<32> { #[inline] - fn to_biguint(&self) -> Option { + fn to_biguint(&self) -> Option> { Some(self.clone()) } } @@ -566,7 +566,7 @@ macro_rules! impl_to_biguint { ($T:ty, $from_ty:path) => { impl ToBigUint for $T { #[inline] - fn to_biguint(&self) -> Option { + fn to_biguint(&self) -> Option> { $from_ty(*self) } } diff --git a/src/lib.rs b/src/lib.rs index 086afc09..36bec184 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -215,6 +215,7 @@ pub use crate::biguint::BigUint; pub use crate::biguint::ToBigUint; pub use crate::biguint::U32Digits; pub use crate::biguint::U64Digits; +pub use crate::biguint::NLIMBS; pub use crate::bigint::BigInt; pub use crate::bigint::Sign; From 028b29c9905d2fb936f9ffeb1504ac606f20f84a Mon Sep 17 00:00:00 2001 From: Sebastien Chapuis Date: Wed, 11 Dec 2024 12:54:51 +0100 Subject: [PATCH 5/6] Rename `to_digits` to `to_nlimbs` --- src/bigint.rs | 4 ++-- src/biguint.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index cf62ab53..03c8baae 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -55,10 +55,10 @@ impl Neg for Sign { } impl BigInt { - pub fn to_digits(&self) -> BigInt { + pub fn to_nlimbs(&self) -> BigInt { BigInt { sign: self.sign, - data: self.data.to_digits(), + data: self.data.to_nlimbs(), } } } diff --git a/src/biguint.rs b/src/biguint.rs index 631356aa..24e6f583 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -41,7 +41,7 @@ pub struct BigUint { } impl BigUint { - pub fn to_digits(&self) -> BigUint { + pub fn to_nlimbs(&self) -> BigUint { BigUint { data: self.data.iter().copied().collect(), } From 8bb5ee4de12587b52d11eac13057c5e8664249a2 Mon Sep 17 00:00:00 2001 From: Sebastien Chapuis Date: Wed, 11 Dec 2024 20:25:15 +0100 Subject: [PATCH 6/6] Remove assert used for debugging --- src/biguint/division.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/biguint/division.rs b/src/biguint/division.rs index 355e93b6..fe20e132 100644 --- a/src/biguint/division.rs +++ b/src/biguint/division.rs @@ -219,14 +219,6 @@ pub(super) fn div_rem_ref( return (BigUint::zero(), BigUint::zero()); } - // if - assert!( - u.data.is_inline(), - "u.data.len={:?} u={:?}", - u.data.len(), - u - ); - if d.data.len() == 1 { if *d.data == [1] { return (u.clone(), BigUint::zero());