arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/math/src/ring/impl_u64/ring.rs
math/src/ring/impl_u64/ring.rsRaw
  1use crate::dft::ntt::Table;
  2use crate::modulus::barrett::Barrett;
  3use crate::modulus::montgomery::Montgomery;
  4use crate::modulus::prime::Prime;
  5use crate::modulus::VectorOperations;
  6use crate::modulus::{BARRETT, REDUCEMOD};
  7use crate::poly::Poly;
  8use crate::ring::Ring;
  9use crate::CHUNK;
 10use num_bigint::BigInt;
 11use num_traits::ToPrimitive;
 12
 13impl Ring<u64> {
 14    pub fn new(n: usize, q_base: u64, q_power: usize) -> Self {
 15        let prime: Prime<u64> = Prime::<u64>::new(q_base, q_power);
 16        Self {
 17            n: n,
 18            modulus: prime.clone(),
 19            dft: Box::new(Table::<u64>::new(prime, n << 1)),
 20        }
 21    }
 22
 23    pub fn from_bigint(&self, coeffs: &[BigInt], step: usize, a: &mut Poly<u64>) {
 24        assert!(
 25            step <= a.n(),
 26            "invalid step: step={} > a.n()={}",
 27            step,
 28            a.n()
 29        );
 30        assert!(
 31            coeffs.len() <= a.n() / step,
 32            "invalid coeffs: coeffs.len()={} > a.n()/step={}",
 33            coeffs.len(),
 34            a.n() / step
 35        );
 36        let q_big: BigInt = BigInt::from(self.modulus.q);
 37        a.0.iter_mut()
 38            .step_by(step)
 39            .enumerate()
 40            .for_each(|(i, v)| *v = (&coeffs[i] % &q_big).to_u64().unwrap());
 41    }
 42}
 43
 44impl Ring<u64> {
 45    pub fn ntt_inplace<const LAZY: bool>(&self, poly: &mut Poly<u64>) {
 46        match LAZY {
 47            true => self.dft.forward_inplace_lazy(&mut poly.0),
 48            false => self.dft.forward_inplace(&mut poly.0),
 49        }
 50    }
 51
 52    pub fn intt_inplace<const LAZY: bool>(&self, poly: &mut Poly<u64>) {
 53        match LAZY {
 54            true => self.dft.backward_inplace_lazy(&mut poly.0),
 55            false => self.dft.backward_inplace(&mut poly.0),
 56        }
 57    }
 58
 59    pub fn ntt<const LAZY: bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>) {
 60        poly_out.0.copy_from_slice(&poly_in.0);
 61        match LAZY {
 62            true => self.dft.forward_inplace_lazy(&mut poly_out.0),
 63            false => self.dft.forward_inplace(&mut poly_out.0),
 64        }
 65    }
 66
 67    pub fn intt<const LAZY: bool>(&self, poly_in: &Poly<u64>, poly_out: &mut Poly<u64>) {
 68        poly_out.0.copy_from_slice(&poly_in.0);
 69        match LAZY {
 70            true => self.dft.backward_inplace_lazy(&mut poly_out.0),
 71            false => self.dft.backward_inplace(&mut poly_out.0),
 72        }
 73    }
 74}
 75
 76impl Ring<u64> {
 77    #[inline(always)]
 78    pub fn a_add_b_into_b<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &mut Poly<u64>) {
 79        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
 80        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
 81        self.modulus
 82            .va_add_vb_into_vb::<CHUNK, REDUCE>(&a.0, &mut b.0);
 83    }
 84
 85    #[inline(always)]
 86    pub fn a_add_b_into_c<const REDUCE: REDUCEMOD>(
 87        &self,
 88        a: &Poly<u64>,
 89        b: &Poly<u64>,
 90        c: &mut Poly<u64>,
 91    ) {
 92        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
 93        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
 94        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
 95        self.modulus
 96            .va_add_vb_into_vc::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
 97    }
 98
 99    #[inline(always)]
