crypto_bigint/limb/
mul.rs1use crate::{
4 primitives::{mac, mul_wide},
5 Checked, CheckedMul, Limb, Wrapping, Zero,
6};
7use core::ops::{Mul, MulAssign};
8use num_traits::WrappingMul;
9use subtle::CtOption;
10
11impl Limb {
12 #[inline(always)]
14 pub const fn mac(self, b: Limb, c: Limb, carry: Limb) -> (Limb, Limb) {
15 let (res, carry) = mac(self.0, b.0, c.0, carry.0);
16 (Limb(res), Limb(carry))
17 }
18
19 #[inline(always)]
21 pub const fn saturating_mul(&self, rhs: Self) -> Self {
22 Limb(self.0.saturating_mul(rhs.0))
23 }
24
25 #[inline(always)]
27 pub const fn wrapping_mul(&self, rhs: Self) -> Self {
28 Limb(self.0.wrapping_mul(rhs.0))
29 }
30
31 pub(crate) const fn mul_wide(&self, rhs: Self) -> (Self, Self) {
33 let (lo, hi) = mul_wide(self.0, rhs.0);
34 (Limb(lo), Limb(hi))
35 }
36}
37
38impl CheckedMul for Limb {
39 #[inline]
40 fn checked_mul(&self, rhs: &Self) -> CtOption<Self> {
41 let (lo, hi) = self.mul_wide(*rhs);
42 CtOption::new(lo, hi.is_zero())
43 }
44}
45
46impl Mul<Limb> for Limb {
47 type Output = Limb;
48
49 #[inline]
50 fn mul(self, rhs: Limb) -> Self {
51 self.checked_mul(&rhs)
52 .expect("attempted to multiply with overflow")
53 }
54}
55
56impl Mul<&Limb> for Limb {
57 type Output = Limb;
58
59 #[inline]
60 fn mul(self, rhs: &Limb) -> Self {
61 self * *rhs
62 }
63}
64
65impl Mul<Limb> for &Limb {
66 type Output = Limb;
67
68 #[inline]
69 fn mul(self, rhs: Limb) -> Self::Output {
70 *self * rhs
71 }
72}
73
74impl Mul<&Limb> for &Limb {
75 type Output = Limb;
76
77 #[inline]
78 fn mul(self, rhs: &Limb) -> Self::Output {
79 *self * *rhs
80 }
81}
82
83impl MulAssign for Wrapping<Limb> {
84 #[inline]
85 fn mul_assign(&mut self, other: Self) {
86 *self = *self * other;
87 }
88}
89
90impl MulAssign<&Wrapping<Limb>> for Wrapping<Limb> {
91 #[inline]
92 fn mul_assign(&mut self, other: &Self) {
93 *self = *self * other;
94 }
95}
96
97impl MulAssign for Checked<Limb> {
98 #[inline]
99 fn mul_assign(&mut self, other: Self) {
100 *self = *self * other;
101 }
102}
103
104impl MulAssign<&Checked<Limb>> for Checked<Limb> {
105 #[inline]
106 fn mul_assign(&mut self, other: &Self) {
107 *self = *self * other;
108 }
109}
110
111impl WrappingMul for Limb {
112 #[inline]
113 fn wrapping_mul(&self, v: &Self) -> Self {
114 self.wrapping_mul(*v)
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::{CheckedMul, Limb};
121
122 #[test]
123 #[cfg(target_pointer_width = "32")]
124 fn checked_mul_ok() {
125 let n = Limb::from_u16(0xffff);
126 assert_eq!(n.checked_mul(&n).unwrap(), Limb::from_u32(0xfffe_0001));
127 }
128
129 #[test]
130 #[cfg(target_pointer_width = "64")]
131 fn checked_mul_ok() {
132 let n = Limb::from_u32(0xffff_ffff);
133 assert_eq!(
134 n.checked_mul(&n).unwrap(),
135 Limb::from_u64(0xffff_fffe_0000_0001)
136 );
137 }
138
139 #[test]
140 fn checked_mul_overflow() {
141 let n = Limb::MAX;
142 assert!(bool::from(n.checked_mul(&n).is_none()));
143 }
144}