Distinguish between gglwe_to_ggsw key and tensor_key + update key repreentation

This commit is contained in:
Pro7ech
2025-10-27 11:28:53 +01:00
parent 41ca5aafcc
commit 8d4c19a304
59 changed files with 2812 additions and 1596 deletions

View File

@@ -1,11 +1,10 @@
use poulpy_hal::{
api::VecZnxAutomorphism,
layouts::{Backend, DataMut, GaloisElement, Module, Scratch},
api::{VecZnxAutomorphism, VecZnxAutomorphismInplace},
layouts::{Backend, CyclotomicOrder, DataMut, GaloisElement, Module, Scratch},
};
use crate::{
ScratchTakeCore,
automorphism::glwe_ct::GLWEAutomorphism,
GLWEKeyswitch, ScratchTakeCore,
layouts::{
GGLWE, GGLWEInfos, GGLWEPreparedToRef, GGLWEToMut, GGLWEToRef, GLWE, GLWEAutomorphismKey, GetGaloisElement,
SetGaloisElement,
@@ -45,14 +44,10 @@ impl<DataSelf: DataMut> GLWEAutomorphismKey<DataSelf> {
}
}
impl<BE: Backend> GLWEAutomorphismKeyAutomorphism<BE> for Module<BE> where
Self: GaloisElement + GLWEAutomorphism<BE> + VecZnxAutomorphism
{
}
pub trait GLWEAutomorphismKeyAutomorphism<BE: Backend>
impl<BE: Backend> GLWEAutomorphismKeyAutomorphism<BE> for Module<BE>
where
Self: GaloisElement + GLWEAutomorphism<BE> + VecZnxAutomorphism,
Self: GaloisElement + GLWEKeyswitch<BE> + VecZnxAutomorphism + VecZnxAutomorphismInplace<BE> + CyclotomicOrder,
Scratch<BE>: ScratchTakeCore<BE>,
{
fn glwe_automorphism_key_automorphism_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
where
@@ -68,7 +63,6 @@ where
R: GGLWEToMut + SetGaloisElement + GGLWEInfos,
A: GGLWEToRef + GetGaloisElement + GGLWEInfos,
K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos,
Scratch<BE>: ScratchTakeCore<BE>,
{
assert!(
res.dnum().as_u32() <= a.dnum().as_u32(),
@@ -163,3 +157,22 @@ where
res.set_p((res.p() * key.p()) % self.cyclotomic_order());
}
}
pub trait GLWEAutomorphismKeyAutomorphism<BE: Backend> {
fn glwe_automorphism_key_automorphism_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
where
R: GGLWEInfos,
A: GGLWEInfos,
K: GGLWEInfos;
fn glwe_automorphism_key_automorphism<R, A, K>(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch<BE>)
where
R: GGLWEToMut + SetGaloisElement + GGLWEInfos,
A: GGLWEToRef + GetGaloisElement + GGLWEInfos,
K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos;
fn glwe_automorphism_key_automorphism_inplace<R, K>(&self, res: &mut R, key: &K, scratch: &mut Scratch<BE>)
where
R: GGLWEToMut + SetGaloisElement + GetGaloisElement + GGLWEInfos,
K: GGLWEPreparedToRef<BE> + GetGaloisElement + GGLWEInfos;
}

View File

@@ -7,8 +7,8 @@ use crate::{
GGSWExpandRows, ScratchTakeCore,
automorphism::glwe_ct::GLWEAutomorphism,
layouts::{
GGLWEInfos, GGLWEPreparedToRef, GGSW, GGSWInfos, GGSWToMut, GGSWToRef, GetGaloisElement,
prepared::{GLWETensorKeyPrepared, GLWETensorKeyPreparedToRef},
GGLWEInfos, GGLWEPreparedToRef, GGLWEToGGSWKeyPrepared, GGLWEToGGSWKeyPreparedToRef, GGSW, GGSWInfos, GGSWToMut,
GGSWToRef, GetGaloisElement,
},
};
@@ -36,7 +36,7 @@ impl<D: DataMut> GGSW<D> {
where
A: GGSWToRef,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
T: GLWETensorKeyPreparedToRef<BE>,
T: GGLWEToGGSWKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
M: GGSWAutomorphism<BE>,
{
@@ -46,7 +46,7 @@ impl<D: DataMut> GGSW<D> {
pub fn automorphism_inplace<K, T, M, BE: Backend>(&mut self, module: &M, key: &K, tsk: &T, scratch: &mut Scratch<BE>)
where
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
T: GLWETensorKeyPreparedToRef<BE>,
T: GGLWEToGGSWKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
M: GGSWAutomorphism<BE>,
{
@@ -67,11 +67,8 @@ where
K: GGLWEInfos,
T: GGLWEInfos,
{
let out_size: usize = res_infos.size();
let ci_dft: usize = self.bytes_of_vec_znx_dft((key_infos.rank_out() + 1).into(), out_size);
let ks_internal: usize = self.glwe_automorphism_tmp_bytes(res_infos, a_infos, key_infos);
let expand: usize = self.ggsw_expand_rows_tmp_bytes(res_infos, tsk_infos);
ci_dft + (ks_internal.max(expand))
self.glwe_automorphism_tmp_bytes(res_infos, a_infos, key_infos)
.max(self.ggsw_expand_rows_tmp_bytes(res_infos, tsk_infos))
}
fn ggsw_automorphism<R, A, K, T>(&self, res: &mut R, a: &A, key: &K, tsk: &T, scratch: &mut Scratch<BE>)
@@ -79,12 +76,12 @@ where
R: GGSWToMut,
A: GGSWToRef,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
T: GLWETensorKeyPreparedToRef<BE>,
T: GGLWEToGGSWKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
{
let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
let a: &GGSW<&[u8]> = &a.to_ref();
let tsk: &GLWETensorKeyPrepared<&[u8], BE> = &tsk.to_ref();
let tsk: &GGLWEToGGSWKeyPrepared<&[u8], BE> = &tsk.to_ref();
assert_eq!(res.dsize(), a.dsize());
assert!(res.dnum() <= a.dnum());
@@ -104,11 +101,11 @@ where
where
R: GGSWToMut,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos,
T: GLWETensorKeyPreparedToRef<BE>,
T: GGLWEToGGSWKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
{
let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
let tsk: &GLWETensorKeyPrepared<&[u8], BE> = &tsk.to_ref();
let tsk: &GGLWEToGGSWKeyPrepared<&[u8], BE> = &tsk.to_ref();
// Keyswitch the j-th row of the col 0
for row in 0..res.dnum().as_usize() {

View File

@@ -1,13 +1,13 @@
use poulpy_hal::{
api::{
ScratchTakeBasic, VecZnxAutomorphismInplace, VecZnxBigAutomorphismInplace, VecZnxBigSubSmallInplace,
VecZnxBigSubSmallNegateInplace,
ScratchTakeBasic, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigNormalize,
VecZnxBigSubSmallInplace, VecZnxBigSubSmallNegateInplace, VecZnxNormalize,
},
layouts::{Backend, DataMut, Module, Scratch, VecZnxBig},
};
use crate::{
GLWEKeyswitch, ScratchTakeCore, keyswitch_internal,
GLWEKeySwitchInternal, GLWEKeyswitch, ScratchTakeCore,
layouts::{GGLWEInfos, GGLWEPreparedToRef, GLWE, GLWEInfos, GLWEToMut, GLWEToRef, GetGaloisElement, LWEInfos},
};
@@ -101,13 +101,71 @@ impl<DataSelf: DataMut> GLWE<DataSelf> {
}
}
pub trait GLWEAutomorphism<BE: Backend>
pub trait GLWEAutomorphism<BE: Backend> {
fn glwe_automorphism_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
where
R: GLWEInfos,
A: GLWEInfos,
K: GGLWEInfos;
fn glwe_automorphism<R, A, K>(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
A: GLWEToRef,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
fn glwe_automorphism_inplace<R, K>(&self, res: &mut R, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
fn glwe_automorphism_add<R, A, K>(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
A: GLWEToRef,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
fn glwe_automorphism_add_inplace<R, K>(&self, res: &mut R, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
fn glwe_automorphism_sub<R, A, K>(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
A: GLWEToRef,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
fn glwe_automorphism_sub_negate<R, A, K>(&self, res: &mut R, a: &A, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
A: GLWEToRef,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
fn glwe_automorphism_sub_inplace<R, K>(&self, res: &mut R, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
fn glwe_automorphism_sub_negate_inplace<R, K>(&self, res: &mut R, key: &K, scratch: &mut Scratch<BE>)
where
R: GLWEToMut,
K: GetGaloisElement + GGLWEPreparedToRef<BE> + GGLWEInfos;
}
impl<BE: Backend> GLWEAutomorphism<BE> for Module<BE>
where
Self: GLWEKeyswitch<BE>
Self: Sized
+ GLWEKeyswitch<BE>
+ GLWEKeySwitchInternal<BE>
+ VecZnxNormalize<BE>
+ VecZnxAutomorphismInplace<BE>
+ VecZnxBigAutomorphismInplace<BE>
+ VecZnxBigSubSmallInplace<BE>
+ VecZnxBigSubSmallNegateInplace<BE>,
+ VecZnxBigSubSmallNegateInplace<BE>
+ VecZnxBigAddSmallInplace<BE>
+ VecZnxBigNormalize<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
{
fn glwe_automorphism_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
where
@@ -160,7 +218,7 @@ where
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> = keyswitch_internal(self, res_dft, a, key, scratch_1);
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);
@@ -186,7 +244,7 @@ where
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> = keyswitch_internal(self, res_dft, res, key, scratch_1);
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);
@@ -214,7 +272,7 @@ where
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> = keyswitch_internal(self, res_dft, a, key, scratch_1);
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);
@@ -242,7 +300,7 @@ where
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> = keyswitch_internal(self, res_dft, a, key, scratch_1);
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);
@@ -268,7 +326,7 @@ where
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> = keyswitch_internal(self, res_dft, res, key, scratch_1);
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);
@@ -294,7 +352,7 @@ where
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> = keyswitch_internal(self, res_dft, res, key, scratch_1);
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);
@@ -311,12 +369,3 @@ where
}
}
}
impl<BE: Backend> GLWEAutomorphism<BE> for Module<BE> where
Self: GLWEKeyswitch<BE>
+ VecZnxAutomorphismInplace<BE>
+ VecZnxBigAutomorphismInplace<BE>
+ VecZnxBigSubSmallInplace<BE>
+ VecZnxBigSubSmallNegateInplace<BE>
{
}