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                // 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}
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                // 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}
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);