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