mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
wip
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
use crate::ring::RingRNS;
|
||||
use crate::poly::PolyRNS;
|
||||
use crate::poly::{Poly, PolyRNS};
|
||||
use crate::modulus::barrett::Barrett;
|
||||
use crate::modulus::ONCE;
|
||||
extern crate test;
|
||||
|
||||
impl RingRNS<'_, u64>{
|
||||
|
||||
/// Updates b to floor(b / q[b.level()]).
|
||||
/// Updates b to floor(a / q[b.level()]).
|
||||
/// Expects a and b to be in the NTT domain.
|
||||
pub fn div_floor_by_last_modulus_ntt(&self, a: &PolyRNS<u64>, buf: &mut PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||
assert!(b.level() >= a.level()-1, "invalid input b: b.level()={} < a.level()-1={}", b.level(), a.level()-1);
|
||||
@@ -21,6 +21,19 @@ impl RingRNS<'_, u64>{
|
||||
}
|
||||
|
||||
/// Updates b to floor(b / q[b.level()]).
|
||||
/// Expects b to be in the NTT domain.
|
||||
pub fn div_floor_by_last_modulus_ntt_inplace(&self, buf: &mut PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||
let level = self.level();
|
||||
self.0[level].intt::<true>(b.at(level), buf.at_mut(0));
|
||||
let rescaling_constants: Vec<Barrett<u64>> = self.rescaling_constant();
|
||||
let (buf_ntt_q_scaling, buf_ntt_qi_scaling) = buf.0.split_at_mut(1);
|
||||
for (i, r) in self.0[0..level].iter().enumerate(){
|
||||
r.ntt::<true>(&buf_ntt_q_scaling[0], &mut buf_ntt_qi_scaling[0]);
|
||||
r.sum_aqqmb_prod_c_scalar_barrett_inplace::<ONCE>(&buf_ntt_qi_scaling[0], &rescaling_constants[i], b.at_mut(i));
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates b to floor(a / q[b.level()]).
|
||||
pub fn div_floor_by_last_modulus(&self, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||
assert!(b.level() >= a.level()-1, "invalid input b: b.level()={} < a.level()-1={}", b.level(), a.level()-1);
|
||||
let level = self.level();
|
||||
@@ -29,6 +42,35 @@ impl RingRNS<'_, u64>{
|
||||
r.sum_aqqmb_prod_c_scalar_barrett::<ONCE>(a.at(level), a.at(i), &rescaling_constants[i], b.at_mut(i));
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates a to floor(b / q[b.level()]).
|
||||
pub fn div_floor_by_last_modulus_inplace(&self, a: &mut PolyRNS<u64>){
|
||||
let level = self.level();
|
||||
let rescaling_constants: Vec<Barrett<u64>> = self.rescaling_constant();
|
||||
let (a_i, a_level) = a.split_at_mut(level);
|
||||
for (i, r) in self.0[0..level].iter().enumerate(){
|
||||
r.sum_aqqmb_prod_c_scalar_barrett_inplace::<ONCE>(&a_level[0], &rescaling_constants[i], &mut a_i[i]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn div_floor_by_last_moduli(&self, nb_moduli:usize, a: &PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||
if nb_moduli == 0{
|
||||
if a != b{
|
||||
b.copy(a);
|
||||
}
|
||||
}else{
|
||||
self.div_floor_by_last_modulus(a, b);
|
||||
(1..nb_moduli).for_each(|i|{self.at_level(self.level()-i).div_floor_by_last_modulus_inplace(b)});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn div_floor_by_last_moduli_inplace(&self, nb_moduli:usize, a: &mut PolyRNS<u64>){
|
||||
(0..nb_moduli).for_each(|i|{self.at_level(self.level()-i).div_floor_by_last_modulus_inplace(a)});
|
||||
}
|
||||
|
||||
pub fn div_round_by_last_modulus_ntt(&self, a: &PolyRNS<u64>, buf: &mut PolyRNS<u64>, b: &mut PolyRNS<u64>){
|
||||
let level = self.level();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -139,4 +139,11 @@ impl Ring<u64>{
|
||||
debug_assert!(d.n() == self.n(), "d.n()={} != n={}", d.n(), self.n());
|
||||
self.modulus.vec_sum_aqqmb_prod_c_scalar_barrett_assign_d::<CHUNK, REDUCE>(&a.0, &b.0, c, &mut d.0);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sum_aqqmb_prod_c_scalar_barrett_inplace<const REDUCE:REDUCEMOD>(&self, a: &Poly<u64>, c: &Barrett<u64>, b: &mut Poly<u64>){
|
||||
debug_assert!(a.n() == self.n(), "a.n()={} != n={}", a.n(), self.n());
|
||||
debug_assert!(b.n() == self.n(), "b.n()={} != n={}", b.n(), self.n());
|
||||
self.modulus.vec_sum_aqqmb_prod_c_scalar_barrett_assign_b::<CHUNK, REDUCE>(&a.0, c, &mut b.0);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,12 @@ impl<'a> RingRNS<'a, u64>{
|
||||
RingRNS(rings)
|
||||
}
|
||||
|
||||
pub fn modulus(&self) -> BigInt{
|
||||
let mut modulus = BigInt::from(1);
|
||||
self.0.iter().enumerate().for_each(|(_, r)|modulus *= BigInt::from(r.modulus.q));
|
||||
modulus
|
||||
}
|
||||
|
||||
pub fn rescaling_constant(&self) -> Vec<Barrett<u64>> {
|
||||
let level = self.level();
|
||||
let q_scale: u64 = self.0[level].modulus.q;
|
||||
@@ -30,6 +36,32 @@ impl<'a> RingRNS<'a, u64>{
|
||||
assert!(level <= a.level(), "invalid level: level={} > a.level()={}", level, a.level());
|
||||
(0..level).for_each(|i|{self.0[i].from_bigint(coeffs, step, a.at_mut(i))});
|
||||
}
|
||||
|
||||
pub fn set_bigint_from_poly(&self, a: &PolyRNS<u64>, step: usize, coeffs: &mut [BigInt]){
|
||||
assert!(step <= a.n(), "invalid step: step={} > a.n()={}", step, a.n());
|
||||
assert!(coeffs.len() <= a.n() / step, "invalid coeffs: coeffs.len()={} > a.n()/step={}", coeffs.len(), a.n()/step);
|
||||
|
||||
let mut inv_crt: Vec<BigInt> = vec![BigInt::default(); self.level()+1];
|
||||
let q_big: BigInt = self.modulus();
|
||||
let q_big_half: BigInt = &q_big>>1;
|
||||
|
||||
inv_crt.iter_mut().enumerate().for_each(|(i, a)|{
|
||||
let qi_big = BigInt::from(self.0[i].modulus.q);
|
||||
*a = (&q_big / &qi_big);
|
||||
*a *= a.modinv(&qi_big).unwrap();
|
||||
});
|
||||
|
||||
(0..self.n()).step_by(step).enumerate().for_each(|(i, j)|{
|
||||
coeffs[j] = BigInt::from(a.at(0).0[i]) * &inv_crt[0];
|
||||
(1..self.level()+1).for_each(|k|{
|
||||
coeffs[j] += BigInt::from(a.at(k).0[i] * &inv_crt[k]);
|
||||
});
|
||||
coeffs[j] %= &q_big;
|
||||
if &coeffs[j] >= &q_big_half{
|
||||
coeffs[j] -= &q_big;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl RingRNS<'_, u64>{
|
||||
|
||||
Reference in New Issue
Block a user