1use crate::field::Field;
2use crate::keccak::fips202::{CrystalsXof, Shake128, Shake128Params, SpongeOps};
3use crate::keccak::KeccakParams;
4use crate::lib::fmt::Debug;
5use crate::lib::ops::{AddAssign, Index, IndexMut, SubAssign};
6use crate::lib::slice::{Iter, IterMut};
7use crate::polyvec::PolyVec;
8
9pub mod dilithium;
10pub mod kyber;
11
12pub const UNIFORM_SEED_BYTES: usize = 32;
14
15pub trait Polynomial:
16 Index<usize, Output = Self::F>
17 + IndexMut<usize, Output = Self::F>
18 + Default
20 + Sized
21 + Clone
22 + Copy + for<'a> AddAssign<&'a Self>
24 + for<'a> SubAssign<&'a Self>
25{
26 type F: Field;
27}
28
29pub trait SizedPolynomial<const N: usize>:
30 Polynomial + AsRef<[Self::F; N]> + AsMut<[Self::F; N]>
31{
32 const N: usize = N;
33
34 const INV_NTT_SCALE: <Self::F as Field>::E;
35
36 const SCALAR_BYTES: usize = core::mem::size_of::<<Self::F as Field>::E>();
37
38 const UNIFORM_SEED_BYTES: usize = UNIFORM_SEED_BYTES; const NUM_SCALARS: usize =
41 Self::N * core::mem::size_of::<Self::F>() / core::mem::size_of::<<Self::F as Field>::E>();
42
43 fn zetas(k: usize) -> <Self::F as Field>::E;
44
45 fn ntt(&mut self) {
81 let mut k = 0;
82 let mut len = Self::N / 2;
83 while len > 0 {
84 let len_times_two = len << 1;
85 let mut start = 0;
86 while start < Self::N {
87 let zeta = Self::zetas(k);
88 k += 1;
89 let end = start + len_times_two;
90 let (top, bottom) = self.as_mut()[start..end].split_at_mut(len);
91
92 for (u, v) in top.iter_mut().zip(bottom) {
94 let t = *v * zeta;
95 *v = *u - t;
96 *u += t;
97 }
98 start = end;
99 }
100 len >>= 1;
101 }
102 }
103
104 fn inv_ntt(&mut self) {
126 let mut k = Self::N - 1;
127 let mut len = 1;
128 while len < Self::N {
129 let mut start = 0;
130 let len_times_two = len << 1;
131 while start < Self::N {
132 k -= 1;
133 let zeta = Self::zetas(k);
134 let end = start + len_times_two;
135 let (left, right) = self.as_mut()[start..end].split_at_mut(len);
136
137 for (u, v) in left.iter_mut().zip(right) {
138 let t = *u;
139 *u = (t + *v).maybe_reduce();
140 *v = (*v - t) * zeta;
141 }
142 start = end;
143 }
144 len = len_times_two;
145 }
146
147 for f in self.as_mut() {
148 *f *= Self::INV_NTT_SCALE;
149 }
150 }
151
152 #[inline(always)]
156 fn reduce(&mut self) {
157 for f in self.as_mut() {
158 *f = f.reduce();
159 }
160 }
161
162 fn pointwise(&self, other: &Self, result: &mut Self);
163
164 fn pointwise_acc(&self, other: &Self, result: &mut Self);
165
166 fn vector_mul_acc<const K: usize>(
167 &mut self,
168 lhs: &PolyVec<Self, N, K>,
169 rhs: &PolyVec<Self, N, K>,
170 ) {
171 let mut t = Self::default();
172
173 for (l, r) in lhs.as_ref().iter().zip(rhs.as_ref().iter()) {
174 l.pointwise(r, &mut t);
175 self.add_assign(&t);
176 }
177 }
178
179 fn rej_uniform(&mut self, start: usize, bytes: &[u8; Shake128Params::RATE_BYTES]) -> usize;
180
181 #[inline]
182 fn uniform(&mut self, seed: &[u8; UNIFORM_SEED_BYTES], i: u8, j: u8) {
183 let mut shake128 = Shake128::default();
184 shake128.absorb_xof_with_nonces(seed, i, j);
185 let mut xof_out = [0u8; Shake128Params::RATE_BYTES];
186
187 let mut ctr = 0;
188 while ctr < Self::NUM_SCALARS {
189 shake128.squeeze(&mut xof_out);
190 ctr = self.rej_uniform(ctr, &xof_out);
191 }
192 debug_assert_eq!(ctr, Self::NUM_SCALARS);
193 }
194}
195
196#[derive(Debug, Clone, Copy, PartialEq)]
197pub struct Poly<T: Field, const N: usize>([T; N]);
198
199impl<T: Field, const N: usize> Default for Poly<T, N> {
200 #[inline(always)]
201 fn default() -> Self {
202 Poly([T::default(); N])
203 }
204}
205
206impl<'a, F: Field, const N: usize> IntoIterator for &'a Poly<F, N> {
230 type Item = &'a F;
231 type IntoIter = Iter<'a, F>;
232
233 #[inline(always)]
234 fn into_iter(self) -> Iter<'a, F> {
235 self.0.iter()
236 }
237}
238
239impl<'a, F: Field, const N: usize> IntoIterator for &'a mut Poly<F, N> {
240 type Item = &'a mut F;
241 type IntoIter = IterMut<'a, F>;
242
243 #[inline(always)]
244 fn into_iter(self) -> IterMut<'a, F> {
245 self.0.iter_mut()
246 }
247}
248
249impl<T: Field, const N: usize> AddAssign<&Self> for Poly<T, N> {
253 #[inline]
254 fn add_assign(&mut self, rhs: &Self) {
255 for (l, r) in self.into_iter().zip(rhs) {
256 *l += *r;
257 }
258 }
259}
260
261impl<T: Field, const N: usize> SubAssign<&Self> for Poly<T, N> {
265 #[inline(always)]
266 fn sub_assign(&mut self, rhs: &Self) {
267 for i in 0..self.0.len() {
268 self[i] -= rhs[i];
269 }
270 }
271}
272
273impl<T: Field, const N: usize> Index<usize> for Poly<T, N> {
274 type Output = T;
275 #[inline(always)]
276 fn index(&self, i: usize) -> &Self::Output {
277 &self.0[i]
278 }
279}
280
281impl<T: Field, const N: usize> IndexMut<usize> for Poly<T, N> {
282 #[inline(always)]
283 fn index_mut(&mut self, i: usize) -> &mut Self::Output {
284 &mut self.0[i]
285 }
286}
287
288impl<F: Field, const N: usize> AsRef<[F; N]> for Poly<F, N> {
289 #[inline(always)]
290 fn as_ref(&self) -> &[F; N] {
291 &self.0
292 }
293}
294
295impl<F: Field, const N: usize> AsMut<[F; N]> for Poly<F, N> {
296 #[inline(always)]
297 fn as_mut(&mut self) -> &mut [F; N] {
298 &mut self.0
299 }
300}
301
302#[cfg(test)]
303mod tests {}