crypto_bigint/int/
mul_unsigned.rs1use crate::{CheckedMul, Choice, Concat, CtOption, Int, Uint};
2use core::ops::Mul;
3
4impl<const LIMBS: usize> Int<LIMBS> {
5 #[deprecated(since = "0.7.0", note = "please use `widening_mul_unsigned` instead")]
12 #[must_use]
13 pub const fn split_mul_unsigned<const RHS_LIMBS: usize>(
14 &self,
15 rhs: &Uint<RHS_LIMBS>,
16 ) -> (Uint<{ LIMBS }>, Uint<{ RHS_LIMBS }>, Choice) {
17 self.widening_mul_unsigned(rhs)
18 }
19
20 #[must_use]
27 pub const fn widening_mul_unsigned<const RHS_LIMBS: usize>(
28 &self,
29 rhs: &Uint<RHS_LIMBS>,
30 ) -> (Uint<{ LIMBS }>, Uint<{ RHS_LIMBS }>, Choice) {
31 let (lhs_abs, lhs_sgn) = self.abs_sign();
33
34 let (lo, hi) = lhs_abs.widening_mul(rhs);
36
37 (lo, hi, lhs_sgn)
39 }
40
41 #[deprecated(
48 since = "0.7.0",
49 note = "please use `Uint::widening_mul_signed` instead"
50 )]
51 #[must_use]
52 pub const fn split_mul_unsigned_right<const RHS_LIMBS: usize>(
53 &self,
54 rhs: &Uint<RHS_LIMBS>,
55 ) -> (Uint<{ RHS_LIMBS }>, Uint<{ LIMBS }>, Choice) {
56 rhs.widening_mul_signed(self)
57 }
58
59 #[deprecated(
66 since = "0.7.0",
67 note = "please use `Uint::widening_mul_signed` instead"
68 )]
69 #[must_use]
70 pub const fn widening_mul_unsigned_right<const RHS_LIMBS: usize>(
71 &self,
72 rhs: &Uint<RHS_LIMBS>,
73 ) -> (Uint<{ RHS_LIMBS }>, Uint<{ LIMBS }>, Choice) {
74 rhs.widening_mul_signed(self)
75 }
76
77 #[must_use]
79 pub const fn concatenating_mul_unsigned<const RHS_LIMBS: usize, const WIDE_LIMBS: usize>(
80 &self,
81 rhs: &Uint<RHS_LIMBS>,
82 ) -> Int<WIDE_LIMBS>
83 where
84 Uint<LIMBS>: Concat<RHS_LIMBS, Output = Uint<WIDE_LIMBS>>,
85 {
86 let (lhs_abs, lhs_sign) = self.abs_sign();
87 let product_abs = lhs_abs.concatenating_mul(rhs);
88
89 *product_abs.wrapping_neg_if(lhs_sign).as_int()
91 }
92
93 #[deprecated(since = "0.7.0", note = "please use `Uint::checked_mul(_int)` instead")]
96 #[must_use]
97 pub fn checked_mul_unsigned_right<const RHS_LIMBS: usize>(
98 &self,
99 rhs: &Uint<RHS_LIMBS>,
100 ) -> CtOption<Int<RHS_LIMBS>> {
101 rhs.checked_mul_signed(self)
102 }
103
104 #[must_use]
106 pub fn checked_mul_unsigned<const RHS_LIMBS: usize>(
107 &self,
108 rhs: &Uint<RHS_LIMBS>,
109 ) -> CtOption<Int<LIMBS>> {
110 let (abs_lhs, lhs_sgn) = self.abs_sign();
111 Self::new_from_abs_opt_sign(abs_lhs.checked_mul(rhs), lhs_sgn)
112 }
113}
114
115impl<const LIMBS: usize, const RHS_LIMBS: usize> CheckedMul<Uint<RHS_LIMBS>> for Int<LIMBS> {
116 #[inline]
117 fn checked_mul(&self, rhs: &Uint<RHS_LIMBS>) -> CtOption<Self> {
118 self.checked_mul_unsigned(rhs)
119 }
120}
121
122impl<const LIMBS: usize, const RHS_LIMBS: usize> Mul<Uint<RHS_LIMBS>> for Int<LIMBS> {
123 type Output = Int<LIMBS>;
124
125 fn mul(self, rhs: Uint<RHS_LIMBS>) -> Self {
126 self.mul(&rhs)
127 }
128}
129
130impl<const LIMBS: usize, const RHS_LIMBS: usize> Mul<&Uint<RHS_LIMBS>> for Int<LIMBS> {
131 type Output = Int<LIMBS>;
132
133 fn mul(self, rhs: &Uint<RHS_LIMBS>) -> Self {
134 (&self).mul(rhs)
135 }
136}
137
138impl<const LIMBS: usize, const RHS_LIMBS: usize> Mul<Uint<RHS_LIMBS>> for &Int<LIMBS> {
139 type Output = Int<LIMBS>;
140
141 fn mul(self, rhs: Uint<RHS_LIMBS>) -> Self::Output {
142 self.mul(&rhs)
143 }
144}
145
146impl<const LIMBS: usize, const RHS_LIMBS: usize> Mul<&Uint<RHS_LIMBS>> for &Int<LIMBS> {
147 type Output = Int<LIMBS>;
148
149 fn mul(self, rhs: &Uint<RHS_LIMBS>) -> Self::Output {
150 self.checked_mul_unsigned(rhs)
151 .expect("attempted to multiply with overflow")
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use crate::{I128, I256, U128, U256};
158
159 #[test]
160 fn test_checked_mul_unsigned() {
161 let result = I128::MIN.checked_mul_unsigned(&U128::ZERO);
164 assert_eq!(result.unwrap(), I128::ZERO);
165
166 let result = I128::MIN.checked_mul_unsigned(&U128::ONE);
167 assert_eq!(result.unwrap(), I128::MIN);
168
169 let result = I128::MIN.checked_mul_unsigned(&U128::MAX);
170 assert!(bool::from(result.is_none()));
171
172 let result = I128::MINUS_ONE.checked_mul_unsigned(&U128::ZERO);
175 assert_eq!(result.unwrap(), I128::ZERO);
176
177 let result = I128::MINUS_ONE.checked_mul_unsigned(&U128::ONE);
178 assert_eq!(result.unwrap(), I128::MINUS_ONE);
179
180 let result = I128::MINUS_ONE.checked_mul_unsigned(&U128::MAX);
181 assert!(bool::from(result.is_none()));
182
183 let result = I128::ZERO.checked_mul_unsigned(&U128::ZERO);
186 assert_eq!(result.unwrap(), I128::ZERO);
187
188 let result = I128::ZERO.checked_mul_unsigned(&U128::ONE);
189 assert_eq!(result.unwrap(), I128::ZERO);
190
191 let result = I128::ZERO.checked_mul_unsigned(&U128::MAX);
192 assert_eq!(result.unwrap(), I128::ZERO);
193
194 let result = I128::ONE.checked_mul_unsigned(&U128::ZERO);
197 assert_eq!(result.unwrap(), I128::ZERO);
198
199 let result = I128::ONE.checked_mul_unsigned(&U128::ONE);
200 assert_eq!(result.unwrap(), I128::ONE);
201
202 let result = I128::ONE.checked_mul_unsigned(&U128::MAX);
203 assert!(bool::from(result.is_none()));
204
205 let result = I128::MAX.checked_mul_unsigned(&U128::ZERO);
208 assert_eq!(result.unwrap(), I128::ZERO);
209
210 let result = I128::MAX.checked_mul_unsigned(&U128::ONE);
211 assert_eq!(result.unwrap(), I128::MAX);
212
213 let result = I128::MAX.checked_mul_unsigned(&U128::MAX);
214 assert!(bool::from(result.is_none()));
215 }
216
217 #[test]
218 #[allow(deprecated)]
219 fn test_checked_mul_unsigned_right() {
220 let result = I256::MIN.checked_mul_unsigned_right(&U128::ZERO);
222 assert!(bool::from(result.is_some()));
223 assert_eq!(result.unwrap(), I128::ZERO);
224
225 let result = I128::MIN.checked_mul_unsigned_right(&U256::ZERO);
226 assert!(bool::from(result.is_some()));
227 assert_eq!(result.unwrap(), I256::ZERO);
228
229 let result = I256::MIN.checked_mul_unsigned_right(&U128::ONE);
231 assert!(bool::from(result.is_none()));
232
233 let result = I128::MIN.checked_mul_unsigned_right(&U256::ONE);
234 assert!(bool::from(result.is_some()));
235 assert_eq!(result.unwrap(), I128::MIN.resize());
236
237 let result = I256::ONE.checked_mul_unsigned_right(I128::MAX.as_uint());
239 assert!(bool::from(result.is_some()));
240 assert_eq!(result.unwrap(), I128::MAX.resize());
241
242 let result = I128::ONE.checked_mul_unsigned_right(I256::MAX.as_uint());
243 assert!(bool::from(result.is_some()));
244 assert_eq!(result.unwrap(), I256::MAX);
245
246 let result = I256::ONE.checked_mul_unsigned_right(&U128::MAX);
248 assert!(bool::from(result.is_none()));
249
250 let result = I128::MIN.checked_mul_unsigned_right(&U256::MAX);
251 assert!(bool::from(result.is_none()));
252 }
253
254 #[test]
255 fn test_concatenating_mul_unsigned() {
256 assert_eq!(
257 I128::MIN.concatenating_mul_unsigned(&U128::ZERO),
258 I256::ZERO
259 );
260 assert_eq!(
261 I128::MIN.concatenating_mul_unsigned(&U128::ONE),
262 I256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80000000000000000000000000000000")
263 );
264 assert_eq!(
265 I128::MIN.concatenating_mul_unsigned(&U128::MAX),
266 I256::from_be_hex("8000000000000000000000000000000080000000000000000000000000000000")
267 );
268
269 assert_eq!(
270 I128::MINUS_ONE.concatenating_mul_unsigned(&U128::ZERO),
271 I256::ZERO
272 );
273 assert_eq!(
274 I128::MINUS_ONE.concatenating_mul_unsigned(&U128::ONE),
275 I256::MINUS_ONE
276 );
277 assert_eq!(
278 I128::MINUS_ONE.concatenating_mul_unsigned(&U128::MAX),
279 I256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000001")
280 );
281
282 assert_eq!(
283 I128::ZERO.concatenating_mul_unsigned(&U128::ZERO),
284 I256::ZERO
285 );
286 assert_eq!(
287 I128::ZERO.concatenating_mul_unsigned(&U128::ONE),
288 I256::ZERO
289 );
290 assert_eq!(
291 I128::ZERO.concatenating_mul_unsigned(&U128::MAX),
292 I256::ZERO
293 );
294
295 assert_eq!(
296 I128::ONE.concatenating_mul_unsigned(&U128::ZERO),
297 I256::ZERO
298 );
299 assert_eq!(I128::ONE.concatenating_mul_unsigned(&U128::ONE), I256::ONE);
300 assert_eq!(
301 I128::ONE.concatenating_mul_unsigned(&U128::MAX),
302 I256::from_be_hex("00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
303 );
304
305 assert_eq!(
306 I128::MAX.concatenating_mul_unsigned(&U128::ZERO),
307 I256::ZERO
308 );
309 assert_eq!(
310 I128::MAX.concatenating_mul_unsigned(&U128::ONE),
311 I256::from_be_hex("000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
312 );
313 assert_eq!(
314 I128::MAX.concatenating_mul_unsigned(&U128::MAX),
315 I256::from_be_hex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE80000000000000000000000000000001")
316 );
317 }
318}