feat: implement operators with 128bit
This commit is contained in:
parent
1a316783b5
commit
35939287b9
456
src/bigint.rs
456
src/bigint.rs
@ -877,6 +877,17 @@ fn i64_abs_as_u64(a: i64) -> u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A convenience method for getting the absolute value of an i128 in a u128.
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
#[inline]
|
||||||
|
fn i128_abs_as_u128(a: i128) -> u128 {
|
||||||
|
if a == i128::min_value() {
|
||||||
|
a as u128
|
||||||
|
} else {
|
||||||
|
a.abs() as u128
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We want to forward to BigUint::add, but it's not clear how that will go until
|
// 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
|
// we compare both sign and magnitude. So we duplicate this body for every
|
||||||
// val/ref combination, deferring that decision to BigUint's own forwarding.
|
// val/ref combination, deferring that decision to BigUint's own forwarding.
|
||||||
@ -951,14 +962,16 @@ forward_val_assign!(impl AddAssign for BigInt, add_assign);
|
|||||||
|
|
||||||
promote_all_scalars!(impl Add for BigInt, add);
|
promote_all_scalars!(impl Add for BigInt, add);
|
||||||
promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign);
|
promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Add<BigDigit> for BigInt, add);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u32> for BigInt, add);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Add<DoubleBigDigit> for BigInt, add);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u64> for BigInt, add);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u128> for BigInt, add);
|
||||||
|
|
||||||
impl Add<BigDigit> for BigInt {
|
impl Add<u32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(self, other: BigDigit) -> BigInt {
|
fn add(self, other: u32) -> BigInt {
|
||||||
match self.sign {
|
match self.sign {
|
||||||
NoSign => From::from(other),
|
NoSign => From::from(other),
|
||||||
Plus => BigInt::from_biguint(Plus, self.data + other),
|
Plus => BigInt::from_biguint(Plus, self.data + other),
|
||||||
@ -970,19 +983,19 @@ impl Add<BigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl AddAssign<BigDigit> for BigInt {
|
impl AddAssign<u32> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_assign(&mut self, other: BigDigit) {
|
fn add_assign(&mut self, other: u32) {
|
||||||
let n = mem::replace(self, BigInt::zero());
|
let n = mem::replace(self, BigInt::zero());
|
||||||
*self = n + other;
|
*self = n + other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add<DoubleBigDigit> for BigInt {
|
impl Add<u64> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(self, other: DoubleBigDigit) -> BigInt {
|
fn add(self, other: u64) -> BigInt {
|
||||||
match self.sign {
|
match self.sign {
|
||||||
NoSign => From::from(other),
|
NoSign => From::from(other),
|
||||||
Plus => BigInt::from_biguint(Plus, self.data + other),
|
Plus => BigInt::from_biguint(Plus, self.data + other),
|
||||||
@ -994,9 +1007,35 @@ impl Add<DoubleBigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl AddAssign<DoubleBigDigit> for BigInt {
|
impl AddAssign<u64> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_assign(&mut self, other: DoubleBigDigit) {
|
fn add_assign(&mut self, other: u64) {
|
||||||
|
let n = mem::replace(self, BigInt::zero());
|
||||||
|
*self = n + other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Add<u128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add(self, other: u128) -> BigInt {
|
||||||
|
match self.sign {
|
||||||
|
NoSign => From::from(other),
|
||||||
|
Plus => BigInt::from_biguint(Plus, self.data + other),
|
||||||
|
Minus => match self.data.cmp(&From::from(other)) {
|
||||||
|
Equal => Zero::zero(),
|
||||||
|
Less => BigInt::from_biguint(Plus, other - self.data),
|
||||||
|
Greater => BigInt::from_biguint(Minus, self.data - other),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
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, BigInt::zero());
|
||||||
*self = n + other;
|
*self = n + other;
|
||||||
}
|
}
|
||||||
@ -1004,6 +1043,8 @@ impl AddAssign<DoubleBigDigit> for BigInt {
|
|||||||
|
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Add<i32> for BigInt, add);
|
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<i64> for BigInt, add);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<i128> for BigInt, add);
|
||||||
|
|
||||||
impl Add<i32> for BigInt {
|
impl Add<i32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
@ -1051,6 +1092,31 @@ impl AddAssign<i64> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Add<i128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add(self, other: i128) -> BigInt {
|
||||||
|
if other >= 0 {
|
||||||
|
self + other as u128
|
||||||
|
} else {
|
||||||
|
self - i128_abs_as_u128(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl AddAssign<i128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, other: i128) {
|
||||||
|
if other >= 0 {
|
||||||
|
*self += other as u128;
|
||||||
|
} else {
|
||||||
|
*self -= i128_abs_as_u128(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We want to forward to BigUint::sub, but it's not clear how that will go until
|
// 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
|
// we compare both sign and magnitude. So we duplicate this body for every
|
||||||
// val/ref combination, deferring that decision to BigUint's own forwarding.
|
// val/ref combination, deferring that decision to BigUint's own forwarding.
|
||||||
@ -1127,14 +1193,16 @@ forward_val_assign!(impl SubAssign for BigInt, sub_assign);
|
|||||||
|
|
||||||
promote_all_scalars!(impl Sub for BigInt, sub);
|
promote_all_scalars!(impl Sub for BigInt, sub);
|
||||||
promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign);
|
promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<BigDigit> for BigInt, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigInt, sub);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<DoubleBigDigit> for BigInt, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigInt, sub);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigInt, sub);
|
||||||
|
|
||||||
impl Sub<BigDigit> for BigInt {
|
impl Sub<u32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, other: BigDigit) -> BigInt {
|
fn sub(self, other: u32) -> BigInt {
|
||||||
match self.sign {
|
match self.sign {
|
||||||
NoSign => BigInt::from_biguint(Minus, From::from(other)),
|
NoSign => BigInt::from_biguint(Minus, From::from(other)),
|
||||||
Minus => BigInt::from_biguint(Minus, self.data + other),
|
Minus => BigInt::from_biguint(Minus, self.data + other),
|
||||||
@ -1146,15 +1214,15 @@ impl Sub<BigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl SubAssign<BigDigit> for BigInt {
|
impl SubAssign<u32> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub_assign(&mut self, other: BigDigit) {
|
fn sub_assign(&mut self, other: u32) {
|
||||||
let n = mem::replace(self, BigInt::zero());
|
let n = mem::replace(self, BigInt::zero());
|
||||||
*self = n - other;
|
*self = n - other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub<BigInt> for BigDigit {
|
impl Sub<BigInt> for u32 {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1163,11 +1231,29 @@ impl Sub<BigInt> for BigDigit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub<DoubleBigDigit> for BigInt {
|
impl Sub<BigInt> for u64 {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, other: DoubleBigDigit) -> BigInt {
|
fn sub(self, other: BigInt) -> BigInt {
|
||||||
|
-(other - self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Sub<BigInt> for u128 {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, other: BigInt) -> BigInt {
|
||||||
|
-(other - self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<u64> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, other: u64) -> BigInt {
|
||||||
match self.sign {
|
match self.sign {
|
||||||
NoSign => BigInt::from_biguint(Minus, From::from(other)),
|
NoSign => BigInt::from_biguint(Minus, From::from(other)),
|
||||||
Minus => BigInt::from_biguint(Minus, self.data + other),
|
Minus => BigInt::from_biguint(Minus, self.data + other),
|
||||||
@ -1179,25 +1265,44 @@ impl Sub<DoubleBigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl SubAssign<DoubleBigDigit> for BigInt {
|
impl SubAssign<u64> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub_assign(&mut self, other: DoubleBigDigit) {
|
fn sub_assign(&mut self, other: u64) {
|
||||||
let n = mem::replace(self, BigInt::zero());
|
let n = mem::replace(self, BigInt::zero());
|
||||||
*self = n - other;
|
*self = n - other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub<BigInt> for DoubleBigDigit {
|
#[cfg(has_i128)]
|
||||||
|
impl Sub<u128> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, other: BigInt) -> BigInt {
|
fn sub(self, other: u128) -> BigInt {
|
||||||
-(other - self)
|
match self.sign {
|
||||||
|
NoSign => BigInt::from_biguint(Minus, From::from(other)),
|
||||||
|
Minus => BigInt::from_biguint(Minus, self.data + other),
|
||||||
|
Plus => match self.data.cmp(&From::from(other)) {
|
||||||
|
Equal => Zero::zero(),
|
||||||
|
Greater => BigInt::from_biguint(Plus, self.data - other),
|
||||||
|
Less => BigInt::from_biguint(Minus, other - self.data),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl SubAssign<u128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, other: u128) {
|
||||||
|
let n = mem::replace(self, BigInt::zero());
|
||||||
|
*self = n - other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<i32> for BigInt, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<i32> for BigInt, sub);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<i64> for BigInt, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<i64> for BigInt, sub);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Sub<i128> for BigInt, sub);
|
||||||
|
|
||||||
impl Sub<i32> for BigInt {
|
impl Sub<i32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
@ -1271,6 +1376,44 @@ impl Sub<BigInt> for i64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Sub<i128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, other: i128) -> BigInt {
|
||||||
|
if other >= 0 {
|
||||||
|
self - other as u128
|
||||||
|
} else {
|
||||||
|
self + i128_abs_as_u128(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl SubAssign<i128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, other: i128) {
|
||||||
|
if other >= 0 {
|
||||||
|
*self -= other as u128;
|
||||||
|
} else {
|
||||||
|
*self += i128_abs_as_u128(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Sub<BigInt> for i128 {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, other: BigInt) -> BigInt {
|
||||||
|
if self >= 0 {
|
||||||
|
self as u128 - other
|
||||||
|
} else {
|
||||||
|
-other - i128_abs_as_u128(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Mul for BigInt, mul);
|
forward_all_binop_to_ref_ref!(impl Mul for BigInt, mul);
|
||||||
|
|
||||||
impl<'a, 'b> Mul<&'b BigInt> for &'a BigInt {
|
impl<'a, 'b> Mul<&'b BigInt> for &'a BigInt {
|
||||||
@ -1292,21 +1435,23 @@ forward_val_assign!(impl MulAssign for BigInt, mul_assign);
|
|||||||
|
|
||||||
promote_all_scalars!(impl Mul for BigInt, mul);
|
promote_all_scalars!(impl Mul for BigInt, mul);
|
||||||
promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign);
|
promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<BigDigit> for BigInt, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u32> for BigInt, mul);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<DoubleBigDigit> for BigInt, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u64> for BigInt, mul);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u128> for BigInt, mul);
|
||||||
|
|
||||||
impl Mul<BigDigit> for BigInt {
|
impl Mul<u32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(self, other: BigDigit) -> BigInt {
|
fn mul(self, other: u32) -> BigInt {
|
||||||
BigInt::from_biguint(self.sign, self.data * other)
|
BigInt::from_biguint(self.sign, self.data * other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MulAssign<BigDigit> for BigInt {
|
impl MulAssign<u32> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_assign(&mut self, other: BigDigit) {
|
fn mul_assign(&mut self, other: u32) {
|
||||||
self.data *= other;
|
self.data *= other;
|
||||||
if self.data.is_zero() {
|
if self.data.is_zero() {
|
||||||
self.sign = NoSign;
|
self.sign = NoSign;
|
||||||
@ -1314,18 +1459,37 @@ impl MulAssign<BigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<DoubleBigDigit> for BigInt {
|
impl Mul<u64> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(self, other: DoubleBigDigit) -> BigInt {
|
fn mul(self, other: u64) -> BigInt {
|
||||||
BigInt::from_biguint(self.sign, self.data * other)
|
BigInt::from_biguint(self.sign, self.data * other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MulAssign<DoubleBigDigit> for BigInt {
|
impl MulAssign<u64> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_assign(&mut self, other: DoubleBigDigit) {
|
fn mul_assign(&mut self, other: u64) {
|
||||||
|
self.data *= other;
|
||||||
|
if self.data.is_zero() {
|
||||||
|
self.sign = NoSign;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Mul<u128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, other: u128) -> BigInt {
|
||||||
|
BigInt::from_biguint(self.sign, self.data * other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl MulAssign<u128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: u128) {
|
||||||
self.data *= other;
|
self.data *= other;
|
||||||
if self.data.is_zero() {
|
if self.data.is_zero() {
|
||||||
self.sign = NoSign;
|
self.sign = NoSign;
|
||||||
@ -1335,6 +1499,8 @@ impl MulAssign<DoubleBigDigit> for BigInt {
|
|||||||
|
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i32> for BigInt, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i32> for BigInt, mul);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i64> for BigInt, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i64> for BigInt, mul);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i128> for BigInt, mul);
|
||||||
|
|
||||||
impl Mul<i32> for BigInt {
|
impl Mul<i32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
@ -1385,6 +1551,31 @@ impl MulAssign<i64> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Mul<i128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, other: i128) -> BigInt {
|
||||||
|
if other >= 0 {
|
||||||
|
self * other as u128
|
||||||
|
} else {
|
||||||
|
-(self * i128_abs_as_u128(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl MulAssign<i128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: i128) {
|
||||||
|
if other >= 0 {
|
||||||
|
*self *= other as u128;
|
||||||
|
} else {
|
||||||
|
self.sign = -self.sign;
|
||||||
|
*self *= i128_abs_as_u128(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Div for BigInt, div);
|
forward_all_binop_to_ref_ref!(impl Div for BigInt, div);
|
||||||
|
|
||||||
@ -1408,21 +1599,23 @@ forward_val_assign!(impl DivAssign for BigInt, div_assign);
|
|||||||
|
|
||||||
promote_all_scalars!(impl Div for BigInt, div);
|
promote_all_scalars!(impl Div for BigInt, div);
|
||||||
promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign);
|
promote_all_scalars_assign!(impl DivAssign for BigInt, div_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigInt, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<u32> for BigInt, div);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<DoubleBigDigit> for BigInt, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<u64> for BigInt, div);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Div<u128> for BigInt, div);
|
||||||
|
|
||||||
impl Div<BigDigit> for BigInt {
|
impl Div<u32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self, other: BigDigit) -> BigInt {
|
fn div(self, other: u32) -> BigInt {
|
||||||
BigInt::from_biguint(self.sign, self.data / other)
|
BigInt::from_biguint(self.sign, self.data / other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DivAssign<BigDigit> for BigInt {
|
impl DivAssign<u32> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div_assign(&mut self, other: BigDigit) {
|
fn div_assign(&mut self, other: u32) {
|
||||||
self.data /= other;
|
self.data /= other;
|
||||||
if self.data.is_zero() {
|
if self.data.is_zero() {
|
||||||
self.sign = NoSign;
|
self.sign = NoSign;
|
||||||
@ -1430,7 +1623,7 @@ impl DivAssign<BigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<BigInt> for BigDigit {
|
impl Div<BigInt> for u32 {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1439,18 +1632,18 @@ impl Div<BigInt> for BigDigit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<DoubleBigDigit> for BigInt {
|
impl Div<u64> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self, other: DoubleBigDigit) -> BigInt {
|
fn div(self, other: u64) -> BigInt {
|
||||||
BigInt::from_biguint(self.sign, self.data / other)
|
BigInt::from_biguint(self.sign, self.data / other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DivAssign<DoubleBigDigit> for BigInt {
|
impl DivAssign<u64> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div_assign(&mut self, other: DoubleBigDigit) {
|
fn div_assign(&mut self, other: u64) {
|
||||||
self.data /= other;
|
self.data /= other;
|
||||||
if self.data.is_zero() {
|
if self.data.is_zero() {
|
||||||
self.sign = NoSign;
|
self.sign = NoSign;
|
||||||
@ -1458,7 +1651,38 @@ impl DivAssign<DoubleBigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<BigInt> for DoubleBigDigit {
|
impl Div<BigInt> for u64 {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: BigInt) -> BigInt {
|
||||||
|
BigInt::from_biguint(other.sign, self / other.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Div<u128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: u128) -> BigInt {
|
||||||
|
BigInt::from_biguint(self.sign, self.data / other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl DivAssign<u128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, other: u128) {
|
||||||
|
self.data /= other;
|
||||||
|
if self.data.is_zero() {
|
||||||
|
self.sign = NoSign;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Div<BigInt> for u128 {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1469,6 +1693,8 @@ impl Div<BigInt> for DoubleBigDigit {
|
|||||||
|
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<i32> for BigInt, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<i32> for BigInt, div);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<i64> for BigInt, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<i64> for BigInt, div);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Div<i128> for BigInt, div);
|
||||||
|
|
||||||
impl Div<i32> for BigInt {
|
impl Div<i32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
@ -1546,6 +1772,47 @@ impl Div<BigInt> for i64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Div<i128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: i128) -> BigInt {
|
||||||
|
if other >= 0 {
|
||||||
|
self / other as u128
|
||||||
|
} else {
|
||||||
|
-(self / i128_abs_as_u128(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl DivAssign<i128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, other: i128) {
|
||||||
|
if other >= 0 {
|
||||||
|
*self /= other as u128;
|
||||||
|
} else {
|
||||||
|
self.sign = -self.sign;
|
||||||
|
*self /= i128_abs_as_u128(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Div<BigInt> for i128 {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: BigInt) -> BigInt {
|
||||||
|
if self >= 0 {
|
||||||
|
self as u128 / other
|
||||||
|
} else {
|
||||||
|
-(i128_abs_as_u128(self) / other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem);
|
forward_all_binop_to_ref_ref!(impl Rem for BigInt, rem);
|
||||||
|
|
||||||
impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt {
|
impl<'a, 'b> Rem<&'b BigInt> for &'a BigInt {
|
||||||
@ -1568,21 +1835,23 @@ forward_val_assign!(impl RemAssign for BigInt, rem_assign);
|
|||||||
|
|
||||||
promote_all_scalars!(impl Rem for BigInt, rem);
|
promote_all_scalars!(impl Rem for BigInt, rem);
|
||||||
promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign);
|
promote_all_scalars_assign!(impl RemAssign for BigInt, rem_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigInt, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<u32> for BigInt, rem);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<DoubleBigDigit> for BigInt, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<u64> for BigInt, rem);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Rem<u128> for BigInt, rem);
|
||||||
|
|
||||||
impl Rem<BigDigit> for BigInt {
|
impl Rem<u32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem(self, other: BigDigit) -> BigInt {
|
fn rem(self, other: u32) -> BigInt {
|
||||||
BigInt::from_biguint(self.sign, self.data % other)
|
BigInt::from_biguint(self.sign, self.data % other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemAssign<BigDigit> for BigInt {
|
impl RemAssign<u32> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem_assign(&mut self, other: BigDigit) {
|
fn rem_assign(&mut self, other: u32) {
|
||||||
self.data %= other;
|
self.data %= other;
|
||||||
if self.data.is_zero() {
|
if self.data.is_zero() {
|
||||||
self.sign = NoSign;
|
self.sign = NoSign;
|
||||||
@ -1590,7 +1859,7 @@ impl RemAssign<BigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rem<BigInt> for BigDigit {
|
impl Rem<BigInt> for u32 {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1599,18 +1868,18 @@ impl Rem<BigInt> for BigDigit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rem<DoubleBigDigit> for BigInt {
|
impl Rem<u64> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem(self, other: DoubleBigDigit) -> BigInt {
|
fn rem(self, other: u64) -> BigInt {
|
||||||
BigInt::from_biguint(self.sign, self.data % other)
|
BigInt::from_biguint(self.sign, self.data % other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemAssign<DoubleBigDigit> for BigInt {
|
impl RemAssign<u64> for BigInt {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem_assign(&mut self, other: DoubleBigDigit) {
|
fn rem_assign(&mut self, other: u64) {
|
||||||
self.data %= other;
|
self.data %= other;
|
||||||
if self.data.is_zero() {
|
if self.data.is_zero() {
|
||||||
self.sign = NoSign;
|
self.sign = NoSign;
|
||||||
@ -1618,7 +1887,38 @@ impl RemAssign<DoubleBigDigit> for BigInt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rem<BigInt> for DoubleBigDigit {
|
impl Rem<BigInt> for u64 {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rem(self, other: BigInt) -> BigInt {
|
||||||
|
BigInt::from_biguint(Plus, self % other.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Rem<u128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rem(self, other: u128) -> BigInt {
|
||||||
|
BigInt::from_biguint(self.sign, self.data % other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl RemAssign<u128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn rem_assign(&mut self, other: u128) {
|
||||||
|
self.data %= other;
|
||||||
|
if self.data.is_zero() {
|
||||||
|
self.sign = NoSign;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Rem<BigInt> for u128 {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1629,6 +1929,8 @@ impl Rem<BigInt> for DoubleBigDigit {
|
|||||||
|
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<i32> for BigInt, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<i32> for BigInt, rem);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<i64> for BigInt, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<i64> for BigInt, rem);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Rem<i128> for BigInt, rem);
|
||||||
|
|
||||||
impl Rem<i32> for BigInt {
|
impl Rem<i32> for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
@ -1704,6 +2006,44 @@ impl Rem<BigInt> for i64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Rem<i128> for BigInt {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rem(self, other: i128) -> BigInt {
|
||||||
|
if other >= 0 {
|
||||||
|
self % other as u128
|
||||||
|
} else {
|
||||||
|
self % i128_abs_as_u128(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl RemAssign<i128> for BigInt {
|
||||||
|
#[inline]
|
||||||
|
fn rem_assign(&mut self, other: i128) {
|
||||||
|
if other >= 0 {
|
||||||
|
*self %= other as u128;
|
||||||
|
} else {
|
||||||
|
*self %= i128_abs_as_u128(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Rem<BigInt> for i128 {
|
||||||
|
type Output = BigInt;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rem(self, other: BigInt) -> BigInt {
|
||||||
|
if self >= 0 {
|
||||||
|
self as u128 % other
|
||||||
|
} else {
|
||||||
|
-(i128_abs_as_u128(self) % other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Neg for BigInt {
|
impl Neg for BigInt {
|
||||||
type Output = BigInt;
|
type Output = BigInt;
|
||||||
|
|
||||||
|
391
src/biguint.rs
391
src/biguint.rs
@ -24,7 +24,7 @@ use traits::{
|
|||||||
ToPrimitive, Unsigned, Zero,
|
ToPrimitive, Unsigned, Zero,
|
||||||
};
|
};
|
||||||
|
|
||||||
use big_digit::{self, BigDigit, DoubleBigDigit};
|
use big_digit::{self, BigDigit};
|
||||||
|
|
||||||
#[path = "algorithms.rs"]
|
#[path = "algorithms.rs"]
|
||||||
mod algorithms;
|
mod algorithms;
|
||||||
@ -518,27 +518,30 @@ impl<'a> AddAssign<&'a BigUint> for BigUint {
|
|||||||
|
|
||||||
promote_unsigned_scalars!(impl Add for BigUint, add);
|
promote_unsigned_scalars!(impl Add for BigUint, add);
|
||||||
promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign);
|
promote_unsigned_scalars_assign!(impl AddAssign for BigUint, add_assign);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Add<BigDigit> for BigUint, add);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u32> for BigUint, add);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Add<DoubleBigDigit> for BigUint, add);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u64> for BigUint, add);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val_commutative!(impl Add<u128> for BigUint, add);
|
||||||
|
|
||||||
impl Add<BigDigit> for BigUint {
|
impl Add<u32> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(mut self, other: BigDigit) -> BigUint {
|
fn add(mut self, other: u32) -> BigUint {
|
||||||
self += other;
|
self += other;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl AddAssign<BigDigit> for BigUint {
|
|
||||||
|
impl AddAssign<u32> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_assign(&mut self, other: BigDigit) {
|
fn add_assign(&mut self, other: u32) {
|
||||||
if other != 0 {
|
if other != 0 {
|
||||||
if self.data.len() == 0 {
|
if self.data.len() == 0 {
|
||||||
self.data.push(0);
|
self.data.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let carry = __add2(&mut self.data, &[other]);
|
let carry = __add2(&mut self.data, &[other as BigDigit]);
|
||||||
if carry != 0 {
|
if carry != 0 {
|
||||||
self.data.push(carry);
|
self.data.push(carry);
|
||||||
}
|
}
|
||||||
@ -546,18 +549,19 @@ impl AddAssign<BigDigit> for BigUint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add<DoubleBigDigit> for BigUint {
|
impl Add<u64> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(mut self, other: DoubleBigDigit) -> BigUint {
|
fn add(mut self, other: u64) -> BigUint {
|
||||||
self += other;
|
self += other;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl AddAssign<DoubleBigDigit> for BigUint {
|
|
||||||
|
impl AddAssign<u64> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_assign(&mut self, other: DoubleBigDigit) {
|
fn add_assign(&mut self, other: u64) {
|
||||||
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
||||||
if hi == 0 {
|
if hi == 0 {
|
||||||
*self += lo;
|
*self += lo;
|
||||||
@ -574,6 +578,44 @@ impl AddAssign<DoubleBigDigit> for BigUint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Add<u128> for BigUint {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add(mut self, other: u128) -> BigUint {
|
||||||
|
self += other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl AddAssign<u128> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, other: u128) {
|
||||||
|
if other <= u64::max_value() as u128 {
|
||||||
|
*self += other as u64
|
||||||
|
} else {
|
||||||
|
let (a, b, c, d) = u32_from_u128(other);
|
||||||
|
let carry = if a > 0 {
|
||||||
|
while self.data.len() < 4 {
|
||||||
|
self.data.push(0);
|
||||||
|
}
|
||||||
|
__add2(&mut self.data, &[d, c, b, a])
|
||||||
|
} else {
|
||||||
|
while self.data.len() < 3 {
|
||||||
|
self.data.push(0);
|
||||||
|
}
|
||||||
|
__add2(&mut self.data, &[d, c, b])
|
||||||
|
};
|
||||||
|
|
||||||
|
if carry != 0 {
|
||||||
|
self.data.push(carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward_val_val_binop!(impl Sub for BigUint, sub);
|
forward_val_val_binop!(impl Sub for BigUint, sub);
|
||||||
forward_ref_ref_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_assign!(impl SubAssign for BigUint, sub_assign);
|
||||||
@ -613,57 +655,61 @@ impl<'a> Sub<BigUint> for &'a BigUint {
|
|||||||
|
|
||||||
promote_unsigned_scalars!(impl Sub for BigUint, sub);
|
promote_unsigned_scalars!(impl Sub for BigUint, sub);
|
||||||
promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
|
promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<BigDigit> for BigUint, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigUint, sub);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Sub<DoubleBigDigit> for BigUint, sub);
|
forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigUint, sub);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigUint, sub);
|
||||||
|
|
||||||
impl Sub<BigDigit> for BigUint {
|
impl Sub<u32> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(mut self, other: BigDigit) -> BigUint {
|
fn sub(mut self, other: u32) -> BigUint {
|
||||||
self -= other;
|
self -= other;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl SubAssign<BigDigit> for BigUint {
|
impl SubAssign<u32> for BigUint {
|
||||||
fn sub_assign(&mut self, other: BigDigit) {
|
fn sub_assign(&mut self, other: u32) {
|
||||||
sub2(&mut self.data[..], &[other]);
|
sub2(&mut self.data[..], &[other as BigDigit]);
|
||||||
self.normalize();
|
self.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub<BigUint> for BigDigit {
|
impl Sub<BigUint> for u32 {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(self, mut other: BigUint) -> BigUint {
|
fn sub(self, mut other: BigUint) -> BigUint {
|
||||||
if other.data.len() == 0 {
|
if other.data.len() == 0 {
|
||||||
other.data.push(self);
|
other.data.push(self as BigDigit);
|
||||||
} else {
|
} else {
|
||||||
sub2rev(&[self], &mut other.data[..]);
|
sub2rev(&[self as BigDigit], &mut other.data[..]);
|
||||||
}
|
}
|
||||||
other.normalized()
|
other.normalized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub<DoubleBigDigit> for BigUint {
|
impl Sub<u64> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sub(mut self, other: DoubleBigDigit) -> BigUint {
|
fn sub(mut self, other: u64) -> BigUint {
|
||||||
self -= other;
|
self -= other;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl SubAssign<DoubleBigDigit> for BigUint {
|
|
||||||
fn sub_assign(&mut self, other: DoubleBigDigit) {
|
impl SubAssign<u64> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, other: u64) {
|
||||||
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
||||||
sub2(&mut self.data[..], &[lo, hi]);
|
sub2(&mut self.data[..], &[lo, hi]);
|
||||||
self.normalize();
|
self.normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub<BigUint> for DoubleBigDigit {
|
impl Sub<BigUint> for u64 {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -678,6 +724,41 @@ impl Sub<BigUint> for DoubleBigDigit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Sub<u128> for BigUint {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(mut self, other: u128) -> BigUint {
|
||||||
|
self -= other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl SubAssign<u128> for BigUint {
|
||||||
|
fn sub_assign(&mut self, other: u128) {
|
||||||
|
let (a, b, c, d) = u32_from_u128(other);
|
||||||
|
sub2(&mut self.data[..], &[d, c, b, a]);
|
||||||
|
self.normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Sub<BigUint> for u128 {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, mut other: BigUint) -> BigUint {
|
||||||
|
while other.data.len() < 4 {
|
||||||
|
other.data.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (a, b, c, d) = u32_from_u128(self);
|
||||||
|
sub2rev(&[d, c, b, a], &mut other.data[..]);
|
||||||
|
other.normalized()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul);
|
forward_all_binop_to_ref_ref!(impl Mul for BigUint, mul);
|
||||||
forward_val_assign!(impl MulAssign for BigUint, mul_assign);
|
forward_val_assign!(impl MulAssign for BigUint, mul_assign);
|
||||||
|
|
||||||
@ -698,25 +779,27 @@ impl<'a> MulAssign<&'a BigUint> for BigUint {
|
|||||||
|
|
||||||
promote_unsigned_scalars!(impl Mul for BigUint, mul);
|
promote_unsigned_scalars!(impl Mul for BigUint, mul);
|
||||||
promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign);
|
promote_unsigned_scalars_assign!(impl MulAssign for BigUint, mul_assign);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<BigDigit> for BigUint, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u32> for BigUint, mul);
|
||||||
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<DoubleBigDigit> for BigUint, mul);
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u64> for BigUint, mul);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u128> for BigUint, mul);
|
||||||
|
|
||||||
impl Mul<BigDigit> for BigUint {
|
impl Mul<u32> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(mut self, other: BigDigit) -> BigUint {
|
fn mul(mut self, other: u32) -> BigUint {
|
||||||
self *= other;
|
self *= other;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MulAssign<BigDigit> for BigUint {
|
impl MulAssign<u32> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_assign(&mut self, other: BigDigit) {
|
fn mul_assign(&mut self, other: u32) {
|
||||||
if other == 0 {
|
if other == 0 {
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
} else {
|
} else {
|
||||||
let carry = scalar_mul(&mut self.data[..], other);
|
let carry = scalar_mul(&mut self.data[..], other as BigDigit);
|
||||||
if carry != 0 {
|
if carry != 0 {
|
||||||
self.data.push(carry);
|
self.data.push(carry);
|
||||||
}
|
}
|
||||||
@ -724,21 +807,21 @@ impl MulAssign<BigDigit> for BigUint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<DoubleBigDigit> for BigUint {
|
impl Mul<u64> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul(mut self, other: DoubleBigDigit) -> BigUint {
|
fn mul(mut self, other: u64) -> BigUint {
|
||||||
self *= other;
|
self *= other;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MulAssign<DoubleBigDigit> for BigUint {
|
impl MulAssign<u64> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_assign(&mut self, other: DoubleBigDigit) {
|
fn mul_assign(&mut self, other: u64) {
|
||||||
if other == 0 {
|
if other == 0 {
|
||||||
self.data.clear();
|
self.data.clear();
|
||||||
} else if other <= BigDigit::max_value() as DoubleBigDigit {
|
} else if other <= BigDigit::max_value() as u64 {
|
||||||
*self *= other as BigDigit
|
*self *= other as BigDigit
|
||||||
} else {
|
} else {
|
||||||
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
let (hi, lo) = big_digit::from_doublebigdigit(other);
|
||||||
@ -747,6 +830,31 @@ impl MulAssign<DoubleBigDigit> for BigUint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Mul<u128> for BigUint {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(mut self, other: u128) -> BigUint {
|
||||||
|
self *= other;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl MulAssign<u128> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: u128) {
|
||||||
|
if other == 0 {
|
||||||
|
self.data.clear();
|
||||||
|
} else if other <= BigDigit::max_value() as u128 {
|
||||||
|
*self *= other as BigDigit
|
||||||
|
} else {
|
||||||
|
let (a, b, c, d) = u32_from_u128(other);
|
||||||
|
*self = mul3(&self.data[..], &[d, c, b, a])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Div for BigUint, div);
|
forward_all_binop_to_ref_ref!(impl Div for BigUint, div);
|
||||||
forward_val_assign!(impl DivAssign for BigUint, div_assign);
|
forward_val_assign!(impl DivAssign for BigUint, div_assign);
|
||||||
|
|
||||||
@ -768,55 +876,57 @@ impl<'a> DivAssign<&'a BigUint> for BigUint {
|
|||||||
|
|
||||||
promote_unsigned_scalars!(impl Div for BigUint, div);
|
promote_unsigned_scalars!(impl Div for BigUint, div);
|
||||||
promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
|
promote_unsigned_scalars_assign!(impl DivAssign for BigUint, div_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<BigDigit> for BigUint, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<u32> for BigUint, div);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Div<DoubleBigDigit> for BigUint, div);
|
forward_all_scalar_binop_to_val_val!(impl Div<u64> for BigUint, div);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Div<u128> for BigUint, div);
|
||||||
|
|
||||||
impl Div<BigDigit> for BigUint {
|
impl Div<u32> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self, other: BigDigit) -> BigUint {
|
fn div(self, other: u32) -> BigUint {
|
||||||
let (q, _) = div_rem_digit(self, other);
|
let (q, _) = div_rem_digit(self, other as BigDigit);
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl DivAssign<BigDigit> for BigUint {
|
impl DivAssign<u32> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div_assign(&mut self, other: BigDigit) {
|
fn div_assign(&mut self, other: u32) {
|
||||||
*self = &*self / other;
|
*self = &*self / other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<BigUint> for BigDigit {
|
impl Div<BigUint> for u32 {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self, other: BigUint) -> BigUint {
|
fn div(self, other: BigUint) -> BigUint {
|
||||||
match other.data.len() {
|
match other.data.len() {
|
||||||
0 => panic!(),
|
0 => panic!(),
|
||||||
1 => From::from(self / other.data[0]),
|
1 => From::from(self as BigDigit / other.data[0]),
|
||||||
_ => Zero::zero(),
|
_ => Zero::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<DoubleBigDigit> for BigUint {
|
impl Div<u64> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div(self, other: DoubleBigDigit) -> BigUint {
|
fn div(self, other: u64) -> BigUint {
|
||||||
let (q, _) = self.div_rem(&From::from(other));
|
let (q, _) = self.div_rem(&From::from(other));
|
||||||
q
|
q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl DivAssign<DoubleBigDigit> for BigUint {
|
impl DivAssign<u64> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn div_assign(&mut self, other: DoubleBigDigit) {
|
fn div_assign(&mut self, other: u64) {
|
||||||
*self = &*self / other;
|
*self = &*self / other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<BigUint> for DoubleBigDigit {
|
impl Div<BigUint> for u64 {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -830,6 +940,45 @@ impl Div<BigUint> for DoubleBigDigit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Div<u128> for BigUint {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: u128) -> BigUint {
|
||||||
|
let (q, _) = self.div_rem(&From::from(other));
|
||||||
|
q
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl DivAssign<u128> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, other: u128) {
|
||||||
|
*self = &*self / other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Div<BigUint> for u128 {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn div(self, other: BigUint) -> BigUint {
|
||||||
|
match other.data.len() {
|
||||||
|
0 => panic!(),
|
||||||
|
1 => From::from(self / other.data[0] as u128),
|
||||||
|
2 => From::from(
|
||||||
|
self / big_digit::to_doublebigdigit(other.data[1], other.data[0]) as u128,
|
||||||
|
),
|
||||||
|
3 => From::from(self / u32_to_u128(0, other.data[2], other.data[1], other.data[0])),
|
||||||
|
4 => From::from(
|
||||||
|
self / u32_to_u128(other.data[3], other.data[2], other.data[1], other.data[0]),
|
||||||
|
),
|
||||||
|
_ => Zero::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem);
|
forward_all_binop_to_ref_ref!(impl Rem for BigUint, rem);
|
||||||
forward_val_assign!(impl RemAssign for BigUint, rem_assign);
|
forward_val_assign!(impl RemAssign for BigUint, rem_assign);
|
||||||
|
|
||||||
@ -851,26 +1000,28 @@ impl<'a> RemAssign<&'a BigUint> for BigUint {
|
|||||||
|
|
||||||
promote_unsigned_scalars!(impl Rem for BigUint, rem);
|
promote_unsigned_scalars!(impl Rem for BigUint, rem);
|
||||||
promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
|
promote_unsigned_scalars_assign!(impl RemAssign for BigUint, rem_assign);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<BigDigit> for BigUint, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<u32> for BigUint, rem);
|
||||||
forward_all_scalar_binop_to_val_val!(impl Rem<DoubleBigDigit> for BigUint, rem);
|
forward_all_scalar_binop_to_val_val!(impl Rem<u64> for BigUint, rem);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
forward_all_scalar_binop_to_val_val!(impl Rem<u128> for BigUint, rem);
|
||||||
|
|
||||||
impl Rem<BigDigit> for BigUint {
|
impl Rem<u32> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem(self, other: BigDigit) -> BigUint {
|
fn rem(self, other: u32) -> BigUint {
|
||||||
let (_, r) = div_rem_digit(self, other);
|
let (_, r) = div_rem_digit(self, other as BigDigit);
|
||||||
From::from(r)
|
From::from(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl RemAssign<BigDigit> for BigUint {
|
impl RemAssign<u32> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem_assign(&mut self, other: BigDigit) {
|
fn rem_assign(&mut self, other: u32) {
|
||||||
*self = &*self % other;
|
*self = &*self % other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rem<BigUint> for BigDigit {
|
impl Rem<BigUint> for u32 {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -896,34 +1047,67 @@ macro_rules! impl_rem_assign_scalar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we can scalar %= BigUint for any scalar, including signed types
|
// we can scalar %= BigUint for any scalar, including signed types
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl_rem_assign_scalar!(u128, to_u128);
|
||||||
impl_rem_assign_scalar!(usize, to_usize);
|
impl_rem_assign_scalar!(usize, to_usize);
|
||||||
impl_rem_assign_scalar!(u64, to_u64);
|
impl_rem_assign_scalar!(u64, to_u64);
|
||||||
impl_rem_assign_scalar!(u32, to_u32);
|
impl_rem_assign_scalar!(u32, to_u32);
|
||||||
impl_rem_assign_scalar!(u16, to_u16);
|
impl_rem_assign_scalar!(u16, to_u16);
|
||||||
impl_rem_assign_scalar!(u8, to_u8);
|
impl_rem_assign_scalar!(u8, to_u8);
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl_rem_assign_scalar!(i128, to_i128);
|
||||||
impl_rem_assign_scalar!(isize, to_isize);
|
impl_rem_assign_scalar!(isize, to_isize);
|
||||||
impl_rem_assign_scalar!(i64, to_i64);
|
impl_rem_assign_scalar!(i64, to_i64);
|
||||||
impl_rem_assign_scalar!(i32, to_i32);
|
impl_rem_assign_scalar!(i32, to_i32);
|
||||||
impl_rem_assign_scalar!(i16, to_i16);
|
impl_rem_assign_scalar!(i16, to_i16);
|
||||||
impl_rem_assign_scalar!(i8, to_i8);
|
impl_rem_assign_scalar!(i8, to_i8);
|
||||||
|
|
||||||
impl Rem<DoubleBigDigit> for BigUint {
|
impl Rem<u64> for BigUint {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem(self, other: DoubleBigDigit) -> BigUint {
|
fn rem(self, other: u64) -> BigUint {
|
||||||
let (_, r) = self.div_rem(&From::from(other));
|
let (_, r) = self.div_rem(&From::from(other));
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl RemAssign<DoubleBigDigit> for BigUint {
|
impl RemAssign<u64> for BigUint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rem_assign(&mut self, other: DoubleBigDigit) {
|
fn rem_assign(&mut self, other: u64) {
|
||||||
*self = &*self % other;
|
*self = &*self % other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rem<BigUint> for DoubleBigDigit {
|
impl Rem<BigUint> for u64 {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rem(mut self, other: BigUint) -> BigUint {
|
||||||
|
self %= other;
|
||||||
|
From::from(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Rem<u128> for BigUint {
|
||||||
|
type Output = BigUint;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rem(self, other: u128) -> BigUint {
|
||||||
|
let (_, r) = self.div_rem(&From::from(other));
|
||||||
|
r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl RemAssign<u128> for BigUint {
|
||||||
|
#[inline]
|
||||||
|
fn rem_assign(&mut self, other: u128) {
|
||||||
|
*self = &*self % other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
impl Rem<BigUint> for u128 {
|
||||||
type Output = BigUint;
|
type Output = BigUint;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1247,10 +1431,10 @@ impl ToPrimitive for BigUint {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret += (*i as u128) << bits;
|
ret |= (*i as u128) << bits;
|
||||||
bits += big_digit::BITS;
|
bits += big_digit::BITS;
|
||||||
}
|
}
|
||||||
|
println!("{:?} -> {}", self, ret);
|
||||||
Some(ret)
|
Some(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1975,6 +2159,25 @@ impl IntDigits for BigUint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Combine four `u32`s into a single `u128`.
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
#[inline]
|
||||||
|
fn u32_to_u128(a: u32, b: u32, c: u32, d: u32) -> u128 {
|
||||||
|
u128::from(d) | (u128::from(c) << 32) | (u128::from(b) << 64) | (u128::from(a) << 96)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Split a single `u128` into four `u32`.
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
#[inline]
|
||||||
|
fn u32_from_u128(n: u128) -> (u32, u32, u32, u32) {
|
||||||
|
(
|
||||||
|
(n >> 96) as u32,
|
||||||
|
(n >> 64) as u32,
|
||||||
|
(n >> 32) as u32,
|
||||||
|
n as u32,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl serde::Serialize for BigUint {
|
impl serde::Serialize for BigUint {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
@ -2596,3 +2799,55 @@ fn test_assign_from_slice() {
|
|||||||
check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
|
check(&[0, 0, 1, 2, 0, 0], &[0, 0, 1, 2]);
|
||||||
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
|
check(&[-1i32 as BigDigit], &[-1i32 as BigDigit]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
#[test]
|
||||||
|
fn test_u32_u128() {
|
||||||
|
assert_eq!(u32_from_u128(0u128), (0, 0, 0, 0));
|
||||||
|
assert_eq!(
|
||||||
|
u32_from_u128(u128::max_value()),
|
||||||
|
(
|
||||||
|
u32::max_value(),
|
||||||
|
u32::max_value(),
|
||||||
|
u32::max_value(),
|
||||||
|
u32::max_value()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
u32_from_u128(u32::max_value() as u128),
|
||||||
|
(0, 0, 0, u32::max_value())
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
u32_from_u128(u64::max_value() as u128),
|
||||||
|
(0, 0, u32::max_value(), u32::max_value())
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
u32_from_u128((u64::max_value() as u128) + u32::max_value() as u128),
|
||||||
|
(0, 1, 0, u32::max_value() - 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(u32_from_u128(36_893_488_151_714_070_528), (0, 2, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
#[test]
|
||||||
|
fn test_u128_u32_roundtrip() {
|
||||||
|
// roundtrips
|
||||||
|
let values = vec![
|
||||||
|
0u128,
|
||||||
|
1u128,
|
||||||
|
u64::max_value() as u128 * 3,
|
||||||
|
u32::max_value() as u128,
|
||||||
|
u64::max_value() as u128,
|
||||||
|
(u64::max_value() as u128) + u32::max_value() as u128,
|
||||||
|
u128::max_value(),
|
||||||
|
];
|
||||||
|
|
||||||
|
for val in &values {
|
||||||
|
let (a, b, c, d) = u32_from_u128(*val);
|
||||||
|
assert_eq!(u32_to_u128(a, b, c, d), *val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ pub const SUM_TRIPLES: &'static [(&'static [u32], &'static [u32], &'static [u32]
|
|||||||
(&[N1, N1], &[N1, N1], &[N2, N1, 1]),
|
(&[N1, N1], &[N1, N1], &[N2, N1, 1]),
|
||||||
(&[1, 1, 1], &[N1, N1], &[0, 1, 2]),
|
(&[1, 1, 1], &[N1, N1], &[0, 1, 2]),
|
||||||
(&[2, 2, 1], &[N1, N2], &[1, 1, 2]),
|
(&[2, 2, 1], &[N1, N2], &[1, 1, 2]),
|
||||||
|
(&[1, 2, 2, 1], &[N1, N2], &[0, 1, 3, 1]),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const M: u32 = ::std::u32::MAX;
|
pub const M: u32 = ::std::u32::MAX;
|
||||||
|
@ -35,6 +35,7 @@ macro_rules! assert_scalar_op {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(has_i128))]
|
||||||
macro_rules! assert_unsigned_scalar_op {
|
macro_rules! assert_unsigned_scalar_op {
|
||||||
($left:ident $op:tt $right:ident == $expected:expr) => {
|
($left:ident $op:tt $right:ident == $expected:expr) => {
|
||||||
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize)
|
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize)
|
||||||
@ -42,6 +43,15 @@ macro_rules! assert_unsigned_scalar_op {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
macro_rules! assert_unsigned_scalar_op {
|
||||||
|
($left:ident $op:tt $right:ident == $expected:expr) => {
|
||||||
|
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128)
|
||||||
|
$left $op $right == $expected);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(has_i128))]
|
||||||
macro_rules! assert_signed_scalar_op {
|
macro_rules! assert_signed_scalar_op {
|
||||||
($left:ident $op:tt $right:ident == $expected:expr) => {
|
($left:ident $op:tt $right:ident == $expected:expr) => {
|
||||||
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize,
|
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize,
|
||||||
@ -49,3 +59,12 @@ macro_rules! assert_signed_scalar_op {
|
|||||||
$left $op $right == $expected);
|
$left $op $right == $expected);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(has_i128)]
|
||||||
|
macro_rules! assert_signed_scalar_op {
|
||||||
|
($left:ident $op:tt $right:ident == $expected:expr) => {
|
||||||
|
assert_scalar_op!((to_u8, to_u16, to_u32, to_u64, to_usize, to_u128,
|
||||||
|
to_i8, to_i16, to_i32, to_i64, to_isize, to_i128)
|
||||||
|
$left $op $right == $expected);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user