From 3236e1be2c6e2321f3e0b01da733cc454b3d4975 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bossuat Date: Thu, 16 Oct 2025 10:08:52 +0200 Subject: [PATCH] automorphism glwe --- poulpy-core/src/automorphism/glwe_ct.rs | 602 +++++++++++------------ poulpy-core/src/keyswitching/gglwe_ct.rs | 6 +- poulpy-core/src/keyswitching/ggsw_ct.rs | 6 +- poulpy-core/src/keyswitching/glwe_ct.rs | 12 +- poulpy-core/src/keyswitching/lwe_ct.rs | 4 +- poulpy-core/src/keyswitching/mod.rs | 5 + poulpy-core/src/lib.rs | 1 + 7 files changed, 313 insertions(+), 323 deletions(-) diff --git a/poulpy-core/src/automorphism/glwe_ct.rs b/poulpy-core/src/automorphism/glwe_ct.rs index 0c8b581..d989891 100644 --- a/poulpy-core/src/automorphism/glwe_ct.rs +++ b/poulpy-core/src/automorphism/glwe_ct.rs @@ -1,345 +1,331 @@ use poulpy_hal::{ api::{ - ScratchAvailable, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, - VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallInplace, VecZnxBigSubSmallNegateInplace, VecZnxDftApply, VecZnxDftBytesOf, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, + ScratchTakeBasic, VecZnxAutomorphismInplace, VecZnxBigAutomorphismInplace, VecZnxBigSubSmallInplace, + VecZnxBigSubSmallNegateInplace, }, - layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig}, + layouts::{Backend, DataMut, Module, Scratch, VecZnxBig}, }; -use crate::layouts::{GGLWEInfos, GLWE, GLWEInfos, LWEInfos, prepared::AutomorphismKeyPrepared}; +use crate::{ + GLWEKeyswitch, ScratchTakeCore, keyswitch_internal, + layouts::{ + GGLWEInfos, GLWE, GLWEInfos, GLWEToMut, GLWEToRef, LWEInfos, + prepared::{AutomorphismKeyPrepared, AutomorphismKeyPreparedToRef, GetAutomorphismGaloisElement}, + }, +}; impl GLWE> { - pub fn automorphism_tmp_bytes( - module: &Module, - out_infos: &OUT, - in_infos: &IN, - key_infos: &KEY, - ) -> usize + pub fn automorphism_tmp_bytes(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize where - OUT: GLWEInfos, - IN: GLWEInfos, - KEY: GGLWEInfos, - Module: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + R: GLWEInfos, + A: GLWEInfos, + K: GGLWEInfos, + M: GLWEAutomorphism, { - Self::keyswitch_tmp_bytes(module, out_infos, in_infos, key_infos) - } - - pub fn automorphism_inplace_tmp_bytes(module: &Module, out_infos: &OUT, key_infos: &KEY) -> usize - where - OUT: GLWEInfos, - KEY: GGLWEInfos, - Module: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, - { - Self::keyswitch_inplace_tmp_bytes(module, out_infos, key_infos) + module.glwe_automorphism_tmp_bytes(res_infos, a_infos, key_infos) } } impl GLWE { - pub fn automorphism( - &mut self, - module: &Module, - lhs: &GLWE, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxAutomorphismInplace - + VecZnxNormalize - + VecZnxNormalizeTmpBytes, - Scratch: ScratchAvailable, + pub fn automorphism(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - self.keyswitch(module, lhs, &rhs.key, scratch); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_automorphism_inplace(rhs.p(), &mut self.data, i, scratch); - }) + module.glwe_automorphism(self, a, key, scratch); } - pub fn automorphism_inplace( - &mut self, - module: &Module, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxAutomorphismInplace - + VecZnxNormalize - + VecZnxNormalizeTmpBytes, - Scratch: ScratchAvailable, + pub fn automorphism_add(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - self.keyswitch_inplace(module, &rhs.key, scratch); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_automorphism_inplace(rhs.p(), &mut self.data, i, scratch); - }) + module.glwe_automorphism_add(self, a, key, scratch); } - pub fn automorphism_add( - &mut self, - module: &Module, - lhs: &GLWE, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxBigAutomorphismInplace - + VecZnxNormalizeTmpBytes - + VecZnxNormalize, - Scratch: ScratchAvailable, + pub fn automorphism_sub(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - #[cfg(debug_assertions)] - { - self.assert_keyswitch(module, lhs, &rhs.key, scratch); - } - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = lhs.keyswitch_internal(module, res_dft, &rhs.key, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i, scratch_1); - module.vec_znx_big_add_small_inplace(&mut res_big, i, &lhs.data, i); - module.vec_znx_big_normalize( - self.base2k().into(), - &mut self.data, - i, - rhs.base2k().into(), - &res_big, - i, - scratch_1, - ); - }) + module.glwe_automorphism_sub(self, a, key, scratch); } - pub fn automorphism_add_inplace( - &mut self, - module: &Module, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxBigAutomorphismInplace - + VecZnxNormalizeTmpBytes - + VecZnxNormalize, - Scratch: ScratchAvailable, + pub fn glwe_automorphism_sub_negate(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - #[cfg(debug_assertions)] - { - self.assert_keyswitch_inplace(module, &rhs.key, scratch); - } - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = self.keyswitch_internal(module, res_dft, &rhs.key, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i, scratch_1); - module.vec_znx_big_add_small_inplace(&mut res_big, i, &self.data, i); - module.vec_znx_big_normalize( - self.base2k().into(), - &mut self.data, - i, - rhs.base2k().into(), - &res_big, - i, - scratch_1, - ); - }) + module.glwe_automorphism_sub_negate(self, a, key, scratch); } - pub fn automorphism_sub_ab( - &mut self, - module: &Module, - lhs: &GLWE, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxBigAutomorphismInplace - + VecZnxBigSubSmallInplace - + VecZnxNormalizeTmpBytes - + VecZnxNormalize, - Scratch: ScratchAvailable, + pub fn automorphism_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - #[cfg(debug_assertions)] - { - self.assert_keyswitch(module, lhs, &rhs.key, scratch); - } - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = lhs.keyswitch_internal(module, res_dft, &rhs.key, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i, scratch_1); - module.vec_znx_big_sub_small_inplace(&mut res_big, i, &lhs.data, i); - module.vec_znx_big_normalize( - self.base2k().into(), - &mut self.data, - i, - rhs.base2k().into(), - &res_big, - i, - scratch_1, - ); - }) + module.glwe_automorphism_inplace(self, key, scratch); } - pub fn automorphism_sub_inplace( - &mut self, - module: &Module, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxBigAutomorphismInplace - + VecZnxBigSubSmallInplace - + VecZnxNormalizeTmpBytes - + VecZnxNormalize, - Scratch: ScratchAvailable, + pub fn automorphism_add_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - #[cfg(debug_assertions)] - { - self.assert_keyswitch_inplace(module, &rhs.key, scratch); - } - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = self.keyswitch_internal(module, res_dft, &rhs.key, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i, scratch_1); - module.vec_znx_big_sub_small_inplace(&mut res_big, i, &self.data, i); - module.vec_znx_big_normalize( - self.base2k().into(), - &mut self.data, - i, - rhs.base2k().into(), - &res_big, - i, - scratch_1, - ); - }) + module.glwe_automorphism_add_inplace(self, key, scratch); } - pub fn automorphism_sub_negate( - &mut self, - module: &Module, - lhs: &GLWE, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxBigAutomorphismInplace - + VecZnxBigSubSmallNegateInplace - + VecZnxNormalizeTmpBytes - + VecZnxNormalize, - Scratch: ScratchAvailable, + pub fn automorphism_sub_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - #[cfg(debug_assertions)] - { - self.assert_keyswitch(module, lhs, &rhs.key, scratch); - } - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = lhs.keyswitch_internal(module, res_dft, &rhs.key, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i, scratch_1); - module.vec_znx_big_sub_small_negate_inplace(&mut res_big, i, &lhs.data, i); - module.vec_znx_big_normalize( - self.base2k().into(), - &mut self.data, - i, - rhs.base2k().into(), - &res_big, - i, - scratch_1, - ); - }) + module.glwe_automorphism_sub_inplace(self, key, scratch); } - pub fn automorphism_sub_negate_inplace( - &mut self, - module: &Module, - rhs: &AutomorphismKeyPrepared, - scratch: &mut Scratch, - ) where - Module: VecZnxDftBytesOf - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft - + VmpApplyDftToDftAdd - + VecZnxDftApply - + VecZnxIdftApplyConsume - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxBigAutomorphismInplace - + VecZnxBigSubSmallNegateInplace - + VecZnxNormalizeTmpBytes - + VecZnxNormalize, - Scratch: ScratchAvailable, + pub fn automorphism_sub_negate_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) + where + M: GLWEAutomorphism, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, { - #[cfg(debug_assertions)] - { - self.assert_keyswitch_inplace(module, &rhs.key, scratch); - } - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // TODO: optimise size - let mut res_big: VecZnxBig<_, B> = self.keyswitch_internal(module, res_dft, &rhs.key, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_automorphism_inplace(rhs.p(), &mut res_big, i, scratch_1); - module.vec_znx_big_sub_small_negate_inplace(&mut res_big, i, &self.data, i); - module.vec_znx_big_normalize( - self.base2k().into(), - &mut self.data, - i, - rhs.base2k().into(), - &res_big, - i, - scratch_1, - ); - }) + module.glwe_automorphism_sub_negate_inplace(self, key, scratch); } } + +pub trait GLWEAutomorphism +where + Self: GLWEKeyswitch + + VecZnxAutomorphismInplace + + VecZnxBigAutomorphismInplace + + VecZnxBigSubSmallInplace + + VecZnxBigSubSmallNegateInplace, +{ + fn glwe_automorphism_tmp_bytes(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize + where + R: GLWEInfos, + A: GLWEInfos, + K: GGLWEInfos, + { + self.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos) + } + + fn glwe_automorphism(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + self.glwe_keyswitch(res, a, &key.to_ref().key, scratch); + + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_automorphism_inplace(key.p(), res.data_mut(), i, scratch); + } + } + + fn glwe_automorphism_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + self.glwe_keyswitch_inplace(res, &key.to_ref().key, scratch); + + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_automorphism_inplace(key.p(), res.data_mut(), i, scratch); + } + } + + fn glwe_automorphism_add(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GLWE<&[u8]> = &a.to_ref(); + let key: &AutomorphismKeyPrepared<&[u8], BE> = &key.to_ref(); + + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), key.size()); // TODO: optimise size + let mut res_big: VecZnxBig<_, BE> = keyswitch_internal(self, res_dft, a, &key.key, scratch_1); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_big_automorphism_inplace(key.p(), &mut res_big, i, scratch_1); + self.vec_znx_big_add_small_inplace(&mut res_big, i, a.data(), i); + self.vec_znx_big_normalize( + res.base2k().into(), + res.data_mut(), + i, + key.base2k().into(), + &res_big, + i, + scratch_1, + ); + } + } + + fn glwe_automorphism_add_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let key: &AutomorphismKeyPrepared<&[u8], BE> = &key.to_ref(); + + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), key.size()); // TODO: optimise size + let mut res_big: VecZnxBig<_, BE> = keyswitch_internal(self, res_dft, res, &key.key, scratch_1); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_big_automorphism_inplace(key.p(), &mut res_big, i, scratch_1); + self.vec_znx_big_add_small_inplace(&mut res_big, i, res.data(), i); + self.vec_znx_big_normalize( + res.base2k().into(), + res.data_mut(), + i, + key.base2k().into(), + &res_big, + i, + scratch_1, + ); + } + } + + fn glwe_automorphism_sub(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GLWE<&[u8]> = &a.to_ref(); + let key: &AutomorphismKeyPrepared<&[u8], BE> = &key.to_ref(); + + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), key.size()); // TODO: optimise size + let mut res_big: VecZnxBig<_, BE> = keyswitch_internal(self, res_dft, a, &key.key, scratch_1); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_big_automorphism_inplace(key.p(), &mut res_big, i, scratch_1); + self.vec_znx_big_sub_small_inplace(&mut res_big, i, a.data(), i); + self.vec_znx_big_normalize( + res.base2k().into(), + res.data_mut(), + i, + key.base2k().into(), + &res_big, + i, + scratch_1, + ); + } + } + + fn glwe_automorphism_sub_negate(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + A: GLWEToRef, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GLWE<&[u8]> = &a.to_ref(); + let key: &AutomorphismKeyPrepared<&[u8], BE> = &key.to_ref(); + + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), key.size()); // TODO: optimise size + let mut res_big: VecZnxBig<_, BE> = keyswitch_internal(self, res_dft, a, &key.key, scratch_1); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_big_automorphism_inplace(key.p(), &mut res_big, i, scratch_1); + self.vec_znx_big_sub_small_negate_inplace(&mut res_big, i, a.data(), i); + self.vec_znx_big_normalize( + res.base2k().into(), + res.data_mut(), + i, + key.base2k().into(), + &res_big, + i, + scratch_1, + ); + } + } + + fn glwe_automorphism_sub_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let key: &AutomorphismKeyPrepared<&[u8], BE> = &key.to_ref(); + + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), key.size()); // TODO: optimise size + let mut res_big: VecZnxBig<_, BE> = keyswitch_internal(self, res_dft, res, &key.key, scratch_1); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_big_automorphism_inplace(key.p(), &mut res_big, i, scratch_1); + self.vec_znx_big_sub_small_inplace(&mut res_big, i, res.data(), i); + self.vec_znx_big_normalize( + res.base2k().into(), + res.data_mut(), + i, + key.base2k().into(), + &res_big, + i, + scratch_1, + ); + } + } + + fn glwe_automorphism_sub_negate_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) + where + R: GLWEToMut, + K: AutomorphismKeyPreparedToRef + GetAutomorphismGaloisElement, + Scratch: ScratchTakeCore, + { + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let key: &AutomorphismKeyPrepared<&[u8], BE> = &key.to_ref(); + + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), key.size()); // TODO: optimise size + let mut res_big: VecZnxBig<_, BE> = keyswitch_internal(self, res_dft, res, &key.key, scratch_1); + + for i in 0..res.rank().as_usize() + 1 { + self.vec_znx_big_automorphism_inplace(key.p(), &mut res_big, i, scratch_1); + self.vec_znx_big_sub_small_negate_inplace(&mut res_big, i, res.data(), i); + self.vec_znx_big_normalize( + res.base2k().into(), + res.data_mut(), + i, + key.base2k().into(), + &res_big, + i, + scratch_1, + ); + } + } +} + +impl GLWEAutomorphism for Module where + Self: GLWEKeyswitch + + VecZnxAutomorphismInplace + + VecZnxBigAutomorphismInplace + + VecZnxBigSubSmallInplace + + VecZnxBigSubSmallNegateInplace +{ +} diff --git a/poulpy-core/src/keyswitching/gglwe_ct.rs b/poulpy-core/src/keyswitching/gglwe_ct.rs index edda267..363f394 100644 --- a/poulpy-core/src/keyswitching/gglwe_ct.rs +++ b/poulpy-core/src/keyswitching/gglwe_ct.rs @@ -2,7 +2,7 @@ use poulpy_hal::layouts::{Backend, DataMut, Module, Scratch}; use crate::{ ScratchTakeCore, - keyswitching::glwe_ct::GLWEKeySwitch, + keyswitching::glwe_ct::GLWEKeyswitch, layouts::{ AutomorphismKey, AutomorphismKeyToRef, GGLWE, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWESwitchingKey, GLWESwitchingKeyToRef, @@ -109,11 +109,11 @@ impl GGLWE { } } -impl GGLWEKeySwitch for Module where Self: GLWEKeySwitch {} +impl GGLWEKeySwitch for Module where Self: GLWEKeyswitch {} pub trait GGLWEKeySwitch where - Self: GLWEKeySwitch, + Self: GLWEKeyswitch, { fn gglwe_keyswitch_tmp_bytes(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize where diff --git a/poulpy-core/src/keyswitching/ggsw_ct.rs b/poulpy-core/src/keyswitching/ggsw_ct.rs index cfb4d8e..c864975 100644 --- a/poulpy-core/src/keyswitching/ggsw_ct.rs +++ b/poulpy-core/src/keyswitching/ggsw_ct.rs @@ -2,7 +2,7 @@ use poulpy_hal::layouts::{Backend, DataMut, Scratch, VecZnx}; use crate::{ GGSWExpandRows, ScratchTakeCore, - keyswitching::glwe_ct::GLWEKeySwitch, + keyswitching::glwe_ct::GLWEKeyswitch, layouts::{ GGLWEInfos, GGSW, GGSWInfos, GGSWToMut, GGSWToRef, prepared::{GLWESwitchingKeyPreparedToRef, TensorKeyPreparedToRef}, @@ -53,7 +53,7 @@ impl GGSW { pub trait GGSWKeySwitch where - Self: GLWEKeySwitch + GGSWExpandRows, + Self: GLWEKeyswitch + GGSWExpandRows, { fn ggsw_keyswitch_tmp_bytes(&self, res_infos: &R, a_infos: &A, key_infos: &K, tsk_infos: &T) -> usize where @@ -127,5 +127,3 @@ where self.ggsw_expand_row(res, tsk, scratch); } } - -impl GGSW {} diff --git a/poulpy-core/src/keyswitching/glwe_ct.rs b/poulpy-core/src/keyswitching/glwe_ct.rs index 6d7bff9..de48cbf 100644 --- a/poulpy-core/src/keyswitching/glwe_ct.rs +++ b/poulpy-core/src/keyswitching/glwe_ct.rs @@ -21,7 +21,7 @@ impl GLWE> { R: GLWEInfos, A: GLWEInfos, B: GGLWEInfos, - M: GLWEKeySwitch, + M: GLWEKeyswitch, { module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, b_infos) } @@ -32,7 +32,7 @@ impl GLWE { where A: GLWEToRef, B: GLWESwitchingKeyPreparedToRef, - M: GLWEKeySwitch, + M: GLWEKeyswitch, Scratch: ScratchTakeCore, { module.glwe_keyswitch(self, a, b, scratch); @@ -41,14 +41,14 @@ impl GLWE { pub fn keyswitch_inplace(&mut self, module: &M, a: &A, scratch: &mut Scratch) where A: GLWESwitchingKeyPreparedToRef, - M: GLWEKeySwitch, + M: GLWEKeyswitch, Scratch: ScratchTakeCore, { module.glwe_keyswitch_inplace(self, a, scratch); } } -impl GLWEKeySwitch for Module where +impl GLWEKeyswitch for Module where Self: Sized + ModuleN + VecZnxDftBytesOf @@ -69,7 +69,7 @@ impl GLWEKeySwitch for Module where { } -pub trait GLWEKeySwitch +pub trait GLWEKeyswitch where Self: Sized + ModuleN @@ -239,7 +239,7 @@ impl GLWE> {} impl GLWE {} -fn keyswitch_internal( +pub(crate) fn keyswitch_internal( module: &M, mut res: VecZnxDft, a: &GLWE, diff --git a/poulpy-core/src/keyswitching/lwe_ct.rs b/poulpy-core/src/keyswitching/lwe_ct.rs index 8546ccb..ff9fb5f 100644 --- a/poulpy-core/src/keyswitching/lwe_ct.rs +++ b/poulpy-core/src/keyswitching/lwe_ct.rs @@ -5,7 +5,7 @@ use poulpy_hal::{ use crate::{ ScratchTakeCore, - keyswitching::glwe_ct::GLWEKeySwitch, + keyswitching::glwe_ct::GLWEKeyswitch, layouts::{ GGLWEInfos, GLWE, GLWEAlloc, GLWELayout, LWE, LWEInfos, LWEToMut, LWEToRef, Rank, TorusPrecision, prepared::{LWESwitchingKeyPrepared, LWESwitchingKeyPreparedToRef}, @@ -40,7 +40,7 @@ impl LWEKeySwitch for Module where Self: LWEKeySwitch { pub trait LWEKeySwitch where - Self: GLWEKeySwitch + GLWEAlloc, + Self: GLWEKeyswitch + GLWEAlloc, { fn lwe_keyswitch_tmp_bytes(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize where diff --git a/poulpy-core/src/keyswitching/mod.rs b/poulpy-core/src/keyswitching/mod.rs index c6a3610..b23fd47 100644 --- a/poulpy-core/src/keyswitching/mod.rs +++ b/poulpy-core/src/keyswitching/mod.rs @@ -2,3 +2,8 @@ mod gglwe_ct; mod ggsw_ct; mod glwe_ct; mod lwe_ct; + +pub use gglwe_ct::*; +pub use gglwe_ct::*; +pub use glwe_ct::*; +pub use lwe_ct::*; diff --git a/poulpy-core/src/lib.rs b/poulpy-core/src/lib.rs index 15e6c76..ffa36a8 100644 --- a/poulpy-core/src/lib.rs +++ b/poulpy-core/src/lib.rs @@ -18,6 +18,7 @@ pub use conversion::*; pub use dist::*; pub use external_product::*; pub use glwe_packing::*; +pub use keyswitching::*; pub use encryption::SIGMA;