Fix #130 & #131 (#132) * fix #131 * fix #130 * update CHANGELOG.md
@@ -1,5 +1,10 @@
# CHANGELOG +## [0.4.3] - 2026-01-16 + +- Fix [#131](https://github.com/phantomzone-org/poulpy/issues/131) +- Fix [#130](https://github.com/phantomzone-org/poulpy/issues/130) + ## [0.4.2] - 2025-12-21 ## `poulpy-core`
@@ -7,8 +7,7 @@ layouts::{Backend, DataRef, DataViewMut, Module, Scratch},
}; use crate::layouts::{ - GLWE, GLWEInfos, GLWEPlaintext, GLWEPlaintextToMut, GLWEToRef, LWEInfos, - prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, + GLWE, GLWEInfos, GLWEPlaintextToMut, GLWESecretPrepared, GLWEToRef, LWEInfos, SetGLWEInfos, prepared::GLWESecretPreparedToRef, }; impl GLWE<Vec<u8>> {@@ -24,8 +23,8 @@
impl<DataSelf: DataRef> GLWE<DataSelf> { pub fn decrypt<P, S, M, BE: Backend>(&self, module: &M, pt: &mut P, sk: &S, scratch: &mut Scratch<BE>) where - P: GLWEPlaintextToMut, - S: GLWESecretPreparedToRef<BE>, + P: GLWEPlaintextToMut + GLWEInfos + SetGLWEInfos, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, M: GLWEDecrypt<BE>, Scratch<BE>: ScratchTakeBasic, {@@ -40,9 +39,9 @@ A: GLWEInfos;
fn glwe_decrypt<R, P, S>(&self, res: &R, pt: &mut P, sk: &S, scratch: &mut Scratch<BE>) where - R: GLWEToRef, - P: GLWEPlaintextToMut, - S: GLWESecretPreparedToRef<BE>; + R: GLWEToRef + GLWEInfos, + P: GLWEPlaintextToMut + GLWEInfos + SetGLWEInfos, + S: GLWESecretPreparedToRef<BE> + GLWEInfos; } impl<BE: Backend> GLWEDecrypt<BE> for Module<BE>@@ -69,17 +68,16 @@ }
fn glwe_decrypt<R, P, S>(&self, res: &R, pt: &mut P, sk: &S, scratch: &mut Scratch<BE>) where - R: GLWEToRef, - P: GLWEPlaintextToMut, - S: GLWESecretPreparedToRef<BE>, + R: GLWEToRef + GLWEInfos, + P: GLWEPlaintextToMut + GLWEInfos + SetGLWEInfos, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, { let res: &GLWE<&[u8]> = &res.to_ref(); - let pt: &mut GLWEPlaintext<&mut [u8]> = &mut pt.to_ref(); let sk: &GLWESecretPrepared<&[u8], BE> = &sk.to_ref(); #[cfg(debug_assertions)] { - assert_eq!(res.rank(), sk.rank()); + assert_eq!(res.rank(), sk.rank()); //NOTE: res.rank() != res.to_ref().rank() if res is of type GLWETensor assert_eq!(res.n(), sk.n()); assert_eq!(pt.n(), sk.n()); }@@ -89,28 +87,34 @@
let (mut c0_big, scratch_1) = scratch.take_vec_znx_big(self, 1, res.size()); // TODO optimize size when pt << ct c0_big.data_mut().fill(0); - { - (1..cols).for_each(|i| { - // ci_dft = DFT(a[i]) * DFT(s[i]) - let (mut ci_dft, _) = scratch_1.take_vec_znx_dft(self, 1, res.size()); // TODO optimize size when pt << ct - self.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, &res.data, i); - self.svp_apply_dft_to_dft_inplace(&mut ci_dft, 0, &sk.data, i - 1); - let ci_big = self.vec_znx_idft_apply_consume(ci_dft); + (1..cols).for_each(|i| { + // ci_dft = DFT(a[i]) * DFT(s[i]) + let (mut ci_dft, _) = scratch_1.take_vec_znx_dft(self, 1, res.size()); // TODO optimize size when pt << ct + self.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, res.data(), i); + self.svp_apply_dft_to_dft_inplace(&mut ci_dft, 0, &sk.data, i - 1); + let ci_big = self.vec_znx_idft_apply_consume(ci_dft); - // c0_big += a[i] * s[i] - self.vec_znx_big_add_inplace(&mut c0_big, 0, &ci_big, 0); - }); - } + // c0_big += a[i] * s[i] + self.vec_znx_big_add_inplace(&mut c0_big, 0, &ci_big, 0); + }); // c0_big = (a * s) + (-a * s + m + e) = BIG(m + e) - self.vec_znx_big_add_small_inplace(&mut c0_big, 0, &res.data, 0); + self.vec_znx_big_add_small_inplace(&mut c0_big, 0, res.data(), 0); - let res_base2k: usize = res.base2k().into(); + let pt_base2k: usize = pt.base2k().into(); // pt = norm(BIG(m + e)) - self.vec_znx_big_normalize(&mut pt.data, res_base2k, 0, 0, &c0_big, res_base2k, 0, scratch_1); + self.vec_znx_big_normalize( + pt.to_mut().data_mut(), + pt_base2k, + 0, + 0, + &c0_big, + res.base2k().into(), + 0, + scratch_1, + ); - pt.base2k = res.base2k(); - pt.k = pt.k().min(res.k()); + pt.set_k(pt.k().min(res.k())); } }
@@ -7,7 +7,7 @@
use crate::{ Distribution, GLWEEncryptSk, GetDistribution, GetDistributionMut, ScratchTakeCore, layouts::{ - GLWE, GLWEInfos, GLWEPublicKey, GLWEToMut, + GLWEInfos, GLWEPublicKey, GLWEToMut, prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, }, };@@ -52,10 +52,7 @@ }
// Its ok to allocate scratch space here since pk is usually generated only once. let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(self.glwe_encrypt_sk_tmp_bytes(res)); - - let mut tmp: GLWE<Vec<u8>> = GLWE::alloc_from_infos(res); - - tmp.encrypt_zero_sk(self, sk, source_xa, source_xe, scratch.borrow()); + res.to_mut().encrypt_zero_sk(self, sk, source_xa, source_xe, scratch.borrow()); } *res.dist_mut() = *sk.dist(); }
@@ -140,11 +140,11 @@ }
} pub trait GLWEPlaintextToMut { - fn to_ref(&mut self) -> GLWEPlaintext<&mut [u8]>; + fn to_mut(&mut self) -> GLWEPlaintext<&mut [u8]>; } impl<D: DataMut> GLWEPlaintextToMut for GLWEPlaintext<D> { - fn to_ref(&mut self) -> GLWEPlaintext<&mut [u8]> { + fn to_mut(&mut self) -> GLWEPlaintext<&mut [u8]> { GLWEPlaintext { base2k: self.base2k, k: self.k,
@@ -55,6 +55,7 @@ }
} impl<D: Data> GLWEInfos for GLWETensor<D> { + ///NOTE: self.rank() != self.to_ref().rank() if self is of type [GLWETensor] fn rank(&self) -> Rank { self.rank }
@@ -5,7 +5,7 @@ };
use crate::{ GLWENoise, - layouts::{GGLWE, GGLWEInfos, GGLWEToRef, prepared::GLWESecretPreparedToRef}, + layouts::{GGLWE, GGLWEInfos, GGLWEToRef, GLWEInfos, prepared::GLWESecretPreparedToRef}, }; use crate::{ScratchTakeCore, layouts::GLWEPlaintext};@@ -20,7 +20,7 @@ sk_prepared: &S,
scratch: &mut Scratch<BE>, ) -> Stats where - S: GLWESecretPreparedToRef<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, P: ScalarZnxToRef, M: GGLWENoise<BE>, {@@ -44,7 +44,7 @@ scratch: &mut Scratch<BE>,
) -> Stats where R: GGLWEToRef, - S: GLWESecretPreparedToRef<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, P: ScalarZnxToRef; }@@ -71,7 +71,7 @@ scratch: &mut Scratch<BE>,
) -> Stats where R: GGLWEToRef, - S: GLWESecretPreparedToRef<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, P: ScalarZnxToRef, { let res: &GGLWE<&[u8]> = &res.to_ref();
@@ -11,7 +11,7 @@ pub fn noise<M, P, S, BE: Backend>(&self, module: &M, pt_want: &P, sk_prepared: &S, scratch: &mut Scratch<BE>) -> Stats
where M: GLWENoise<BE>, P: GLWEToRef, - S: GLWESecretPreparedToRef<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, { module.glwe_noise(self, pt_want, sk_prepared, scratch) }@@ -26,7 +26,7 @@ fn glwe_noise<R, P, S>(&self, res: &R, pt_want: &P, sk_prepared: &S, scratch: &mut Scratch<BE>) -> Stats
where R: GLWEToRef + GLWEInfos, P: GLWEToRef, - S: GLWESecretPreparedToRef<BE>; + S: GLWESecretPreparedToRef<BE> + GLWEInfos; } impl<BE: Backend> GLWENoise<BE> for Module<BE>@@ -45,7 +45,7 @@ fn glwe_noise<R, P, S>(&self, res: &R, pt_want: &P, sk_prepared: &S, scratch: &mut Scratch<BE>) -> Stats
where R: GLWEToRef + GLWEInfos, P: GLWEToRef, - S: GLWESecretPreparedToRef<BE>, + S: GLWESecretPreparedToRef<BE> + GLWEInfos, { let (mut pt_have, scratch_1) = scratch.take_glwe_plaintext(res); self.glwe_decrypt(res, &mut pt_have, sk_prepared, scratch_1);