fixed div_floor rns scaling
Jean-Philippe Bossuat jeanphilippe.bossuat@gmail.com
Mon, 06 Jan 2025 23:47:17 +0100
2 files changed,
50 insertions(+),
37 deletions(-)
M
math/src/ring/impl_u64/rescaling_rns.rs
→
math/src/ring/impl_u64/rescaling_rns.rs
@@ -14,6 +14,7 @@ a: &PolyRNS<u64>,
buf: &mut PolyRNS<u64>, b: &mut PolyRNS<u64>, ) { + debug_assert!(self.level() != 0, "invalid call: self.level()=0"); debug_assert!( self.level() <= a.level(), "invalid input a: self.level()={} > a.level()={}",@@ -21,10 +22,10 @@ self.level(),
a.level() ); debug_assert!( - b.level() >= a.level() - 1, - "invalid input b: b.level()={} < a.level()-1={}", + b.level() >= self.level() - 1, + "invalid input b: b.level()={} < self.level()-1={}", b.level(), - a.level() - 1 + self.level() - 1 ); let level = self.level();@@ -102,28 +103,31 @@ a: &PolyRNS<u64>,
buf: &mut PolyRNS<u64>, c: &mut PolyRNS<u64>, ) { - - println!("{:?}", buf); - + debug_assert!( + nb_moduli <= self.level(), + "invalid input nb_moduli: nb_moduli={} > a.level()={}", + nb_moduli, + a.level() + ); debug_assert!( - self.level() <= a.level(), + a.level() <= self.level(), "invalid input a: self.level()={} > a.level()={}", self.level(), a.level() ); debug_assert!( - c.level() >= a.level() - 1, - "invalid input b: b.level()={} < a.level()-1={}", - c.level(), + buf.level() >= self.level() - 1, + "invalid input buf: buf.level()={} < a.level()-1={}", + buf.level(), a.level() - 1 ); debug_assert!( - nb_moduli <= a.level(), - "invalid input nb_moduli: nb_moduli={} > a.level()={}", - nb_moduli, - a.level() + c.level() >= self.level() - nb_moduli, + "invalid input c: c.level()={} < c.level()-nb_moduli={}", + c.level(), + a.level() - nb_moduli ); - + if nb_moduli == 0 { if a != c { c.copy(a);@@ -140,11 +144,21 @@ )
}); self.at_level(self.level() - nb_moduli).ntt::<false>(buf, c); } else { - self.div_floor_by_last_modulus::<false>(a, buf, c); - (1..nb_moduli).for_each(|i| { + + let empty_buf: &mut PolyRNS<u64> = &mut PolyRNS::<u64>::default(); + + if nb_moduli == 1{ + self.div_floor_by_last_modulus::<false>(a, empty_buf, c); + }else{ + self.div_floor_by_last_modulus::<false>(a, empty_buf, buf); + } + + (1..nb_moduli-1).for_each(|i| { self.at_level(self.level() - i) - .div_floor_by_last_modulus_inplace::<false>(buf, c) + .div_floor_by_last_modulus_inplace::<false>(empty_buf, buf); }); + + self.at_level(self.level()-nb_moduli+1).div_floor_by_last_modulus::<false>(buf, empty_buf, c); } } }@@ -168,17 +182,20 @@ "invalid input nb_moduli: nb_moduli={} > a.level()={}",
nb_moduli, a.level() ); + if nb_moduli == 0{ + return + } if NTT { self.intt::<false>(a, buf); (0..nb_moduli).for_each(|i| { self.at_level(self.level() - i) .div_floor_by_last_modulus_inplace::<false>(&mut PolyRNS::<u64>::default(), buf) }); - self.at_level(self.level() - nb_moduli).ntt::<false>(buf, a); + self.at_level(self.level() - nb_moduli+1).ntt::<false>(buf, a); } else { (0..nb_moduli).for_each(|i| { self.at_level(self.level() - i) - .div_floor_by_last_modulus_inplace::<false>(buf, a) + .div_floor_by_last_modulus_inplace::<false>(buf, a); }); } }
M
math/tests/rescaling_rns.rs
→
math/tests/rescaling_rns.rs
@@ -10,14 +10,14 @@ let n = 1 << 10;
let moduli: Vec<u64> = vec![0x1fffffffffc80001u64, 0x1fffffffffe00001u64, 0x1fffffffffb40001, 0x1fffffffff500001]; let ring_rns: RingRNS<u64> = RingRNS::new(n, moduli); - //test_div_floor_by_last_modulus::<false>(&ring_rns); - //test_div_floor_by_last_modulus::<true>(&ring_rns); + test_div_floor_by_last_modulus::<false>(&ring_rns); + test_div_floor_by_last_modulus::<true>(&ring_rns); test_div_floor_by_last_modulus_inplace::<false>(&ring_rns); - //test_div_floor_by_last_modulus_inplace::<true>(&ring_rns); - //test_div_floor_by_last_moduli::<false>(&ring_rns); - //test_div_floor_by_last_moduli::<true>(&ring_rns); - //test_div_floor_by_last_moduli_inplace::<false>(&ring_rns); - //test_div_floor_by_last_moduli_inplace::<true>(&ring_rns); + test_div_floor_by_last_modulus_inplace::<true>(&ring_rns); + test_div_floor_by_last_moduli::<false>(&ring_rns); + test_div_floor_by_last_moduli::<true>(&ring_rns); + test_div_floor_by_last_moduli_inplace::<false>(&ring_rns); + test_div_floor_by_last_moduli_inplace::<true>(&ring_rns); } fn test_div_floor_by_last_modulus<const NTT: bool>(ring_rns: &RingRNS<u64>) {@@ -83,8 +83,6 @@ ring_rns
.at_level(a.level()) .to_bigint_inplace(&a, 1, &mut coeffs_a); - println!("{:?}", &coeffs_a[..8]); - // Performs c = intt(ntt(a) / q_level) if NTT { ring_rns.ntt_inplace::<false>(&mut a);@@ -112,9 +110,6 @@ *a -= 1;
} }); - println!("{:?}", &coeffs_a[..8]); - println!("{:?}", &coeffs_c[..8]); - assert!(coeffs_a == coeffs_c, "test_div_floor_by_last_modulus_inplace"); }@@ -122,11 +117,11 @@ fn test_div_floor_by_last_moduli<const NTT: bool>(ring_rns: &RingRNS<u64>) {
let seed: [u8; 32] = [0; 32]; let mut source: Source = Source::new(seed); - let nb_moduli: usize = ring_rns.level()-1; + let nb_moduli: usize = ring_rns.level(); let mut a: PolyRNS<u64> = ring_rns.new_polyrns(); let mut b: PolyRNS<u64> = ring_rns.new_polyrns(); - let mut c: PolyRNS<u64> = ring_rns.at_level(ring_rns.level() - 1).new_polyrns(); + let mut c: PolyRNS<u64> = ring_rns.at_level(ring_rns.level() - nb_moduli).new_polyrns(); // Allocates a random PolyRNS ring_rns.fill_uniform(&mut source, &mut a);@@ -156,7 +151,8 @@ .to_bigint_inplace(&c, 1, &mut coeffs_c);
// Performs floor division on a let mut scalar_big = BigInt::from(1); - (0..nb_moduli).for_each(|i|{scalar_big *= BigInt::from(ring_rns.0[ring_rns.level()].modulus.q)}); + (0..nb_moduli).for_each(|i|{scalar_big *= BigInt::from(ring_rns.0[ring_rns.level()-i].modulus.q)}); + coeffs_a.iter_mut().for_each(|a| { // Emulates floor division in [0, q-1] and maps to [-(q-1)/2, (q-1)/2-1] *a /= &scalar_big;@@ -172,7 +168,7 @@ fn test_div_floor_by_last_moduli_inplace<const NTT: bool>(ring_rns: &RingRNS<u64>) {
let seed: [u8; 32] = [0; 32]; let mut source: Source = Source::new(seed); - let nb_moduli: usize = ring_rns.level()-1; + let nb_moduli: usize = ring_rns.level(); let mut a: PolyRNS<u64> = ring_rns.new_polyrns(); let mut b: PolyRNS<u64> = ring_rns.new_polyrns();@@ -205,7 +201,7 @@ .to_bigint_inplace(&a, 1, &mut coeffs_c);
// Performs floor division on a let mut scalar_big = BigInt::from(1); - (0..nb_moduli).for_each(|i|{scalar_big *= BigInt::from(ring_rns.0[ring_rns.level()].modulus.q)}); + (0..nb_moduli).for_each(|i|{scalar_big *= BigInt::from(ring_rns.0[ring_rns.level()-i].modulus.q)}); coeffs_a.iter_mut().for_each(|a| { // Emulates floor division in [0, q-1] and maps to [-(q-1)/2, (q-1)/2-1] *a /= &scalar_big;