1 use super::CheckedUnsignedAbs::{Negative, Positive}; 2 use super::Sign::{self, Minus, NoSign, Plus}; 3 use super::{BigInt, UnsignedAbs}; 4 5 use crate::{IsizePromotion, UsizePromotion}; 6 7 use core::iter::Product; 8 use core::ops::{Mul, MulAssign}; 9 use num_traits::{CheckedMul, One, Zero}; 10 11 impl Mul<Sign> for Sign { 12 type Output = Sign; 13 14 #[inline] mul(self, other: Sign) -> Sign15 fn mul(self, other: Sign) -> Sign { 16 match (self, other) { 17 (NoSign, _) | (_, NoSign) => NoSign, 18 (Plus, Plus) | (Minus, Minus) => Plus, 19 (Plus, Minus) | (Minus, Plus) => Minus, 20 } 21 } 22 } 23 24 macro_rules! impl_mul { 25 ($(impl Mul<$Other:ty> for $Self:ty;)*) => {$( 26 impl Mul<$Other> for $Self { 27 type Output = BigInt; 28 29 #[inline] 30 fn mul(self, other: $Other) -> BigInt { 31 // automatically match value/ref 32 let BigInt { data: x, .. } = self; 33 let BigInt { data: y, .. } = other; 34 BigInt::from_biguint(self.sign * other.sign, x * y) 35 } 36 } 37 )*} 38 } 39 impl_mul! { 40 impl Mul<BigInt> for BigInt; 41 impl Mul<BigInt> for &BigInt; 42 impl Mul<&BigInt> for BigInt; 43 impl Mul<&BigInt> for &BigInt; 44 } 45 46 macro_rules! impl_mul_assign { 47 ($(impl MulAssign<$Other:ty> for BigInt;)*) => {$( 48 impl MulAssign<$Other> for BigInt { 49 #[inline] 50 fn mul_assign(&mut self, other: $Other) { 51 // automatically match value/ref 52 let BigInt { data: y, .. } = other; 53 self.data *= y; 54 if self.data.is_zero() { 55 self.sign = NoSign; 56 } else { 57 self.sign = self.sign * other.sign; 58 } 59 } 60 } 61 )*} 62 } 63 impl_mul_assign! { 64 impl MulAssign<BigInt> for BigInt; 65 impl MulAssign<&BigInt> for BigInt; 66 } 67 68 promote_all_scalars!(impl Mul for BigInt, mul); 69 promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign); 70 forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u32> for BigInt, mul); 71 forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u64> for BigInt, mul); 72 forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u128> for BigInt, mul); 73 74 impl Mul<u32> for BigInt { 75 type Output = BigInt; 76 77 #[inline] mul(self, other: u32) -> BigInt78 fn mul(self, other: u32) -> BigInt { 79 BigInt::from_biguint(self.sign, self.data * other) 80 } 81 } 82 83 impl MulAssign<u32> for BigInt { 84 #[inline] mul_assign(&mut self, other: u32)85 fn mul_assign(&mut self, other: u32) { 86 self.data *= other; 87 if self.data.is_zero() { 88 self.sign = NoSign; 89 } 90 } 91 } 92 93 impl Mul<u64> for BigInt { 94 type Output = BigInt; 95 96 #[inline] mul(self, other: u64) -> BigInt97 fn mul(self, other: u64) -> BigInt { 98 BigInt::from_biguint(self.sign, self.data * other) 99 } 100 } 101 102 impl MulAssign<u64> for BigInt { 103 #[inline] mul_assign(&mut self, other: u64)104 fn mul_assign(&mut self, other: u64) { 105 self.data *= other; 106 if self.data.is_zero() { 107 self.sign = NoSign; 108 } 109 } 110 } 111 112 impl Mul<u128> for BigInt { 113 type Output = BigInt; 114 115 #[inline] mul(self, other: u128) -> BigInt116 fn mul(self, other: u128) -> BigInt { 117 BigInt::from_biguint(self.sign, self.data * other) 118 } 119 } 120 121 impl MulAssign<u128> for BigInt { 122 #[inline] mul_assign(&mut self, other: u128)123 fn mul_assign(&mut self, other: u128) { 124 self.data *= other; 125 if self.data.is_zero() { 126 self.sign = NoSign; 127 } 128 } 129 } 130 131 forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i32> for BigInt, mul); 132 forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i64> for BigInt, mul); 133 forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i128> for BigInt, mul); 134 135 impl Mul<i32> for BigInt { 136 type Output = BigInt; 137 138 #[inline] mul(self, other: i32) -> BigInt139 fn mul(self, other: i32) -> BigInt { 140 match other.checked_uabs() { 141 Positive(u) => self * u, 142 Negative(u) => -self * u, 143 } 144 } 145 } 146 147 impl MulAssign<i32> for BigInt { 148 #[inline] mul_assign(&mut self, other: i32)149 fn mul_assign(&mut self, other: i32) { 150 match other.checked_uabs() { 151 Positive(u) => *self *= u, 152 Negative(u) => { 153 self.sign = -self.sign; 154 self.data *= u; 155 } 156 } 157 } 158 } 159 160 impl Mul<i64> for BigInt { 161 type Output = BigInt; 162 163 #[inline] mul(self, other: i64) -> BigInt164 fn mul(self, other: i64) -> BigInt { 165 match other.checked_uabs() { 166 Positive(u) => self * u, 167 Negative(u) => -self * u, 168 } 169 } 170 } 171 172 impl MulAssign<i64> for BigInt { 173 #[inline] mul_assign(&mut self, other: i64)174 fn mul_assign(&mut self, other: i64) { 175 match other.checked_uabs() { 176 Positive(u) => *self *= u, 177 Negative(u) => { 178 self.sign = -self.sign; 179 self.data *= u; 180 } 181 } 182 } 183 } 184 185 impl Mul<i128> for BigInt { 186 type Output = BigInt; 187 188 #[inline] mul(self, other: i128) -> BigInt189 fn mul(self, other: i128) -> BigInt { 190 match other.checked_uabs() { 191 Positive(u) => self * u, 192 Negative(u) => -self * u, 193 } 194 } 195 } 196 197 impl MulAssign<i128> for BigInt { 198 #[inline] mul_assign(&mut self, other: i128)199 fn mul_assign(&mut self, other: i128) { 200 match other.checked_uabs() { 201 Positive(u) => *self *= u, 202 Negative(u) => { 203 self.sign = -self.sign; 204 self.data *= u; 205 } 206 } 207 } 208 } 209 210 impl CheckedMul for BigInt { 211 #[inline] checked_mul(&self, v: &BigInt) -> Option<BigInt>212 fn checked_mul(&self, v: &BigInt) -> Option<BigInt> { 213 Some(self.mul(v)) 214 } 215 } 216 217 impl_product_iter_type!(BigInt); 218