crypto_bigint/uint/
mul_signed.rs1use crate::{Choice, Concat, CtOption, Int, Uint};
2
3impl<const LIMBS: usize> Uint<LIMBS> {
4 #[must_use]
11 pub const fn widening_mul_signed<const RHS_LIMBS: usize>(
12 &self,
13 rhs: &Int<RHS_LIMBS>,
14 ) -> (Uint<LIMBS>, Uint<RHS_LIMBS>, Choice) {
15 let (rhs_abs, rhs_sgn) = rhs.abs_sign();
16 let (lo, hi) = self.widening_mul(&rhs_abs);
17 (lo, hi, rhs_sgn)
18 }
19
20 #[must_use]
22 pub const fn concatenating_mul_signed<const RHS_LIMBS: usize, const WIDE_LIMBS: usize>(
23 &self,
24 rhs: &Int<RHS_LIMBS>,
25 ) -> Int<WIDE_LIMBS>
26 where
27 Uint<LIMBS>: Concat<RHS_LIMBS, Output = Uint<WIDE_LIMBS>>,
28 {
29 let (rhs_abs, rhs_sign) = rhs.abs_sign();
30 let product_abs = self.concatenating_mul(&rhs_abs);
31
32 *product_abs.wrapping_neg_if(rhs_sign).as_int()
34 }
35
36 #[must_use]
38 pub fn checked_mul_signed<const RHS_LIMBS: usize>(
39 &self,
40 rhs: &Int<RHS_LIMBS>,
41 ) -> CtOption<Int<LIMBS>> {
42 let (abs_rhs, rhs_sgn) = rhs.abs_sign();
43 let maybe_res = self.checked_mul(&abs_rhs);
44 Int::new_from_abs_opt_sign(maybe_res, rhs_sgn)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use crate::{I64, I128, I256, U64, U128};
51
52 #[test]
53 fn widening_mul_signed() {
54 let (lo, hi, rhs_sgn) = U128::MAX.widening_mul_signed(&I64::from_i64(-55));
55 assert_eq!(lo, U128::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9"));
56 assert_eq!(hi, U64::from_u64(54));
57 assert!(rhs_sgn.to_bool());
58 }
59
60 #[test]
61 fn concatenating_mul_signed() {
62 assert_eq!(
63 U128::MAX.concatenating_mul_signed(&I128::from_i64(-55)),
64 I256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC900000000000000000000000000000037")
65 );
66 assert_eq!(
67 U128::MAX.concatenating_mul_signed(&I128::MAX),
68 I256::from_be_hex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE80000000000000000000000000000001")
69 );
70 assert_eq!(
71 U128::MAX.concatenating_mul_signed(&I128::MIN),
72 I256::from_be_hex("8000000000000000000000000000000080000000000000000000000000000000")
73 );
74 }
75
76 #[test]
77 fn checked_mul_signed() {
78 assert_eq!(
79 U64::from_be_hex("00000000FFFFFFFF")
80 .checked_mul_signed(&I64::from_be_hex("FFFFFFFF80000000"))
81 .unwrap(),
82 I64::from_be_hex("8000000080000000")
83 );
84 assert!(bool::from(
85 U64::MAX.checked_mul_signed(&I128::ONE).is_none()
86 ));
87 }
88}