Skip to content

Commit

Permalink
Merge #193
Browse files Browse the repository at this point in the history
193: Split into more modules r=cuviper a=cuviper

There should be no functional change in this.

Co-authored-by: Josh Stone <cuviper@gmail.com>
  • Loading branch information
bors[bot] and cuviper committed Feb 25, 2021
2 parents d9287a4 + a6e88c5 commit 72810a5
Show file tree
Hide file tree
Showing 25 changed files with 6,198 additions and 6,021 deletions.
936 changes: 0 additions & 936 deletions src/algorithms.rs

This file was deleted.

2,520 changes: 70 additions & 2,450 deletions src/bigint.rs

Large diffs are not rendered by default.

239 changes: 239 additions & 0 deletions src/bigint/addition.rs
@@ -0,0 +1,239 @@
use super::CheckedUnsignedAbs::{Negative, Positive};
use super::Sign::{Minus, NoSign, Plus};
use super::{BigInt, UnsignedAbs};

use crate::{IsizePromotion, UsizePromotion};

use core::cmp::Ordering::{Equal, Greater, Less};
use core::iter::Sum;
use core::mem;
use core::ops::{Add, AddAssign};
use num_traits::{CheckedAdd, Zero};

// 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
// val/ref combination, deferring that decision to BigUint's own forwarding.
macro_rules! bigint_add {
($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => {
match ($a.sign, $b.sign) {
(_, NoSign) => $a_owned,
(NoSign, _) => $b_owned,
// same sign => keep the sign with the sum of magnitudes
(Plus, Plus) | (Minus, Minus) => BigInt::from_biguint($a.sign, $a_data + $b_data),
// opposite signs => keep the sign of the larger with the difference of magnitudes
(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(),
},
}
};
}

impl<'a, 'b> Add<&'b BigInt> for &'a BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: &BigInt) -> BigInt {
bigint_add!(
self,
self.clone(),
&self.data,
other,
other.clone(),
&other.data
)
}
}

impl<'a> Add<BigInt> for &'a BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: BigInt) -> BigInt {
bigint_add!(self, self.clone(), &self.data, other, other, other.data)
}
}

impl<'a> Add<&'a BigInt> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: &BigInt) -> BigInt {
bigint_add!(self, self, self.data, other, other.clone(), &other.data)
}
}

impl Add<BigInt> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: BigInt) -> BigInt {
bigint_add!(self, self, self.data, other, other, other.data)
}
}

impl<'a> AddAssign<&'a BigInt> for BigInt {
#[inline]
fn add_assign(&mut self, other: &BigInt) {
let n = mem::replace(self, BigInt::zero());
*self = n + other;
}
}
forward_val_assign!(impl AddAssign for BigInt, add_assign);

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<u32> for BigInt, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u64> for BigInt, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u128> for BigInt, add);

impl Add<u32> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: u32) -> BigInt {
match self.sign {
NoSign => From::from(other),
Plus => BigInt::from(self.data + other),
Minus => match self.data.cmp(&From::from(other)) {
Equal => Zero::zero(),
Less => BigInt::from(other - self.data),
Greater => -BigInt::from(self.data - other),
},
}
}
}

impl AddAssign<u32> for BigInt {
#[inline]
fn add_assign(&mut self, other: u32) {
let n = mem::replace(self, BigInt::zero());
*self = n + other;
}
}

impl Add<u64> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: u64) -> BigInt {
match self.sign {
NoSign => From::from(other),
Plus => BigInt::from(self.data + other),
Minus => match self.data.cmp(&From::from(other)) {
Equal => Zero::zero(),
Less => BigInt::from(other - self.data),
Greater => -BigInt::from(self.data - other),
},
}
}
}

impl AddAssign<u64> for BigInt {
#[inline]
fn add_assign(&mut self, other: u64) {
let n = mem::replace(self, BigInt::zero());
*self = n + other;
}
}

impl Add<u128> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: u128) -> BigInt {
match self.sign {
NoSign => BigInt::from(other),
Plus => BigInt::from(self.data + other),
Minus => match self.data.cmp(&From::from(other)) {
Equal => BigInt::zero(),
Less => BigInt::from(other - self.data),
Greater => -BigInt::from(self.data - other),
},
}
}
}
impl AddAssign<u128> for BigInt {
#[inline]
fn add_assign(&mut self, other: u128) {
let n = mem::replace(self, BigInt::zero());
*self = n + other;
}
}

forward_all_scalar_binop_to_val_val_commutative!(impl Add<i32> for BigInt, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<i64> for BigInt, add);
forward_all_scalar_binop_to_val_val_commutative!(impl Add<i128> for BigInt, add);

impl Add<i32> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: i32) -> BigInt {
match other.checked_uabs() {
Positive(u) => self + u,
Negative(u) => self - u,
}
}
}
impl AddAssign<i32> for BigInt {
#[inline]
fn add_assign(&mut self, other: i32) {
match other.checked_uabs() {
Positive(u) => *self += u,
Negative(u) => *self -= u,
}
}
}

impl Add<i64> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: i64) -> BigInt {
match other.checked_uabs() {
Positive(u) => self + u,
Negative(u) => self - u,
}
}
}
impl AddAssign<i64> for BigInt {
#[inline]
fn add_assign(&mut self, other: i64) {
match other.checked_uabs() {
Positive(u) => *self += u,
Negative(u) => *self -= u,
}
}
}

impl Add<i128> for BigInt {
type Output = BigInt;

#[inline]
fn add(self, other: i128) -> BigInt {
match other.checked_uabs() {
Positive(u) => self + u,
Negative(u) => self - u,
}
}
}
impl AddAssign<i128> for BigInt {
#[inline]
fn add_assign(&mut self, other: i128) {
match other.checked_uabs() {
Positive(u) => *self += u,
Negative(u) => *self -= u,
}
}
}

impl CheckedAdd for BigInt {
#[inline]
fn checked_add(&self, v: &BigInt) -> Option<BigInt> {
Some(self.add(v))
}
}

impl_sum_iter_type!(BigInt);
34 changes: 34 additions & 0 deletions src/bigint/arbitrary.rs
@@ -0,0 +1,34 @@
use super::{BigInt, Sign};

use crate::std_alloc::Box;
use crate::BigUint;

#[cfg(feature = "quickcheck")]
impl quickcheck::Arbitrary for BigInt {
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
let positive = bool::arbitrary(g);
let sign = if positive { Sign::Plus } else { Sign::Minus };
Self::from_biguint(sign, BigUint::arbitrary(g))
}

fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let sign = self.sign();
let unsigned_shrink = self.data.shrink();
Box::new(unsigned_shrink.map(move |x| BigInt::from_biguint(sign, x)))
}
}

#[cfg(feature = "arbitrary")]
impl arbitrary::Arbitrary for BigInt {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let positive = bool::arbitrary(u)?;
let sign = if positive { Sign::Plus } else { Sign::Minus };
Ok(Self::from_biguint(sign, BigUint::arbitrary(u)?))
}

fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let sign = self.sign();
let unsigned_shrink = self.data.shrink();
Box::new(unsigned_shrink.map(move |x| BigInt::from_biguint(sign, x)))
}
}

0 comments on commit 72810a5

Please sign in to comment.