use poulpy_hal::{ api::{ ScratchTakeBasic, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigSubSmallInplace, VecZnxBigSubSmallNegateInplace, VecZnxNormalize, }, layouts::{Backend, DataMut, Module, Scratch, VecZnxBig}, }; use crate::{ GLWEKeySwitchInternal, GLWEKeyswitch, ScratchTakeCore, layouts::{GGLWEInfos, GGLWEPreparedToRef, GLWE, GLWEInfos, GLWEToMut, GLWEToRef, GetGaloisElement, LWEInfos}, }; impl GLWE> { pub fn automorphism_tmp_bytes(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize where R: GLWEInfos, A: GLWEInfos, K: GGLWEInfos, M: GLWEAutomorphism, { module.glwe_automorphism_tmp_bytes(res_infos, a_infos, key_infos) } } impl GLWE { pub fn automorphism(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism(self, a, key, scratch); } pub fn automorphism_add(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism_add(self, a, key, scratch); } pub fn automorphism_sub(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism_sub(self, a, key, scratch); } pub fn automorphism_sub_negate(&mut self, module: &M, a: &A, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism_sub_negate(self, a, key, scratch); } pub fn automorphism_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism_inplace(self, key, scratch); } pub fn automorphism_add_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism_add_inplace(self, key, scratch); } pub fn automorphism_sub_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism_sub_inplace(self, key, scratch); } pub fn automorphism_sub_negate_inplace(&mut self, module: &M, key: &K, scratch: &mut Scratch) where M: GLWEAutomorphism, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { module.glwe_automorphism_sub_negate_inplace(self, key, scratch); } } pub trait GLWEAutomorphism { fn glwe_automorphism_tmp_bytes(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize where R: GLWEInfos, A: GLWEInfos, K: GGLWEInfos; fn glwe_automorphism(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) where R: GLWEToMut, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; fn glwe_automorphism_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) where R: GLWEToMut, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; fn glwe_automorphism_add(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) where R: GLWEToMut, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; fn glwe_automorphism_add_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) where R: GLWEToMut, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; fn glwe_automorphism_sub(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) where R: GLWEToMut, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; fn glwe_automorphism_sub_negate(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch) where R: GLWEToMut, A: GLWEToRef, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; fn glwe_automorphism_sub_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) where R: GLWEToMut, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; fn glwe_automorphism_sub_negate_inplace(&self, res: &mut R, key: &K, scratch: &mut Scratch) where R: GLWEToMut, K: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos; } impl GLWEAutomorphism for Module where Self: Sized + GLWEKeyswitch + GLWEKeySwitchInternal + VecZnxNormalize + VecZnxAutomorphismInplace + VecZnxBigAutomorphismInplace + VecZnxBigSubSmallInplace + VecZnxBigSubSmallNegateInplace + VecZnxBigAddSmallInplace + VecZnxBigNormalize, Scratch: ScratchTakeCore, { 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { self.glwe_keyswitch(res, a, 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { self.glwe_keyswitch_inplace(res, 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); let a: &GLWE<&[u8]> = &a.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> = self.glwe_keyswitch_internal(res_dft, a, 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); 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> = self.glwe_keyswitch_internal(res_dft, res, 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); let a: &GLWE<&[u8]> = &a.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> = self.glwe_keyswitch_internal(res_dft, a, 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); let a: &GLWE<&[u8]> = &a.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> = self.glwe_keyswitch_internal(res_dft, a, 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); 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> = self.glwe_keyswitch_internal(res_dft, res, 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: GetGaloisElement + GGLWEPreparedToRef + GGLWEInfos, Scratch: ScratchTakeCore, { let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); 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> = self.glwe_keyswitch_internal(res_dft, res, 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, ); } } }