Skip to content

Commit

Permalink
Merge pull request #298 from cuviper/impls
Browse files Browse the repository at this point in the history
Add `const ZERO` and additional trait implementations
  • Loading branch information
cuviper committed May 3, 2024
2 parents 396b0a1 + 2d13702 commit ba9d00c
Show file tree
Hide file tree
Showing 19 changed files with 146 additions and 90 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Expand Up @@ -45,12 +45,12 @@ name = "shootout-pidigits"
[dependencies]

[dependencies.num-integer]
version = "0.1.42"
version = "0.1.46"
default-features = false
features = ["i128"]

[dependencies.num-traits]
version = "0.2.16"
version = "0.2.18"
default-features = false
features = ["i128"]

Expand Down
44 changes: 29 additions & 15 deletions src/bigint.rs
Expand Up @@ -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};

Expand Down Expand Up @@ -132,7 +132,7 @@ impl Ord for BigInt {
impl Default for BigInt {
#[inline]
fn default() -> BigInt {
Zero::zero()
Self::ZERO
}
}

Expand Down Expand Up @@ -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]
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}
Expand All @@ -273,7 +275,7 @@ impl Signed for BigInt {
match self.sign {
Plus => BigInt::one(),
Minus => -BigInt::one(),
NoSign => BigInt::zero(),
NoSign => Self::ZERO,
}
}

Expand Down Expand Up @@ -462,7 +464,7 @@ impl Integer for BigInt {
fn extended_gcd_lcm(&self, other: &BigInt) -> (num_integer::ExtendedGcd<BigInt>, 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)
};
Expand Down Expand Up @@ -508,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 {
Expand Down Expand Up @@ -567,6 +577,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 2<sup>32</sup> digits are ordered least significant digit first.
Expand Down Expand Up @@ -922,11 +938,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 {
Expand All @@ -943,7 +958,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 {
Expand All @@ -957,11 +972,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) {
Expand All @@ -980,7 +994,7 @@ impl BigInt {
pub fn to_biguint(&self) -> Option<BigUint> {
match self.sign {
Plus => Some(self.data.clone()),
NoSign => Some(Zero::zero()),
NoSign => Some(BigUint::ZERO),
Minus => None,
}
}
Expand Down
18 changes: 9 additions & 9 deletions src/bigint/addition.rs
Expand Up @@ -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
Expand All @@ -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,
},
}
};
Expand Down Expand Up @@ -76,7 +76,7 @@ impl Add<BigInt> 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;
}
}
Expand All @@ -97,7 +97,7 @@ impl Add<u32> 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),
},
Expand All @@ -108,7 +108,7 @@ impl Add<u32> for BigInt {
impl AddAssign<u32> 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;
}
}
Expand All @@ -122,7 +122,7 @@ impl Add<u64> 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),
},
Expand All @@ -133,7 +133,7 @@ impl Add<u64> for BigInt {
impl AddAssign<u64> 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;
}
}
Expand All @@ -147,7 +147,7 @@ impl Add<u128> 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),
},
Expand All @@ -157,7 +157,7 @@ impl Add<u128> for BigInt {
impl AddAssign<u128> 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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/bigint/bits.rs
Expand Up @@ -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,
Expand Down
16 changes: 8 additions & 8 deletions src/bigint/convert.rs
Expand Up @@ -228,7 +228,7 @@ impl From<u64> for BigInt {
data: BigUint::from(n),
}
} else {
BigInt::zero()
Self::ZERO
}
}
}
Expand All @@ -242,7 +242,7 @@ impl From<u128> for BigInt {
data: BigUint::from(n),
}
} else {
BigInt::zero()
Self::ZERO
}
}
}
Expand All @@ -267,7 +267,7 @@ impl From<BigUint> for BigInt {
#[inline]
fn from(n: BigUint) -> Self {
if n.is_zero() {
BigInt::zero()
Self::ZERO
} else {
BigInt {
sign: Plus,
Expand All @@ -288,7 +288,7 @@ impl ToBigInt for BigUint {
#[inline]
fn to_bigint(&self) -> Option<BigInt> {
if self.is_zero() {
Some(Zero::zero())
Some(BigInt::ZERO)
} else {
Some(BigInt {
sign: Plus,
Expand All @@ -303,7 +303,7 @@ impl ToBigUint for BigInt {
fn to_biguint(&self) -> Option<BigUint> {
match self.sign() {
Plus => Some(self.data.clone()),
NoSign => Some(Zero::zero()),
NoSign => Some(BigUint::ZERO),
Minus => None,
}
}
Expand Down Expand Up @@ -366,7 +366,7 @@ impl From<bool> for BigInt {
if x {
One::one()
} else {
Zero::zero()
Self::ZERO
}
}
}
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down
17 changes: 17 additions & 0 deletions src/bigint/division.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
}
}
2 changes: 1 addition & 1 deletion src/bigint/power.rs
Expand Up @@ -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`.
Expand Down

0 comments on commit ba9d00c

Please sign in to comment.