Skip to main content

crypto_bigint/uint/boxed/mul/
helper.rs

1//! [`BoxedUint`] multiplication helper to reduce allocations.
2
3use alloc::vec::Vec;
4
5use crate::{BoxedUint, Choice, Limb, UintRef};
6
7/// Boxed multiplier with a pre-allocated internal buffer to avoid additional allocations.
8#[derive(Debug, Clone)]
9pub struct BoxedMultiplier {
10    product: Vec<Limb>,
11}
12
13impl BoxedMultiplier {
14    pub fn new() -> Self {
15        Self {
16            product: Vec::new(),
17        }
18    }
19
20    fn get_buffer(&mut self, limbs: usize) -> &mut UintRef {
21        self.product.clear();
22        self.product.resize(limbs, Limb::ZERO);
23        UintRef::new_mut(&mut self.product[..limbs])
24    }
25
26    pub fn overflowing_mul(&mut self, lhs: &BoxedUint, rhs: &BoxedUint) -> (&mut UintRef, Choice) {
27        let buf = self.get_buffer(lhs.nlimbs());
28        let overflow = lhs.as_uint_ref().overflowing_mul(rhs.as_uint_ref(), buf);
29        (buf, overflow)
30    }
31
32    pub fn overflowing_mul_assign(&mut self, lhs: &mut BoxedUint, rhs: &BoxedUint) -> Choice {
33        let (buf, overflow) = self.overflowing_mul(lhs, rhs);
34        lhs.as_mut_uint_ref().copy_from(buf);
35        overflow
36    }
37
38    pub fn overflowing_square(&mut self, lhs: &BoxedUint) -> (&mut UintRef, Choice) {
39        let buf = self.get_buffer(lhs.nlimbs());
40        let overflow = lhs.as_uint_ref().overflowing_square(buf);
41        (buf, overflow)
42    }
43
44    pub fn overflowing_square_assign(&mut self, lhs: &mut BoxedUint) -> Choice {
45        let (buf, overflow) = self.overflowing_square(lhs);
46        lhs.as_mut_uint_ref().copy_from(buf);
47        overflow
48    }
49
50    pub fn wrapping_mul(&mut self, lhs: &BoxedUint, rhs: &BoxedUint) -> &mut UintRef {
51        self.wrapping_mul_with_carry(lhs, rhs).0
52    }
53
54    pub fn wrapping_mul_assign(&mut self, lhs: &mut BoxedUint, rhs: &BoxedUint) {
55        let (buf, _) = self.wrapping_mul_with_carry(lhs, rhs);
56        lhs.as_mut_uint_ref().copy_from(buf);
57    }
58
59    fn wrapping_mul_with_carry(
60        &mut self,
61        lhs: &BoxedUint,
62        rhs: &BoxedUint,
63    ) -> (&mut UintRef, Limb) {
64        let buf = self.get_buffer(lhs.nlimbs());
65        let carry = lhs.as_uint_ref().wrapping_mul(rhs.as_uint_ref(), buf);
66        (buf, carry)
67    }
68
69    pub fn wrapping_square_assign(&mut self, lhs: &mut BoxedUint) {
70        let (buf, _) = self.wrapping_square_with_carry(lhs);
71        lhs.as_mut_uint_ref().copy_from(buf);
72    }
73
74    fn wrapping_square_with_carry(&mut self, lhs: &BoxedUint) -> (&mut UintRef, Limb) {
75        let buf = self.get_buffer(lhs.nlimbs());
76        let carry = lhs.as_uint_ref().wrapping_square(buf);
77        (buf, carry)
78    }
79}