num_bigint/bigint/
multiplication.rs
1use super::CheckedUnsignedAbs::{Negative, Positive};
2use super::Sign::{self, Minus, NoSign, Plus};
3use super::{BigInt, UnsignedAbs};
4
5use crate::{IsizePromotion, UsizePromotion};
6
7use core::iter::Product;
8use core::ops::{Mul, MulAssign};
9use num_traits::{CheckedMul, One, Zero};
10
11impl Mul<Sign> for Sign {
12 type Output = Sign;
13
14 #[inline]
15 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
24macro_rules! impl_mul {
25 ($(impl<$($a:lifetime),*> Mul<$Other:ty> for $Self:ty;)*) => {$(
26 impl<$($a),*> Mul<$Other> for $Self {
27 type Output = BigInt;
28
29 #[inline]
30 fn mul(self, other: $Other) -> BigInt {
31 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}
39impl_mul! {
40 impl<> Mul<BigInt> for BigInt;
41 impl<'b> Mul<&'b BigInt> for BigInt;
42 impl<'a> Mul<BigInt> for &'a BigInt;
43 impl<'a, 'b> Mul<&'b BigInt> for &'a BigInt;
44}
45
46macro_rules! impl_mul_assign {
47 ($(impl<$($a:lifetime),*> MulAssign<$Other:ty> for BigInt;)*) => {$(
48 impl<$($a),*> MulAssign<$Other> for BigInt {
49 #[inline]
50 fn mul_assign(&mut self, other: $Other) {
51 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}
63impl_mul_assign! {
64 impl<> MulAssign<BigInt> for BigInt;
65 impl<'a> MulAssign<&'a BigInt> for BigInt;
66}
67
68promote_all_scalars!(impl Mul for BigInt, mul);
69promote_all_scalars_assign!(impl MulAssign for BigInt, mul_assign);
70forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u32> for BigInt, mul);
71forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u64> for BigInt, mul);
72forward_all_scalar_binop_to_val_val_commutative!(impl Mul<u128> for BigInt, mul);
73
74impl Mul<u32> for BigInt {
75 type Output = BigInt;
76
77 #[inline]
78 fn mul(self, other: u32) -> BigInt {
79 BigInt::from_biguint(self.sign, self.data * other)
80 }
81}
82
83impl MulAssign<u32> for BigInt {
84 #[inline]
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
93impl Mul<u64> for BigInt {
94 type Output = BigInt;
95
96 #[inline]
97 fn mul(self, other: u64) -> BigInt {
98 BigInt::from_biguint(self.sign, self.data * other)
99 }
100}
101
102impl MulAssign<u64> for BigInt {
103 #[inline]
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
112impl Mul<u128> for BigInt {
113 type Output = BigInt;
114
115 #[inline]
116 fn mul(self, other: u128) -> BigInt {
117 BigInt::from_biguint(self.sign, self.data * other)
118 }
119}
120
121impl MulAssign<u128> for BigInt {
122 #[inline]
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
131forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i32> for BigInt, mul);
132forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i64> for BigInt, mul);
133forward_all_scalar_binop_to_val_val_commutative!(impl Mul<i128> for BigInt, mul);
134
135impl Mul<i32> for BigInt {
136 type Output = BigInt;
137
138 #[inline]
139 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
147impl MulAssign<i32> for BigInt {
148 #[inline]
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
160impl Mul<i64> for BigInt {
161 type Output = BigInt;
162
163 #[inline]
164 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
172impl MulAssign<i64> for BigInt {
173 #[inline]
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
185impl Mul<i128> for BigInt {
186 type Output = BigInt;
187
188 #[inline]
189 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
197impl MulAssign<i128> for BigInt {
198 #[inline]
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
210impl CheckedMul for BigInt {
211 #[inline]
212 fn checked_mul(&self, v: &BigInt) -> Option<BigInt> {
213 Some(self.mul(v))
214 }
215}
216
217impl_product_iter_type!(BigInt);