Skip to main content

p521/arithmetic/field/
loose.rs

1use super::{FieldElement, field_impl::*};
2use core::{fmt, ops::Mul};
3use elliptic_curve::bigint::cpubits;
4
5/// "Loose" field element: unreduced and intended to be followed by an
6/// additional operation which will perform a reduction.
7#[derive(Clone, Copy)]
8pub struct LooseFieldElement(pub(super) fiat_p521_loose_field_element);
9
10impl LooseFieldElement {
11    cpubits! {
12        32 => { const LIMBS: usize = 19; }
13        64 => { const LIMBS: usize = 9; }
14    }
15
16    /// Reduce field element.
17    #[inline]
18    pub const fn carry(&self) -> FieldElement {
19        let mut out = fiat_p521_tight_field_element([0; Self::LIMBS]);
20        fiat_p521_carry(&mut out, &self.0);
21        FieldElement(out)
22    }
23
24    /// Multiplies two field elements and reduces the result.
25    #[inline]
26    pub const fn multiply(&self, rhs: &Self) -> FieldElement {
27        let mut out = fiat_p521_tight_field_element([0; Self::LIMBS]);
28        fiat_p521_carry_mul(&mut out, &self.0, &rhs.0);
29        FieldElement(out)
30    }
31
32    /// Squares a field element and reduces the result.
33    #[inline]
34    pub const fn square(&self) -> FieldElement {
35        let mut out = fiat_p521_tight_field_element([0; Self::LIMBS]);
36        fiat_p521_carry_square(&mut out, &self.0);
37        FieldElement(out)
38    }
39}
40
41impl From<FieldElement> for LooseFieldElement {
42    #[inline]
43    fn from(tight: FieldElement) -> LooseFieldElement {
44        LooseFieldElement::from(&tight)
45    }
46}
47
48impl From<&FieldElement> for LooseFieldElement {
49    #[inline]
50    fn from(tight: &FieldElement) -> LooseFieldElement {
51        tight.relax()
52    }
53}
54
55impl From<LooseFieldElement> for FieldElement {
56    #[inline]
57    fn from(loose: LooseFieldElement) -> FieldElement {
58        FieldElement::from(&loose)
59    }
60}
61
62impl From<&LooseFieldElement> for FieldElement {
63    #[inline]
64    fn from(loose: &LooseFieldElement) -> FieldElement {
65        loose.carry()
66    }
67}
68
69impl Mul for LooseFieldElement {
70    type Output = FieldElement;
71
72    #[inline]
73    fn mul(self, rhs: LooseFieldElement) -> FieldElement {
74        Self::multiply(&self, &rhs)
75    }
76}
77
78impl Mul<&LooseFieldElement> for LooseFieldElement {
79    type Output = FieldElement;
80
81    #[inline]
82    fn mul(self, rhs: &LooseFieldElement) -> FieldElement {
83        Self::multiply(&self, rhs)
84    }
85}
86
87impl Mul<&LooseFieldElement> for &LooseFieldElement {
88    type Output = FieldElement;
89
90    #[inline]
91    fn mul(self, rhs: &LooseFieldElement) -> FieldElement {
92        LooseFieldElement::multiply(self, rhs)
93    }
94}
95
96impl fmt::Debug for LooseFieldElement {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        f.debug_tuple("LooseFieldElement").field(&self.0.0).finish()
99    }
100}