arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/dsa/rpo_falcon512/math/field.rs
src/dsa/rpo_falcon512/math/field.rsRaw
  1use alloc::string::String;
  2use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
  3
  4use num::{One, Zero};
  5
  6use super::{fft::CyclotomicFourier, Inverse, MODULUS};
  7
  8#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
  9pub struct FalconFelt(u32);
 10
 11impl FalconFelt {
 12    pub const fn new(value: i16) -> Self {
 13        let gtz_bool = value >= 0;
 14        let gtz_int = gtz_bool as i16;
 15        let gtz_sign = gtz_int - ((!gtz_bool) as i16);
 16        let reduced = gtz_sign * (gtz_sign * value) % MODULUS;
 17        let canonical_representative = (reduced + MODULUS * (1 - gtz_int)) as u32;
 18        FalconFelt(canonical_representative)
 19    }
 20
 21    pub const fn value(&self) -> i16 {
 22        self.0 as i16
 23    }
 24
 25    pub fn balanced_value(&self) -> i16 {
 26        let value = self.value();
 27        let g = (value > ((MODULUS) / 2)) as i16;
 28        value - (MODULUS) * g
 29    }
 30
 31    pub const fn multiply(&self, other: Self) -> Self {
 32        FalconFelt((self.0 * other.0) % MODULUS as u32)
 33    }
 34}
 35
 36impl Add for FalconFelt {
 37    type Output = Self;
 38
 39    #[allow(clippy::suspicious_arithmetic_impl)]
 40    fn add(self, rhs: Self) -> Self::Output {
 41        let (s, _) = self.0.overflowing_add(rhs.0);
 42        let (d, n) = s.overflowing_sub(MODULUS as u32);
 43        let (r, _) = d.overflowing_add(MODULUS as u32 * (n as u32));
 44        FalconFelt(r)
 45    }
 46}
 47
 48impl AddAssign for FalconFelt {
 49    fn add_assign(&mut self, rhs: Self) {
 50        *self = *self + rhs;
 51    }
 52}
 53
 54impl Sub for FalconFelt {
 55    type Output = Self;
 56
 57    fn sub(self, rhs: Self) -> Self::Output {
 58        self + -rhs
 59    }
 60}
 61
 62impl SubAssign for FalconFelt {
 63    fn sub_assign(&mut self, rhs: Self) {
 64        *self = *self - rhs;
 65    }
 66}
 67
 68impl Neg for FalconFelt {
 69    type Output = FalconFelt;
 70
 71    fn neg(self) -> Self::Output {
 72        let is_nonzero = self.0 != 0;
 73        let r = MODULUS as u32 - self.0;
 74        FalconFelt(r * (is_nonzero as u32))
 75    }
 76}
 77
 78impl Mul for FalconFelt {
 79    fn mul(self, rhs: Self) -> Self::Output {
 80        FalconFelt((self.0 * rhs.0) % MODULUS as u32)
 81    }
 82
 83    type Output = Self;
 84}
 85
 86impl MulAssign for FalconFelt {
 87    fn mul_assign(&mut self, rhs: Self) {
 88        *self = *self * rhs;
 89    }
 90}
 91
 92impl Div for FalconFelt {
 93    type Output = FalconFelt;
 94
 95    #[allow(clippy::suspicious_arithmetic_impl)]
 96    fn div(self, rhs: Self) -> Self::Output {
 97        self * rhs.inverse_or_zero()
 98    }
 99}
100
101impl DivAssign for FalconFelt {
102    fn div_assign(&mut self, rhs: Self) {
103        *self = *self / rhs
104    }
105}
106
107impl Zero for FalconFelt {
108    fn zero() -> Self {
109        FalconFelt::new(0)
110    }
111
112    fn is_zero(&self) -> bool {
113        self.0 == 0
114    }
115}
116
117impl One for FalconFelt {
118    fn one() -> Self {
119        FalconFelt::new(1)
120    }
121}
122
123impl Inverse for FalconFelt {
124    fn inverse_or_zero(self) -> Self {
125        // q-2 = 0b10 11 11 11  11 11 11
126        let two = self.multiply(self);
127        let three = two.multiply(self);
128        let six = three.multiply(three);
129        let twelve = six.multiply(six);
130        let fifteen = twelve.multiply(three);
131        let thirty = fifteen.multiply(fifteen);
132        let sixty = thirty.multiply(thirty);
133        let sixty_three = sixty.multiply(three);
134
135        let sixty_three_sq = sixty_three.multiply(sixty_three);
136        let sixty_three_qu = sixty_three_sq.multiply(sixty_three_sq);
137        let sixty_three_oc = sixty_three_qu.multiply(sixty_three_qu);
138        let sixty_three_hx = sixty_three_oc.multiply(sixty_three_oc);
139        let sixty_three_tt = sixty_three_hx.multiply(sixty_three_hx);
140        let sixty_three_sf = sixty_three_tt.multiply(sixty_three_tt);
141
142        let all_ones = sixty_three_sf.multiply(sixty_three);
143        let two_e_twelve = all_ones.multiply(self);
144        let two_e_thirteen = two_e_twelve.multiply(two_e_twelve);
145
146        two_e_thirteen.multiply(all_ones)
147    }
148}
149
150impl CyclotomicFourier for FalconFelt {
151    fn primitive_root_of_unity(n: usize) -> Self {
152        let log2n = n.ilog2();
153        assert!(log2n <= 12);
154        // and 1331 is a twelfth root of unity
155        let mut a = FalconFelt::new(1331);
156        let num_squarings = 12 - n.ilog2();
157        for _ in 0..num_squarings {
158            a *= a;
159        }
160        a
161    }
162}
163
164impl TryFrom<u32> for FalconFelt {
165    type Error = String;
166
167    fn try_from(value: u32) -> Result<Self, Self::Error> {
168        if value >= MODULUS as u32 {
169            Err(format!("value {value} is greater than or equal to the field modulus {MODULUS}"))
170        } else {
171            Ok(FalconFelt::new(value as i16))
172        }
173    }
174}