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, (2 * n) as u64)),
 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 add_inplace<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 add<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &Poly<u64>, c: &mut Poly<u64>) {
 87        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
 88        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
 89        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
 90        self.modulus
 91            .va_add_vb_into_vc::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
 92    }
 93
 94    #[inline(always)]
 95    pub fn add_scalar_inplace<const REDUCE: REDUCEMOD>(&self, a: &u64, b: &mut Poly<u64>) {
 96        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
 97        self.modulus.sa_add_vb_into_vb::<CHUNK, REDUCE>(a, &mut b.0);
 98    }
 99
100    #[inline(always)]
101    pub fn add_scalar<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &u64, c: &mut Poly<u64>) {
102        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
103        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
104        self.modulus
105            .va_add_sb_into_vc::<CHUNK, REDUCE>(&a.0, b, &mut c.0);
106    }
107
108    #[inline(always)]
109    pub fn sub_inplace<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &mut Poly<u64>) {
110        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
111        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
112        self.modulus
113            .va_sub_vb_into_vb::<CHUNK, REDUCE>(&a.0, &mut b.0);
114    }
115
116    #[inline(always)]
117    pub fn sub<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &Poly<u64>, c: &mut Poly<u64>) {
118        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
119        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
120        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
121        self.modulus
122            .va_sub_vb_into_vc::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
123    }
124
125    #[inline(always)]
126    pub fn neg<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &mut Poly<u64>) {
127        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
128        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
129        self.modulus.va_neg_into_vb::<CHUNK, REDUCE>(&a.0, &mut b.0);
130    }
131
132    #[inline(always)]
133    pub fn neg_inplace<const REDUCE: REDUCEMOD>(&self, a: &mut Poly<u64>) {
134        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
135        self.modulus.va_neg_into_va::<CHUNK, REDUCE>(&mut a.0);
136    }
137
138    #[inline(always)]
139    pub fn mul_montgomery_external<const REDUCE: REDUCEMOD>(
140        &self,
141        a: &Poly<Montgomery<u64>>,
142        b: &Poly<u64>,
143        c: &mut Poly<u64>,
144    ) {
145        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
146        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
147        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
148        self.modulus
149            .va_mont_mul_vb_into_vc::<CHUNK, REDUCE>(&a.0, &b.0, &mut c.0);
150    }
151
152    #[inline(always)]
153    pub fn mul_montgomery_external_inplace<const REDUCE: REDUCEMOD>(
154        &self,
155        a: &Poly<Montgomery<u64>>,
156        b: &mut Poly<u64>,
157    ) {
158        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
159        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
160        self.modulus
161            .va_mont_mul_vb_into_vb::<CHUNK, REDUCE>(&a.0, &mut b.0);
162    }
163
164    #[inline(always)]
165    pub fn mul_scalar<const REDUCE: REDUCEMOD>(&self, a: &Poly<u64>, b: &u64, c: &mut Poly<u64>) {
166        debug_assert!(a.n() == self.n(), "b.n()={} != n={}", a.n(), self.n());
167        debug_assert!(c.n() == self.n(), "c.n()={} != n={}", c.n(), self.n());
168        self.modulus.sa_barrett_mul_vb_into_vc::<CHUNK, REDUCE>(
169            &self.modulus.barrett.prepare(*b),
170            &a.0,
171            &mut c.0,
172        );
173    }
174
175    #[inline(always)]
176    pub fn mul_scalar_inplace<const REDUCE: REDUCEMOD>(&self, a: &u64, b: &mut Poly<u64>) {
177        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
178        self.modulus.sa_barrett_mul_vb_into_vb::<CHUNK, REDUCE>(
179            &self
180                .modulus
181                .barrett
182                .prepare(self.modulus.barrett.reduce::<BARRETT>(a)),
183            &mut b.0,
184        );
185    }
186
187    #[inline(always)]
188    pub fn mul_scalar_barrett_inplace<const REDUCE: REDUCEMOD>(
189        &self,
190        a: &Barrett<u64>,
191        b: &mut Poly<u64>,
192    ) {
193        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
194        self.modulus
195            .sa_barrett_mul_vb_into_vb::<CHUNK, REDUCE>(a, &mut b.0);
196    }
197
198    #[inline(always)]
199    pub fn mul_scalar_barrett<const REDUCE: REDUCEMOD>(
200        &self,
201        a: &Barrett<u64>,
202        b: &Poly<u64>,
203        c: &mut Poly<u64>,
204    ) {
205        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
206        self.modulus
207            .sa_barrett_mul_vb_into_vc::<CHUNK, REDUCE>(a, &b.0, &mut c.0);
208    }
209
210    #[inline(always)]
211    pub fn sum_aqqmb_prod_c_scalar_barrett<const REDUCE: REDUCEMOD>(
212        &self,
213        a: &Poly<u64>,
214        b: &Poly<u64>,
215        c: &Barrett<u64>,
216        d: &mut Poly<u64>,
217    ) {
218        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
219        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
220        debug_assert!(d.n() == self.n(), "d.n()={} != n={}", d.n(), self.n());
221        self.modulus
222            .va_sub_vb_mul_sc_into_vd::<CHUNK, REDUCE>(&a.0, &b.0, c, &mut d.0);
223    }
224
225    #[inline(always)]
226    pub fn sum_aqqmb_prod_c_scalar_barrett_inplace<const REDUCE: REDUCEMOD>(
227        &self,
228        a: &Poly<u64>,
229        c: &Barrett<u64>,
230        b: &mut Poly<u64>,
231    ) {
232        debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
233        debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
234        self.modulus
235            .va_sub_vb_mul_sc_into_vb::<CHUNK, REDUCE>(&a.0, c, &mut b.0);
236    }
237}