1 use super::CheckedUnsignedAbs::{Negative, Positive}; 2 use super::Sign::{Minus, NoSign, Plus}; 3 use super::{BigInt, UnsignedAbs}; 4 5 use crate::{IsizePromotion, UsizePromotion}; 6 7 use core::cmp::Ordering::{Equal, Greater, Less}; 8 use core::iter::Sum; 9 use core::mem; 10 use core::ops::{Add, AddAssign}; 11 use num_traits::{CheckedAdd, Zero}; 12 13 // We want to forward to BigUint::add, but it's not clear how that will go until 14 // we compare both sign and magnitude. So we duplicate this body for every 15 // val/ref combination, deferring that decision to BigUint's own forwarding. 16 macro_rules! bigint_add { 17 ($a:expr, $a_owned:expr, $a_data:expr, $b:expr, $b_owned:expr, $b_data:expr) => { 18 match ($a.sign, $b.sign) { 19 (_, NoSign) => $a_owned, 20 (NoSign, _) => $b_owned, 21 // same sign => keep the sign with the sum of magnitudes 22 (Plus, Plus) | (Minus, Minus) => BigInt::from_biguint($a.sign, $a_data + $b_data), 23 // opposite signs => keep the sign of the larger with the difference of magnitudes 24 (Plus, Minus) | (Minus, Plus) => match $a.data.cmp(&$b.data) { 25 Less => BigInt::from_biguint($b.sign, $b_data - $a_data), 26 Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), 27 Equal => Zero::zero(), 28 }, 29 } 30 }; 31 } 32 33 impl Add<&BigInt> for &BigInt { 34 type Output = BigInt; 35 36 #[inline] add(self, other: &BigInt) -> BigInt37 fn add(self, other: &BigInt) -> BigInt { 38 bigint_add!( 39 self, 40 self.clone(), 41 &self.data, 42 other, 43 other.clone(), 44 &other.data 45 ) 46 } 47 } 48 49 impl Add<BigInt> for &BigInt { 50 type Output = BigInt; 51 52 #[inline] add(self, other: BigInt) -> BigInt53 fn add(self, other: BigInt) -> BigInt { 54 bigint_add!(self, self.clone(), &self.data, other, other, other.data) 55 } 56 } 57 58 impl Add<&BigInt> for BigInt { 59 type Output = BigInt; 60 61 #[inline] add(self, other: &BigInt) -> BigInt62 fn add(self, other: &BigInt) -> BigInt { 63 bigint_add!(self, self, self.data, other, other.clone(), &other.data) 64 } 65 } 66 67 impl Add<BigInt> for BigInt { 68 type Output = BigInt; 69 70 #[inline] add(self, other: BigInt) -> BigInt71 fn add(self, other: BigInt) -> BigInt { 72 bigint_add!(self, self, self.data, other, other, other.data) 73 } 74 } 75 76 impl AddAssign<&BigInt> for BigInt { 77 #[inline] add_assign(&mut self, other: &BigInt)78 fn add_assign(&mut self, other: &BigInt) { 79 let n = mem::replace(self, BigInt::zero()); 80 *self = n + other; 81 } 82 } 83 forward_val_assign!(impl AddAssign for BigInt, add_assign); 84 85 promote_all_scalars!(impl Add for BigInt, add); 86 promote_all_scalars_assign!(impl AddAssign for BigInt, add_assign); 87 forward_all_scalar_binop_to_val_val_commutative!(impl Add<u32> for BigInt, add); 88 forward_all_scalar_binop_to_val_val_commutative!(impl Add<u64> for BigInt, add); 89 forward_all_scalar_binop_to_val_val_commutative!(impl Add<u128> for BigInt, add); 90 91 impl Add<u32> for BigInt { 92 type Output = BigInt; 93 94 #[inline] add(self, other: u32) -> BigInt95 fn add(self, other: u32) -> BigInt { 96 match self.sign { 97 NoSign => From::from(other), 98 Plus => BigInt::from(self.data + other), 99 Minus => match self.data.cmp(&From::from(other)) { 100 Equal => Zero::zero(), 101 Less => BigInt::from(other - self.data), 102 Greater => -BigInt::from(self.data - other), 103 }, 104 } 105 } 106 } 107 108 impl AddAssign<u32> for BigInt { 109 #[inline] add_assign(&mut self, other: u32)110 fn add_assign(&mut self, other: u32) { 111 let n = mem::replace(self, BigInt::zero()); 112 *self = n + other; 113 } 114 } 115 116 impl Add<u64> for BigInt { 117 type Output = BigInt; 118 119 #[inline] add(self, other: u64) -> BigInt120 fn add(self, other: u64) -> BigInt { 121 match self.sign { 122 NoSign => From::from(other), 123 Plus => BigInt::from(self.data + other), 124 Minus => match self.data.cmp(&From::from(other)) { 125 Equal => Zero::zero(), 126 Less => BigInt::from(other - self.data), 127 Greater => -BigInt::from(self.data - other), 128 }, 129 } 130 } 131 } 132 133 impl AddAssign<u64> for BigInt { 134 #[inline] add_assign(&mut self, other: u64)135 fn add_assign(&mut self, other: u64) { 136 let n = mem::replace(self, BigInt::zero()); 137 *self = n + other; 138 } 139 } 140 141 impl Add<u128> for BigInt { 142 type Output = BigInt; 143 144 #[inline] add(self, other: u128) -> BigInt145 fn add(self, other: u128) -> BigInt { 146 match self.sign { 147 NoSign => BigInt::from(other), 148 Plus => BigInt::from(self.data + other), 149 Minus => match self.data.cmp(&From::from(other)) { 150 Equal => BigInt::zero(), 151 Less => BigInt::from(other - self.data), 152 Greater => -BigInt::from(self.data - other), 153 }, 154 } 155 } 156 } 157 impl AddAssign<u128> for BigInt { 158 #[inline] add_assign(&mut self, other: u128)159 fn add_assign(&mut self, other: u128) { 160 let n = mem::replace(self, BigInt::zero()); 161 *self = n + other; 162 } 163 } 164 165 forward_all_scalar_binop_to_val_val_commutative!(impl Add<i32> for BigInt, add); 166 forward_all_scalar_binop_to_val_val_commutative!(impl Add<i64> for BigInt, add); 167 forward_all_scalar_binop_to_val_val_commutative!(impl Add<i128> for BigInt, add); 168 169 impl Add<i32> for BigInt { 170 type Output = BigInt; 171 172 #[inline] add(self, other: i32) -> BigInt173 fn add(self, other: i32) -> BigInt { 174 match other.checked_uabs() { 175 Positive(u) => self + u, 176 Negative(u) => self - u, 177 } 178 } 179 } 180 impl AddAssign<i32> for BigInt { 181 #[inline] add_assign(&mut self, other: i32)182 fn add_assign(&mut self, other: i32) { 183 match other.checked_uabs() { 184 Positive(u) => *self += u, 185 Negative(u) => *self -= u, 186 } 187 } 188 } 189 190 impl Add<i64> for BigInt { 191 type Output = BigInt; 192 193 #[inline] add(self, other: i64) -> BigInt194 fn add(self, other: i64) -> BigInt { 195 match other.checked_uabs() { 196 Positive(u) => self + u, 197 Negative(u) => self - u, 198 } 199 } 200 } 201 impl AddAssign<i64> for BigInt { 202 #[inline] add_assign(&mut self, other: i64)203 fn add_assign(&mut self, other: i64) { 204 match other.checked_uabs() { 205 Positive(u) => *self += u, 206 Negative(u) => *self -= u, 207 } 208 } 209 } 210 211 impl Add<i128> for BigInt { 212 type Output = BigInt; 213 214 #[inline] add(self, other: i128) -> BigInt215 fn add(self, other: i128) -> BigInt { 216 match other.checked_uabs() { 217 Positive(u) => self + u, 218 Negative(u) => self - u, 219 } 220 } 221 } 222 impl AddAssign<i128> for BigInt { 223 #[inline] add_assign(&mut self, other: i128)224 fn add_assign(&mut self, other: i128) { 225 match other.checked_uabs() { 226 Positive(u) => *self += u, 227 Negative(u) => *self -= u, 228 } 229 } 230 } 231 232 impl CheckedAdd for BigInt { 233 #[inline] checked_add(&self, v: &BigInt) -> Option<BigInt>234 fn checked_add(&self, v: &BigInt) -> Option<BigInt> { 235 Some(self.add(v)) 236 } 237 } 238 239 impl_sum_iter_type!(BigInt); 240