From 57f1f6e588145f74cd41e582a557fc65ac86f210 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 3 May 2024 14:52:46 -0700 Subject: [PATCH 1/3] Implement combined `div_rem_euclid` --- Cargo.toml | 2 +- src/bigint/division.rs | 17 +++++++++++++++++ src/biguint/division.rs | 9 +++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ba14b04f..dc8da257 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ default-features = false features = ["i128"] [dependencies.num-traits] -version = "0.2.16" +version = "0.2.18" default-features = false features = ["i128"] diff --git a/src/bigint/division.rs b/src/bigint/division.rs index 318d1fb6..b230cd08 100644 --- a/src/bigint/division.rs +++ b/src/bigint/division.rs @@ -463,6 +463,10 @@ impl CheckedEuclid for BigInt { } Some(self.rem_euclid(v)) } + + fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> { + Some(self.div_rem_euclid(v)) + } } impl Euclid for BigInt { @@ -493,4 +497,17 @@ impl Euclid for BigInt { r } } + + fn div_rem_euclid(&self, v: &Self) -> (Self, Self) { + let (q, r) = self.div_rem(v); + if r.is_negative() { + if v.is_positive() { + (q - 1, r + v) + } else { + (q + 1, r - v) + } + } else { + (q, r) + } + } } diff --git a/src/biguint/division.rs b/src/biguint/division.rs index 29998382..6b91726a 100644 --- a/src/biguint/division.rs +++ b/src/biguint/division.rs @@ -635,6 +635,10 @@ impl CheckedEuclid for BigUint { } Some(self.rem_euclid(v)) } + + fn checked_div_rem_euclid(&self, v: &Self) -> Option<(Self, Self)> { + Some(self.div_rem_euclid(v)) + } } impl Euclid for BigUint { @@ -649,4 +653,9 @@ impl Euclid for BigUint { // trivially same as regular remainder self % v } + + fn div_rem_euclid(&self, v: &Self) -> (Self, Self) { + // trivially same as regular division and remainder + self.div_rem(v) + } } From e09db4ab5521860fc9871be61b74535613a188b4 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 3 May 2024 15:30:00 -0700 Subject: [PATCH 2/3] Add `const ZERO` and `impl ConstZero` --- src/bigint.rs | 36 ++++++++++++++++++++--------------- src/bigint/addition.rs | 18 +++++++++--------- src/bigint/bits.rs | 2 +- src/bigint/convert.rs | 16 ++++++++-------- src/bigint/power.rs | 2 +- src/bigint/subtraction.rs | 18 +++++++++--------- src/biguint.rs | 26 ++++++++++++++++--------- src/biguint/addition.rs | 2 +- src/biguint/convert.rs | 12 ++++++------ src/biguint/division.rs | 28 +++++++++++++-------------- src/biguint/monty.rs | 6 +++--- src/biguint/multiplication.rs | 4 ++-- src/biguint/power.rs | 4 ++-- src/biguint/shift.rs | 4 ++-- src/biguint/subtraction.rs | 4 ++-- src/lib.rs | 6 +++--- src/macros.rs | 2 +- 17 files changed, 102 insertions(+), 88 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 97faa834..7ab72cb6 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -12,7 +12,7 @@ use core::{i128, u128}; use core::{i64, u64}; use num_integer::{Integer, Roots}; -use num_traits::{Num, One, Pow, Signed, Zero}; +use num_traits::{ConstZero, Num, One, Pow, Signed, Zero}; use self::Sign::{Minus, NoSign, Plus}; @@ -132,7 +132,7 @@ impl Ord for BigInt { impl Default for BigInt { #[inline] fn default() -> BigInt { - Zero::zero() + Self::ZERO } } @@ -211,10 +211,7 @@ impl Not for &BigInt { impl Zero for BigInt { #[inline] fn zero() -> BigInt { - BigInt { - sign: NoSign, - data: BigUint::zero(), - } + Self::ZERO } #[inline] @@ -229,6 +226,11 @@ impl Zero for BigInt { } } +impl ConstZero for BigInt { + // forward to the inherent const + const ZERO: Self = Self::ZERO; +} + impl One for BigInt { #[inline] fn one() -> BigInt { @@ -262,7 +264,7 @@ impl Signed for BigInt { #[inline] fn abs_sub(&self, other: &BigInt) -> BigInt { if *self <= *other { - Zero::zero() + Self::ZERO } else { self - other } @@ -273,7 +275,7 @@ impl Signed for BigInt { match self.sign { Plus => BigInt::one(), Minus => -BigInt::one(), - NoSign => BigInt::zero(), + NoSign => Self::ZERO, } } @@ -462,7 +464,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() { - BigInt::zero() + Self::ZERO } else { BigInt::from(&self.data / &egcd.gcd.data * &other.data) }; @@ -567,6 +569,12 @@ 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, + }; + /// Creates and initializes a [`BigInt`]. /// /// The base 232 digits are ordered least significant digit first. @@ -922,11 +930,10 @@ impl BigInt { /// /// ``` /// use num_bigint::{BigInt, Sign}; - /// use num_traits::Zero; /// /// assert_eq!(BigInt::from(1234).sign(), Sign::Plus); /// assert_eq!(BigInt::from(-4321).sign(), Sign::Minus); - /// assert_eq!(BigInt::zero().sign(), Sign::NoSign); + /// assert_eq!(BigInt::ZERO.sign(), Sign::NoSign); /// ``` #[inline] pub fn sign(&self) -> Sign { @@ -943,7 +950,7 @@ impl BigInt { /// /// assert_eq!(BigInt::from(1234).magnitude(), &BigUint::from(1234u32)); /// assert_eq!(BigInt::from(-4321).magnitude(), &BigUint::from(4321u32)); - /// assert!(BigInt::zero().magnitude().is_zero()); + /// assert!(BigInt::ZERO.magnitude().is_zero()); /// ``` #[inline] pub fn magnitude(&self) -> &BigUint { @@ -957,11 +964,10 @@ impl BigInt { /// /// ``` /// use num_bigint::{BigInt, BigUint, Sign}; - /// use num_traits::Zero; /// /// assert_eq!(BigInt::from(1234).into_parts(), (Sign::Plus, BigUint::from(1234u32))); /// assert_eq!(BigInt::from(-4321).into_parts(), (Sign::Minus, BigUint::from(4321u32))); - /// assert_eq!(BigInt::zero().into_parts(), (Sign::NoSign, BigUint::zero())); + /// assert_eq!(BigInt::ZERO.into_parts(), (Sign::NoSign, BigUint::ZERO)); /// ``` #[inline] pub fn into_parts(self) -> (Sign, BigUint) { @@ -980,7 +986,7 @@ impl BigInt { pub fn to_biguint(&self) -> Option { match self.sign { Plus => Some(self.data.clone()), - NoSign => Some(Zero::zero()), + NoSign => Some(BigUint::ZERO), Minus => None, } } diff --git a/src/bigint/addition.rs b/src/bigint/addition.rs index 76aeb997..0d3a0e2a 100644 --- a/src/bigint/addition.rs +++ b/src/bigint/addition.rs @@ -8,7 +8,7 @@ use core::cmp::Ordering::{Equal, Greater, Less}; use core::iter::Sum; use core::mem; use core::ops::{Add, AddAssign}; -use num_traits::{CheckedAdd, Zero}; +use num_traits::CheckedAdd; // We want to forward to BigUint::add, but it's not clear how that will go until // we compare both sign and magnitude. So we duplicate this body for every @@ -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 => Zero::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, BigInt::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 => Zero::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, BigInt::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 => Zero::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, BigInt::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 => BigInt::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, BigInt::zero()); + let n = mem::replace(self, Self::ZERO); *self = n + other; } } diff --git a/src/bigint/bits.rs b/src/bigint/bits.rs index 80f4e2c1..dfb86645 100644 --- a/src/bigint/bits.rs +++ b/src/bigint/bits.rs @@ -114,7 +114,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, diff --git a/src/bigint/convert.rs b/src/bigint/convert.rs index 74280ceb..f1cc2ff9 100644 --- a/src/bigint/convert.rs +++ b/src/bigint/convert.rs @@ -228,7 +228,7 @@ impl From for BigInt { data: BigUint::from(n), } } else { - BigInt::zero() + Self::ZERO } } } @@ -242,7 +242,7 @@ impl From for BigInt { data: BigUint::from(n), } } else { - BigInt::zero() + Self::ZERO } } } @@ -267,7 +267,7 @@ impl From for BigInt { #[inline] fn from(n: BigUint) -> Self { if n.is_zero() { - BigInt::zero() + Self::ZERO } else { BigInt { sign: Plus, @@ -288,7 +288,7 @@ impl ToBigInt for BigUint { #[inline] fn to_bigint(&self) -> Option { if self.is_zero() { - Some(Zero::zero()) + Some(BigInt::ZERO) } else { Some(BigInt { sign: Plus, @@ -303,7 +303,7 @@ impl ToBigUint for BigInt { fn to_biguint(&self) -> Option { match self.sign() { Plus => Some(self.data.clone()), - NoSign => Some(Zero::zero()), + NoSign => Some(BigUint::ZERO), Minus => None, } } @@ -366,7 +366,7 @@ impl From for BigInt { if x { One::one() } else { - Zero::zero() + Self::ZERO } } } @@ -376,7 +376,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 { @@ -394,7 +394,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 4b41f4f2..ef254c89 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 548f3143..ef778549 100644 --- a/src/bigint/subtraction.rs +++ b/src/bigint/subtraction.rs @@ -7,7 +7,7 @@ use crate::{IsizePromotion, UsizePromotion}; use core::cmp::Ordering::{Equal, Greater, Less}; use core::mem; use core::ops::{Sub, SubAssign}; -use num_traits::{CheckedSub, Zero}; +use num_traits::CheckedSub; // We want to forward to BigUint::sub, but it's not clear how that will go until // we compare both sign and magnitude. So we duplicate this body for every @@ -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 => Zero::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, BigInt::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 => Zero::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, BigInt::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 => Zero::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, BigInt::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 => Zero::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, BigInt::zero()); + let n = mem::replace(self, Self::ZERO); *self = n - other; } } diff --git a/src/biguint.rs b/src/biguint.rs index 8303f957..245bcba5 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -11,7 +11,7 @@ use core::str; use core::{u32, u64, u8}; use num_integer::{Integer, Roots}; -use num_traits::{Num, One, Pow, ToPrimitive, Unsigned, Zero}; +use num_traits::{ConstZero, Num, One, Pow, ToPrimitive, Unsigned, Zero}; mod addition; mod division; @@ -101,7 +101,7 @@ fn cmp_slice(a: &[BigDigit], b: &[BigDigit]) -> Ordering { impl Default for BigUint { #[inline] fn default() -> BigUint { - Zero::zero() + Self::ZERO } } @@ -146,7 +146,7 @@ impl fmt::Octal for BigUint { impl Zero for BigUint { #[inline] fn zero() -> BigUint { - BigUint { data: Vec::new() } + Self::ZERO } #[inline] @@ -160,6 +160,11 @@ impl Zero for BigUint { } } +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 { @@ -255,7 +260,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 } @@ -267,7 +272,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 }; @@ -519,12 +524,15 @@ pub(crate) fn biguint_from_vec(digits: Vec) -> BigUint { } impl BigUint { + /// A constant `BigUint` with value 0, useful for static initialization. + pub const ZERO: Self = BigUint { data: Vec::new() }; + /// 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 = BigUint::zero(); + let mut big = Self::ZERO; #[cfg(not(u64_digit))] { @@ -543,7 +551,7 @@ impl BigUint { /// The base 232 digits are ordered least significant digit first. #[inline] pub fn from_slice(slice: &[u32]) -> BigUint { - let mut big = BigUint::zero(); + let mut big = Self::ZERO; big.assign_from_slice(slice); big } @@ -585,7 +593,7 @@ impl BigUint { #[inline] pub fn from_bytes_be(bytes: &[u8]) -> BigUint { if bytes.is_empty() { - Zero::zero() + Self::ZERO } else { let mut v = bytes.to_vec(); v.reverse(); @@ -599,7 +607,7 @@ impl BigUint { #[inline] pub fn from_bytes_le(bytes: &[u8]) -> BigUint { if bytes.is_empty() { - Zero::zero() + Self::ZERO } else { convert::from_bitwise_digits_le(bytes, 8) } diff --git a/src/biguint/addition.rs b/src/biguint/addition.rs index ac6c0dde..622e1d80 100644 --- a/src/biguint/addition.rs +++ b/src/biguint/addition.rs @@ -7,7 +7,7 @@ use crate::UsizePromotion; use core::iter::Sum; use core::ops::{Add, AddAssign}; -use num_traits::{CheckedAdd, Zero}; +use num_traits::CheckedAdd; #[cfg(all(use_addcarry, target_arch = "x86_64"))] use core::arch::x86_64 as arch; diff --git a/src/biguint/convert.rs b/src/biguint/convert.rs index 4d983676..59df82b9 100644 --- a/src/biguint/convert.rs +++ b/src/biguint/convert.rs @@ -159,7 +159,7 @@ pub(super) fn from_radix_be(buf: &[u8], radix: u32) -> Option { ); if buf.is_empty() { - return Some(Zero::zero()); + return Some(BigUint::ZERO); } if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { @@ -190,7 +190,7 @@ pub(super) fn from_radix_le(buf: &[u8], radix: u32) -> Option { ); if buf.is_empty() { - return Some(Zero::zero()); + return Some(BigUint::ZERO); } if radix != 256 && buf.iter().any(|&b| b >= radix as u8) { @@ -469,7 +469,7 @@ impl FromPrimitive for BigUint { // handle 0.x, -0.x if n.is_zero() { - return Some(BigUint::zero()); + return Some(Self::ZERO); } let (mantissa, exponent, sign) = FloatCore::integer_decode(n); @@ -491,7 +491,7 @@ impl FromPrimitive for BigUint { impl From for BigUint { #[inline] fn from(mut n: u64) -> Self { - let mut ret: BigUint = Zero::zero(); + let mut ret: BigUint = Self::ZERO; while n != 0 { ret.data.push(n as BigDigit); @@ -506,7 +506,7 @@ impl From for BigUint { impl From for BigUint { #[inline] fn from(mut n: u128) -> Self { - let mut ret: BigUint = Zero::zero(); + let mut ret: BigUint = Self::ZERO; while n != 0 { ret.data.push(n as BigDigit); @@ -593,7 +593,7 @@ impl From for BigUint { if x { One::one() } else { - Zero::zero() + Self::ZERO } } } diff --git a/src/biguint/division.rs b/src/biguint/division.rs index 6b91726a..d233c8cb 100644 --- a/src/biguint/division.rs +++ b/src/biguint/division.rs @@ -121,12 +121,12 @@ fn div_rem(mut u: BigUint, mut d: BigUint) -> (BigUint, BigUint) { panic!("attempt to divide by zero") } if u.is_zero() { - return (Zero::zero(), Zero::zero()); + return (BigUint::ZERO, BigUint::ZERO); } if d.data.len() == 1 { if d.data == [1] { - return (u, Zero::zero()); + return (u, BigUint::ZERO); } let (div, rem) = div_rem_digit(u, d.data[0]); // reuse d @@ -137,10 +137,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 (Zero::zero(), u), + Less => return (BigUint::ZERO, u), Equal => { u.set_one(); - return (u, Zero::zero()); + return (u, BigUint::ZERO); } Greater => {} // Do nothing } @@ -168,12 +168,12 @@ pub(super) fn div_rem_ref(u: &BigUint, d: &BigUint) -> (BigUint, BigUint) { panic!("attempt to divide by zero") } if u.is_zero() { - return (Zero::zero(), Zero::zero()); + return (BigUint::ZERO, BigUint::ZERO); } if d.data.len() == 1 { if d.data == [1] { - return (u.clone(), Zero::zero()); + return (u.clone(), BigUint::ZERO); } let (div, rem) = div_rem_digit(u.clone(), d.data[0]); @@ -182,8 +182,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 (Zero::zero(), u.clone()), - Equal => return (One::one(), Zero::zero()), + Less => return (BigUint::ZERO, u.clone()), + Equal => return (One::one(), BigUint::ZERO), Greater => {} // Do nothing } @@ -360,7 +360,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]), - _ => Zero::zero(), + _ => BigUint::ZERO, } } } @@ -378,7 +378,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, Zero::zero()); + let temp = mem::replace(self, Self::ZERO); *self = temp / other; } } @@ -393,7 +393,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])), - _ => Zero::zero(), + _ => BigUint::ZERO, } } @@ -403,7 +403,7 @@ impl Div for u64 { match other.data.len() { 0 => panic!("attempt to divide by zero"), 1 => From::from(self / other.data[0]), - _ => Zero::zero(), + _ => BigUint::ZERO, } } } @@ -441,7 +441,7 @@ impl Div for u128 { 4 => From::from( self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]), ), - _ => Zero::zero(), + _ => BigUint::ZERO, } } @@ -452,7 +452,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])), - _ => Zero::zero(), + _ => BigUint::ZERO, } } } diff --git a/src/biguint/monty.rs b/src/biguint/monty.rs index abaca50c..484034e4 100644 --- a/src/biguint/monty.rs +++ b/src/biguint/monty.rs @@ -1,7 +1,7 @@ use crate::std_alloc::Vec; use core::mem; use core::ops::Shl; -use num_traits::{One, Zero}; +use num_traits::One; use crate::big_digit::{self, BigDigit, DoubleBigDigit, SignedDoubleBigDigit}; use crate::biguint::BigUint; @@ -56,7 +56,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; @@ -173,7 +173,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 fe56ac36..c2f547d6 100644 --- a/src/biguint/multiplication.rs +++ b/src/biguint/multiplication.rs @@ -457,7 +457,7 @@ fn sub_sign(mut a: &[BigDigit], mut b: &[BigDigit]) -> (Sign, BigUint) { sub2(&mut b, a); (Minus, biguint_from_vec(b)) } - Ordering::Equal => (NoSign, Zero::zero()), + Ordering::Equal => (NoSign, BigUint::ZERO), } } @@ -470,7 +470,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 621e1b15..fa1c4926 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() { - BigUint::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/shift.rs b/src/biguint/shift.rs index 00326bb5..f603537a 100644 --- a/src/biguint/shift.rs +++ b/src/biguint/shift.rs @@ -135,7 +135,7 @@ macro_rules! impl_shift { impl ShlAssign<$rhs> for BigUint { #[inline] fn shl_assign(&mut self, rhs: $rhs) { - let n = mem::replace(self, BigUint::zero()); + let n = mem::replace(self, Self::ZERO); *self = n << rhs; } } @@ -160,7 +160,7 @@ macro_rules! impl_shift { impl ShrAssign<$rhs> for BigUint { #[inline] fn shr_assign(&mut self, rhs: $rhs) { - let n = mem::replace(self, BigUint::zero()); + let n = mem::replace(self, Self::ZERO); *self = n >> rhs; } } diff --git a/src/biguint/subtraction.rs b/src/biguint/subtraction.rs index b7cf59dd..1d2de047 100644 --- a/src/biguint/subtraction.rs +++ b/src/biguint/subtraction.rs @@ -7,7 +7,7 @@ use crate::UsizePromotion; use core::cmp::Ordering::{Equal, Greater, Less}; use core::ops::{Sub, SubAssign}; -use num_traits::{CheckedSub, Zero}; +use num_traits::CheckedSub; #[cfg(all(use_addcarry, target_arch = "x86_64"))] use core::arch::x86_64 as arch; @@ -305,7 +305,7 @@ impl CheckedSub for BigUint { fn checked_sub(&self, v: &BigUint) -> Option { match self.cmp(v) { Less => None, - Equal => Some(Zero::zero()), + Equal => Some(Self::ZERO), Greater => Some(self.sub(v)), } } diff --git a/src/lib.rs b/src/lib.rs index 6bf2edf7..ea7bd95c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,12 +21,12 @@ //! ```rust //! # fn main() { //! use num_bigint::BigUint; -//! use num_traits::{Zero, One}; +//! use num_traits::One; //! //! // Calculate large fibonacci numbers. //! fn fib(n: usize) -> BigUint { -//! let mut f0: BigUint = Zero::zero(); -//! let mut f1: BigUint = One::one(); +//! let mut f0 = BigUint::ZERO; +//! let mut f1 = BigUint::one(); //! for _ in 0..n { //! let f2 = f0 + &f1; //! f0 = f1; diff --git a/src/macros.rs b/src/macros.rs index 16186165..8977f217 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -418,7 +418,7 @@ macro_rules! impl_sum_iter_type { where I: Iterator, { - iter.fold(Zero::zero(), <$res>::add) + iter.fold(Self::ZERO, <$res>::add) } } }; From 2d13702aea28777abd25d7db4456a9eba10d3a3b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 3 May 2024 15:38:54 -0700 Subject: [PATCH 3/3] Implement `Integer::dec` and `inc` --- Cargo.toml | 2 +- src/bigint.rs | 8 ++++++++ src/biguint.rs | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index dc8da257..a3bdcea3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ name = "shootout-pidigits" [dependencies] [dependencies.num-integer] -version = "0.1.42" +version = "0.1.46" default-features = false features = ["i128"] diff --git a/src/bigint.rs b/src/bigint.rs index 7ab72cb6..d6d524b2 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -510,6 +510,14 @@ impl Integer for BigInt { fn prev_multiple_of(&self, other: &Self) -> Self { self - self.mod_floor(other) } + + fn dec(&mut self) { + *self -= 1u32; + } + + fn inc(&mut self) { + *self += 1u32; + } } impl Roots for BigInt { diff --git a/src/biguint.rs b/src/biguint.rs index 245bcba5..ffa3858a 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -325,6 +325,14 @@ impl Integer for BigUint { fn prev_multiple_of(&self, other: &Self) -> Self { self - self.mod_floor(other) } + + fn dec(&mut self) { + *self -= 1u32; + } + + fn inc(&mut self) { + *self += 1u32; + } } #[inline]