100    pub fn a_add_b_scalar_into_a<const REDUCE: REDUCEMOD>(&self, b: &u64, a: &mut Poly<u64>) {
101        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
102        self.modulus.va_add_sb_into_va::<CHUNK, REDUCE>(b, &mut a.0);
103    }
104
105    #[inline(always)]
106    pub fn a_add_b_scalar_into_c<const REDUCE: REDUCEMOD>(
107        &self,
108        a: &Poly<u64>,
109        b: &u64,
110        c: &mut Poly<u64>,
111    ) {
112        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
113        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
114        self.modulus
115            .va_add_sb_into_vc::<CHUNK, REDUCE>(&a.0, b, &mut c.0);
116    }
117
118    #[inline(always)]
119    pub fn a_add_scalar_b_mul_c_scalar_barrett_into_a<const REDUCE: REDUCEMOD>(
120        &self,
121        b: &u64,
122        c: &Barrett<u64>,
123        a: &mut Poly<u64>,
124    ) {
125        debug_assert!(a.n() == self.n(), "b.n()={} != n={}", a.n(), self.n());
126        self.modulus
127            .va_add_sb_mul_sc_into_va::<CHUNK, REDUCE>(b, c, &mut a.0);
128    }
129
130    #[inline(always)]
131    pub fn add_scalar_then_mul_scalar_barrett<const REDUCE: REDUCEMOD>(
132        &self,
133        a: &Poly<u64>,
134        b: &u64,
135        c: &Barrett<u64>,
136        d: &mut Poly<u64>,
137    ) {
138        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
139        debug_assert!(d.n() == self.n(), "c.n()={} != n={}", d.n(), self.n());
140        self.modulus
141            .va_add_sb_mul_sc_into_vd::<CHUNK, REDUCE>(&a.0, b, c, &mut d.0);
142    }
143
144    #[inline(always)]
145    pub fn a_sub_b_into_b<const BRANGE: u8, const REDUCE: REDUCEMOD>(
146        &self,
147        a: &Poly<u64>,
148        b: &mut Poly<u64>,
149    ) {
150        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
151        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
152        self.modulus
153            .va_sub_vb_into_vb::<CHUNK, BRANGE, REDUCE>(&a.0, &mut b.0);
154    }
155
156    #[inline(always)]
157    pub fn a_sub_b_into_a<const BRANGE: u8, const REDUCE: REDUCEMOD>(
158        &self,
159        b: &Poly<u64>,
160        a: &mut Poly<u64>,
161    ) {
162        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
163        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
164        self.modulus
165            .va_sub_vb_into_va::<CHUNK, BRANGE, REDUCE>(&b.0, &mut a.0);
166    }
167
168    #[inline(always)]
169    pub fn a_sub_b_into_c<const BRANGE: u8, const REDUCE: REDUCEMOD>(
170        &self,
171        a: &Poly<u64>,
172        b: &Poly<u64>,
173        c: &mut Poly<u64>,
174    ) {
175        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
176        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
177        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
178        self.modulus
179            .va_sub_vb_into_vc::<CHUNK, BRANGE, REDUCE>(&a.0, &b.0, &mut c.0);
180    }
181
182    #[inline(always)]
183    pub fn a_neg_into_b<const ARANGE: u8, const REDUCE: REDUCEMOD>(
184        &self,
185        a: &Poly<u64>,
186        b: &mut Poly<u64>,
187    ) {
188        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
189        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
190        self.modulus
191            .va_neg_into_vb::<CHUNK, ARANGE, REDUCE>(&a.0, &mut b.0);
192    }
193
194    #[inline(always)]
195    pub fn a_neg_into_a<const ARANGE: u8, const REDUCE: REDUCEMOD>(&self, a: &mut Poly<u64>) {
196        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
197        self.modulus
198            .va_neg_into_va::<CHUNK, ARANGE, REDUCE>(&mut a.0);
199    }
200
201    #[inline(always)]
202    pub fn a_mul_b_montgomery_into_c<const REDUCE: REDUCEMOD>(
203        &self,
204        a: &Poly<Montgomery<u64>>,
205        b: &Poly<u64>,
206        c: &mut Poly<u64>,
207    ) {
208        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
209        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
210        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
211        self.modulus
212            .va_mont_mul_vb_into_vc::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
213    }
214
215    #[inline(always)]
216    pub fn a_mul_b_montgomery_into_a<const REDUCE: REDUCEMOD>(
217        &self,
218        b: &Poly<Montgomery<u64>>,
219        a: &mut Poly<u64>,
220    ) {
221        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
222        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
223        self.modulus
224            .va_mont_mul_vb_into_vb::<CHUNK, REDUCE>(&b.0, &mut a.0);
225    }
226
227    #[inline(always)]
228    pub fn a_mul_b_scalar_into_c<const REDUCE: REDUCEMOD>(
229        &self,
230        a: &Poly<u64>,
231        b: &u64,
232        c: &mut Poly<u64>,
233    ) {
234        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
235        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
236        self.modulus.sa_barrett_mul_vb_into_vc::<CHUNK, REDUCE>(
237            &self.modulus.barrett.prepare(*b),
238            &a.0,
239            &mut c.0,
240        );
241    }
242
243    #[inline(always)]
244    pub fn a_mul_b_scalar_into_a<const REDUCE: REDUCEMOD>(&self, b: &u64, a: &mut Poly<u64>) {
245        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
246        self.modulus.sa_barrett_mul_vb_into_vb::<CHUNK, REDUCE>(
247            &self
248                .modulus
249                .barrett
250                .prepare(self.modulus.barrett.reduce::<BARRETT>(b)),
251            &mut a.0,
252        );
253    }
254
255    #[inline(always)]
256    pub fn a_mul_b_scalar_barrett_into_a<const REDUCE: REDUCEMOD>(
257        &self,
258        b: &Barrett<u64>,
259        a: &mut Poly<u64>,
260    ) {
261        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
262        self.modulus
263            .sa_barrett_mul_vb_into_vb::<CHUNK, REDUCE>(b, &mut a.0);
264    }
265
266    #[inline(always)]
267    pub fn a_mul_b_scalar_barrett_into_c<const REDUCE: REDUCEMOD>(
268        &self,
269        a: &Barrett<u64>,
270        b: &Poly<u64>,
271        c: &mut Poly<u64>,
272    ) {
273        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
274        self.modulus
275            .sa_barrett_mul_vb_into_vc::<CHUNK, REDUCE>(a, &b.0, &mut c.0);
276    }
277
278    #[inline(always)]
279    pub fn a_sub_b_mul_c_scalar_barrett_into_d<const VBRANGE: u8, const REDUCE: REDUCEMOD>(
280        &self,
281        a: &Poly<u64>,
282        b: &Poly<u64>,
283        c: &Barrett<u64>,
284        d: &mut Poly<u64>,
285    ) {
286        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
287        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
288        debug_assert!(d.n() == self.n(), "d.n()={} != n={}", d.n(), self.n());
289        self.modulus
290            .va_sub_vb_mul_sc_into_vd::<CHUNK, VBRANGE, REDUCE>(&a.0, &b.0, c, &mut d.0);
291    }
292
293    #[inline(always)]
294    pub fn b_sub_a_mul_c_scalar_barrett_into_a<const BRANGE: u8, const REDUCE: REDUCEMOD>(
295        &self,
296        b: &Poly<u64>,
297        c: &Barrett<u64>,
298        a: &mut Poly<u64>,
299    ) {
300        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
301        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
302        self.modulus
303            .va_sub_vb_mul_sc_into_vb::<CHUNK, BRANGE, REDUCE>(&b.0, c, &mut a.0);
304    }
305
306    #[inline(always)]
307    pub fn a_sub_b_add_c_scalar_mul_d_scalar_barrett_into_e<
308        const BRANGE: u8,
309        const REDUCE: REDUCEMOD,
310    >(
311        &self,
312        a: &Poly<u64>,
313        b: &Poly<u64>,
314        c: &u64,
315        d: &Barrett<u64>,
316        e: &mut Poly<u64>,
317    ) {
318        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
319        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
320        debug_assert!(e.n() == self.n(), "e.n()={} != n={}", e.n(), self.n());
321        self.modulus
322            .vb_sub_va_add_sc_mul_sd_into_ve::<CHUNK, BRANGE, REDUCE>(&a.0, &b.0, c, d, &mut e.0);
323    }
324
325    #[inline(always)]
326    pub fn b_sub_a_add_c_scalar_mul_d_scalar_barrett_into_a<
327        const BRANGE: u8,
328        const REDUCE: REDUCEMOD,
329    >(
330        &self,
331        b: &Poly<u64>,
332        c: &u64,
333        d: &Barrett<u64>,
334        a: &mut Poly<u64>,
335    ) {
336        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
337        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
338        self.modulus
339            .vb_sub_va_add_sc_mul_sd_into_va::<CHUNK, BRANGE, REDUCE>(&b.0, c, d, &mut a.0);
340    }
341}