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::mem; use core::ops::{Sub, SubAssign}; use num_traits::{CheckedSub, Zero}; // 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 // val/ref combination, deferring that decision to BigUint's own forwarding. macro_rules! bigint_sub { ($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, // opposite signs => keep the sign of the left with the sum of magnitudes (Plus, Minus) | (Minus, Plus) => BigInt::from_biguint($a.sign, $a_data + $b_data), // same sign => keep or toggle the sign of the left with the difference of magnitudes (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(), }, } }; } impl Sub<&BigInt> for &BigInt { type Output = BigInt; #[inline] fn sub(self, other: &BigInt) -> BigInt { bigint_sub!( self, self.clone(), &self.data, other, other.clone(), &other.data ) } } impl Sub for &BigInt { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { bigint_sub!(self, self.clone(), &self.data, other, other, other.data) } } impl Sub<&BigInt> for BigInt { type Output = BigInt; #[inline] fn sub(self, other: &BigInt) -> BigInt { bigint_sub!(self, self, self.data, other, other.clone(), &other.data) } } impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { bigint_sub!(self, self, self.data, other, other, other.data) } } impl SubAssign<&BigInt> for BigInt { #[inline] fn sub_assign(&mut self, other: &BigInt) { let n = mem::replace(self, BigInt::zero()); *self = n - other; } } forward_val_assign!(impl SubAssign for BigInt, sub_assign); promote_all_scalars!(impl Sub for BigInt, sub); promote_all_scalars_assign!(impl SubAssign for BigInt, sub_assign); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: u32) -> BigInt { match self.sign { NoSign => -BigInt::from(other), Minus => -BigInt::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), Greater => BigInt::from(self.data - other), Less => -BigInt::from(other - self.data), }, } } } impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u32) { let n = mem::replace(self, BigInt::zero()); *self = n - other; } } impl Sub for u32 { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { -(other - self) } } impl Sub for u64 { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { -(other - self) } } impl Sub for u128 { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { -(other - self) } } impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: u64) -> BigInt { match self.sign { NoSign => -BigInt::from(other), Minus => -BigInt::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), Greater => BigInt::from(self.data - other), Less => -BigInt::from(other - self.data), }, } } } impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: u64) { let n = mem::replace(self, BigInt::zero()); *self = n - other; } } impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: u128) -> BigInt { match self.sign { NoSign => -BigInt::from(other), Minus => -BigInt::from(self.data + other), Plus => match self.data.cmp(&From::from(other)) { Equal => Zero::zero(), Greater => BigInt::from(self.data - other), Less => -BigInt::from(other - self.data), }, } } } impl SubAssign 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 for BigInt, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); forward_all_scalar_binop_to_val_val!(impl Sub for BigInt, sub); impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: i32) -> BigInt { match other.checked_uabs() { Positive(u) => self - u, Negative(u) => self + u, } } } impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: i32) { match other.checked_uabs() { Positive(u) => *self -= u, Negative(u) => *self += u, } } } impl Sub for i32 { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u - other, Negative(u) => -other - u, } } } impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: i64) -> BigInt { match other.checked_uabs() { Positive(u) => self - u, Negative(u) => self + u, } } } impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: i64) { match other.checked_uabs() { Positive(u) => *self -= u, Negative(u) => *self += u, } } } impl Sub for i64 { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u - other, Negative(u) => -other - u, } } } impl Sub for BigInt { type Output = BigInt; #[inline] fn sub(self, other: i128) -> BigInt { match other.checked_uabs() { Positive(u) => self - u, Negative(u) => self + u, } } } impl SubAssign for BigInt { #[inline] fn sub_assign(&mut self, other: i128) { match other.checked_uabs() { Positive(u) => *self -= u, Negative(u) => *self += u, } } } impl Sub for i128 { type Output = BigInt; #[inline] fn sub(self, other: BigInt) -> BigInt { match self.checked_uabs() { Positive(u) => u - other, Negative(u) => -other - u, } } } impl CheckedSub for BigInt { #[inline] fn checked_sub(&self, v: &BigInt) -> Option { Some(self.sub(v)) } }