From 463731948de4a9a920e1889fbe479adcbab68199 Mon Sep 17 00:00:00 2001 From: Janmajaya Mall Date: Sun, 6 Jul 2025 12:40:08 +0530 Subject: [PATCH] Bug fixes - fixed `encoding.rs/decode_coeff_i64` for the case `k < basek2` - `glwe/external_product.rs/external_product_scratch_space` did not allocate enough space for [`a_dft`](https://github.com/phantomzone-org/poulpy/blob/829b8be610bb518765be3eb857e58ffe09683c2d/core/src/glwe/external_product.rs#L83) when `k_out < k_ggsw`. Fixed by replacing `in_size` with `ggsw_size`. - `glwe/ops.rs/add` sets `basek` and `k`of `self` GLWECiphertext whic is invalid because the `size` which depends on `inner` data remains unchanged. - (not a fix) expose `backend` from `core`. --- backend/src/encoding.rs | 10 +++++----- core/src/glwe/external_product.rs | 2 +- core/src/glwe/ops.rs | 5 +++-- core/src/lib.rs | 1 + 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/src/encoding.rs b/backend/src/encoding.rs index 55bba09..27d4b8c 100644 --- a/backend/src/encoding.rs +++ b/backend/src/encoding.rs @@ -269,12 +269,12 @@ fn decode_coeff_i64>(a: &VecZnx, col_i: usize, basek: usize, k let size: usize = (k + basek - 1) / basek; let data: &[i64] = a.raw(); - let mut res: i64 = data[i]; + let mut res: i64 = 0; let rem: usize = basek - (k % basek); let slice_size: usize = a.n() * a.cols(); - (0..size).for_each(|i| { - let x: i64 = data[i * slice_size]; - if i == size - 1 && rem != basek { + (0..size).for_each(|j| { + let x: i64 = data[j * slice_size + i]; + if j == size - 1 && rem != basek { let k_rem: usize = basek - rem; res = (res << k_rem) + (x >> rem); } else { @@ -320,7 +320,7 @@ mod tests { let module: Module = Module::::new(n); let basek: usize = 17; let size: usize = 5; - for k in [size * basek - 5] { + for k in [1, basek / 2, size * basek - 5] { let mut a: VecZnx<_> = module.new_vec_znx(2, size); let mut source = Source::new([0u8; 32]); let raw: &mut [i64] = a.raw_mut(); diff --git a/core/src/glwe/external_product.rs b/core/src/glwe/external_product.rs index 3ebf339..3f826f1 100644 --- a/core/src/glwe/external_product.rs +++ b/core/src/glwe/external_product.rs @@ -18,7 +18,7 @@ impl GLWECiphertext> { let in_size: usize = k_in.div_ceil(basek).div_ceil(digits); let out_size: usize = k_out.div_ceil(basek); let ggsw_size: usize = k_ggsw.div_ceil(basek); - let vmp: usize = module.bytes_of_vec_znx_dft(rank + 1, in_size) + let vmp: usize = module.bytes_of_vec_znx_dft(rank + 1, ggsw_size) + module.vmp_apply_tmp_bytes( out_size, in_size, diff --git a/core/src/glwe/ops.rs b/core/src/glwe/ops.rs index 2beffe6..d921583 100644 --- a/core/src/glwe/ops.rs +++ b/core/src/glwe/ops.rs @@ -14,6 +14,7 @@ pub trait GLWEOps: GLWECiphertextToMut + Infos + SetMetaData { assert_eq!(b.n(), module.n()); assert_eq!(self.n(), module.n()); assert_eq!(a.basek(), b.basek()); + assert_eq!(self.basek(), a.basek()); assert!(self.rank() >= a.rank().max(b.rank())); } @@ -46,8 +47,8 @@ pub trait GLWEOps: GLWECiphertextToMut + Infos + SetMetaData { }); }); - self.set_basek(a.basek()); - self.set_k(a.k().max(b.k())); + // self.set_basek(a.basek()); + // self.set_k(a.k().max(b.k())); } fn add_inplace(&mut self, module: &Module, a: &A) diff --git a/core/src/lib.rs b/core/src/lib.rs index ba28589..eb3cbce 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -19,6 +19,7 @@ pub use glwe::{GLWECiphertext, GLWEOps, GLWEPacker, GLWEPlaintext, GLWEPublicKey pub(crate) use glwe::{GLWECiphertextToMut, GLWECiphertextToRef}; pub use lwe::{LWECiphertext, LWESecret}; +pub use backend; pub use backend::Scratch; pub use backend::ScratchOwned;