This commit is contained in:
Pro7ech
2025-10-15 17:15:51 +02:00
parent 15ee02e21d
commit 10817a8529
19 changed files with 264 additions and 304 deletions

View File

@@ -1,5 +1,5 @@
use poulpy_core::layouts::{ use poulpy_core::layouts::{
Base2K, Degree, Dnum, Dsize, GGSW, GGSWCiphertextLayout, GLWE, GLWELayout, GLWESecret, Rank, TorusPrecision, Base2K, Degree, Dnum, Dsize, GGSW, GGSWLayout, GLWE, GLWELayout, GLWESecret, Rank, TorusPrecision,
prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc}, prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc},
}; };
use std::hint::black_box; use std::hint::black_box;
@@ -38,7 +38,7 @@ fn bench_external_product_glwe_fft64(c: &mut Criterion) {
let dnum: Dnum = Dnum(1); //(p.k_ct_in.div_ceil(p.base2k); let dnum: Dnum = Dnum(1); //(p.k_ct_in.div_ceil(p.base2k);
let ggsw_layout: GGSWCiphertextLayout = GGSWCiphertextLayout { let ggsw_layout: GGSWLayout = GGSWLayout {
n, n,
base2k, base2k,
k: k_ggsw, k: k_ggsw,
@@ -146,7 +146,7 @@ fn bench_external_product_glwe_inplace_fft64(c: &mut Criterion) {
let dnum: Dnum = p.k_ct.div_ceil(p.base2k).into(); let dnum: Dnum = p.k_ct.div_ceil(p.base2k).into();
let ggsw_layout: GGSWCiphertextLayout = GGSWCiphertextLayout { let ggsw_layout: GGSWLayout = GGSWLayout {
n, n,
base2k, base2k,
k: k_ggsw, k: k_ggsw,

View File

@@ -1,224 +1,205 @@
use poulpy_hal::{ use poulpy_hal::layouts::{Backend, DataMut, Module, Scratch};
api::{
ScratchAvailable, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply,
VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft,
VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
},
layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero},
};
use crate::layouts::{ use crate::{
AutomorphismKey, GGLWEInfos, GLWE, GLWEInfos, GLWESwitchingKey, ScratchTakeCore,
prepared::{AutomorphismKeyPrepared, GLWESwitchingKeyPrepared}, keyswitching::glwe_ct::GLWEKeySwitch,
layouts::{
AutomorphismKey, AutomorphismKeyToRef, GGLWE, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWESwitchingKey,
GLWESwitchingKeyToRef,
prepared::{GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedToRef},
},
}; };
impl AutomorphismKey<Vec<u8>> { impl AutomorphismKey<Vec<u8>> {
pub fn keyswitch_tmp_bytes<B: Backend, OUT, IN, KEY>( pub fn keyswitch_inplace_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
module: &Module<B>,
out_infos: &OUT,
in_infos: &IN,
key_infos: &KEY,
) -> usize
where where
OUT: GGLWEInfos, R: GGLWEInfos,
IN: GGLWEInfos, A: GGLWEInfos,
KEY: GGLWEInfos, K: GGLWEInfos,
Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, M: GGLWEKeySwitch<BE>,
{ {
GLWESwitchingKey::keyswitch_tmp_bytes(module, out_infos, in_infos, key_infos) module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos)
}
pub fn keyswitch_inplace_tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GGLWEInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GLWESwitchingKey::keyswitch_inplace_tmp_bytes(module, out_infos, key_infos)
} }
} }
impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { impl<DataSelf: DataMut> AutomorphismKey<DataSelf> {
pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>)
&mut self, where
module: &Module<B>, A: AutomorphismKeyToRef,
lhs: &AutomorphismKey<DataLhs>, B: GLWESwitchingKeyPreparedToRef<BE>,
rhs: &GLWESwitchingKeyPrepared<DataRhs, B>, Scratch<BE>: ScratchTakeCore<BE>,
scratch: &mut Scratch<B>, M: GGLWEKeySwitch<BE>,
) where
Module<B>: VecZnxDftBytesOf
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalize<B>
+ VecZnxNormalizeTmpBytes,
Scratch<B>: ScratchAvailable,
{ {
self.key.keyswitch(module, &lhs.key, rhs, scratch); module.gglwe_keyswitch(&mut self.key.key, &a.to_ref().key.key, b, scratch);
} }
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>)
&mut self, where
module: &Module<B>, A: GLWESwitchingKeyPreparedToRef<BE>,
rhs: &AutomorphismKeyPrepared<DataRhs, B>, Scratch<BE>: ScratchTakeCore<BE>,
scratch: &mut Scratch<B>, M: GGLWEKeySwitch<BE>,
) where
Module<B>: VecZnxDftBytesOf
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalize<B>
+ VecZnxNormalizeTmpBytes,
Scratch<B>: ScratchAvailable,
{ {
self.key.keyswitch_inplace(module, &rhs.key, scratch); module.gglwe_keyswitch_inplace(&mut self.key.key, a, scratch);
} }
} }
impl GLWESwitchingKey<Vec<u8>> { impl GLWESwitchingKey<Vec<u8>> {
pub fn keyswitch_tmp_bytes<B: Backend, OUT, IN, KEY>( pub fn keyswitch_inplace_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
module: &Module<B>,
out_infos: &OUT,
in_infos: &IN,
key_apply: &KEY,
) -> usize
where where
OUT: GGLWEInfos, R: GGLWEInfos,
IN: GGLWEInfos, A: GGLWEInfos,
KEY: GGLWEInfos, K: GGLWEInfos,
Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, M: GGLWEKeySwitch<BE>,
{ {
GLWE::keyswitch_tmp_bytes(module, out_infos, in_infos, key_apply) module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos)
}
pub fn keyswitch_inplace_tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_apply: &KEY) -> usize
where
OUT: GGLWEInfos + GLWEInfos,
KEY: GGLWEInfos + GLWEInfos,
Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GLWE::keyswitch_inplace_tmp_bytes(module, out_infos, key_apply)
} }
} }
impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> { impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>)
&mut self, where
module: &Module<B>, A: GLWESwitchingKeyToRef,
lhs: &GLWESwitchingKey<DataLhs>, B: GLWESwitchingKeyPreparedToRef<BE>,
rhs: &GLWESwitchingKeyPrepared<DataRhs, B>, Scratch<BE>: ScratchTakeCore<BE>,
scratch: &mut Scratch<B>, M: GGLWEKeySwitch<BE>,
) where
Module<B>: VecZnxDftBytesOf
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalize<B>
+ VecZnxNormalizeTmpBytes,
Scratch<B>: ScratchAvailable,
{ {
#[cfg(debug_assertions)] module.gglwe_keyswitch(&mut self.key, &a.to_ref().key, b, scratch);
{
assert_eq!(
self.rank_in(),
lhs.rank_in(),
"ksk_out input rank: {} != ksk_in input rank: {}",
self.rank_in(),
lhs.rank_in()
);
assert_eq!(
lhs.rank_out(),
rhs.rank_in(),
"ksk_in output rank: {} != ksk_apply input rank: {}",
self.rank_out(),
rhs.rank_in()
);
assert_eq!(
self.rank_out(),
rhs.rank_out(),
"ksk_out output rank: {} != ksk_apply output rank: {}",
self.rank_out(),
rhs.rank_out()
);
assert!(
self.dnum() <= lhs.dnum(),
"self.dnum()={} > lhs.dnum()={}",
self.dnum(),
lhs.dnum()
);
assert_eq!(
self.dsize(),
lhs.dsize(),
"ksk_out dsize: {} != ksk_in dsize: {}",
self.dsize(),
lhs.dsize()
)
}
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.dnum().into()).for_each(|row_j| {
self.at_mut(row_j, col_i)
.keyswitch(module, &lhs.at(row_j, col_i), rhs, scratch);
});
});
(self.dnum().min(lhs.dnum()).into()..self.dnum().into()).for_each(|row_i| {
(0..self.rank_in().into()).for_each(|col_j| {
self.at_mut(row_i, col_j).data.zero();
});
});
} }
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>)
&mut self, where
module: &Module<B>, A: GLWESwitchingKeyPreparedToRef<BE>,
rhs: &GLWESwitchingKeyPrepared<DataRhs, B>, Scratch<BE>: ScratchTakeCore<BE>,
scratch: &mut Scratch<B>, M: GGLWEKeySwitch<BE>,
) where
Module<B>: VecZnxDftBytesOf
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalize<B>
+ VecZnxNormalizeTmpBytes,
Scratch<B>: ScratchAvailable,
{ {
#[cfg(debug_assertions)] module.gglwe_keyswitch_inplace(&mut self.key, a, scratch);
{
assert_eq!(
self.rank_out(),
rhs.rank_out(),
"ksk_out output rank: {} != ksk_apply output rank: {}",
self.rank_out(),
rhs.rank_out()
);
}
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.dnum().into()).for_each(|row_j| {
self.at_mut(row_j, col_i)
.keyswitch_inplace(module, rhs, scratch)
});
});
} }
} }
impl GGLWE<Vec<u8>> {
pub fn keyswitch_inplace_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
where
R: GGLWEInfos,
A: GGLWEInfos,
K: GGLWEInfos,
M: GGLWEKeySwitch<BE>,
{
module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos)
}
}
impl<DataSelf: DataMut> GGLWE<DataSelf> {
pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>)
where
A: GGLWEToRef,
B: GLWESwitchingKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
M: GGLWEKeySwitch<BE>,
{
module.gglwe_keyswitch(self, a, b, scratch);
}
pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>)
where
A: GLWESwitchingKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
M: GGLWEKeySwitch<BE>,
{
module.gglwe_keyswitch_inplace(self, a, scratch);
}
}
impl<BE: Backend> GGLWEKeySwitch<BE> for Module<BE> where Self: GLWEKeySwitch<BE> {}
pub trait GGLWEKeySwitch<BE: Backend>
where
Self: GLWEKeySwitch<BE>,
{
fn gglwe_keyswitch_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
where
R: GGLWEInfos,
A: GGLWEInfos,
K: GGLWEInfos,
{
self.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos)
}
fn gglwe_keyswitch<R, A, B>(&self, res: &mut R, a: &A, b: &B, scratch: &mut Scratch<BE>)
where
R: GGLWEToMut,
A: GGLWEToRef,
B: GLWESwitchingKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
{
let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut();
let a: &GGLWE<&[u8]> = &a.to_ref();
let b: &GLWESwitchingKeyPrepared<&[u8], BE> = &b.to_ref();
assert_eq!(
res.rank_in(),
a.rank_in(),
"res input rank: {} != a input rank: {}",
res.rank_in(),
a.rank_in()
);
assert_eq!(
a.rank_out(),
b.rank_in(),
"res output rank: {} != b input rank: {}",
a.rank_out(),
b.rank_in()
);
assert_eq!(
res.rank_out(),
b.rank_out(),
"res output rank: {} != b output rank: {}",
res.rank_out(),
b.rank_out()
);
assert!(
res.dnum() <= a.dnum(),
"res.dnum()={} > a.dnum()={}",
res.dnum(),
a.dnum()
);
assert_eq!(
res.dsize(),
a.dsize(),
"res dsize: {} != a dsize: {}",
res.dsize(),
a.dsize()
);
for row in 0..res.dnum().into() {
for col in 0..res.rank_in().into() {
self.glwe_keyswitch(&mut res.at_mut(row, col), &a.at(row, col), b, scratch);
}
}
}
fn gglwe_keyswitch_inplace<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<BE>)
where
R: GGLWEToMut,
A: GLWESwitchingKeyPreparedToRef<BE>,
Scratch<BE>: ScratchTakeCore<BE>,
{
let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut();
let a: &GLWESwitchingKeyPrepared<&[u8], BE> = &a.to_ref();
assert_eq!(
res.rank_out(),
a.rank_out(),
"res output rank: {} != a output rank: {}",
res.rank_out(),
a.rank_out()
);
for row in 0..res.dnum().into() {
for col in 0..res.rank_in().into() {
self.glwe_keyswitch_inplace(&mut res.at_mut(row, col), a, scratch);
}
}
}
}
impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {}

View File

@@ -2,7 +2,7 @@ use poulpy_hal::layouts::{Backend, DataMut, Scratch, VecZnx};
use crate::{ use crate::{
GGSWExpandRows, ScratchTakeCore, GGSWExpandRows, ScratchTakeCore,
keyswitching::glwe_ct::GLWEKeySwitching, keyswitching::glwe_ct::GLWEKeySwitch,
layouts::{ layouts::{
GGLWEInfos, GGSW, GGSWInfos, GGSWToMut, GGSWToRef, GGLWEInfos, GGSW, GGSWInfos, GGSWToMut, GGSWToRef,
prepared::{GLWESwitchingKeyPreparedToRef, TensorKeyPreparedToRef}, prepared::{GLWESwitchingKeyPreparedToRef, TensorKeyPreparedToRef},
@@ -53,7 +53,7 @@ impl<D: DataMut> GGSW<D> {
pub trait GGSWKeySwitch<BE: Backend> pub trait GGSWKeySwitch<BE: Backend>
where where
Self: GLWEKeySwitching<BE> + GGSWExpandRows<BE>, Self: GLWEKeySwitch<BE> + GGSWExpandRows<BE>,
{ {
fn ggsw_keyswitch_tmp_bytes<R, A, K, T>(&self, res_infos: &R, a_infos: &A, key_infos: &K, tsk_infos: &T) -> usize fn ggsw_keyswitch_tmp_bytes<R, A, K, T>(&self, res_infos: &R, a_infos: &A, key_infos: &K, tsk_infos: &T) -> usize
where where

View File

@@ -21,7 +21,7 @@ impl GLWE<Vec<u8>> {
R: GLWEInfos, R: GLWEInfos,
A: GLWEInfos, A: GLWEInfos,
B: GGLWEInfos, B: GGLWEInfos,
M: GLWEKeySwitching<BE>, M: GLWEKeySwitch<BE>,
{ {
module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, b_infos) module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, b_infos)
} }
@@ -32,7 +32,7 @@ impl<D: DataMut> GLWE<D> {
where where
A: GLWEToRef, A: GLWEToRef,
B: GLWESwitchingKeyPreparedToRef<BE>, B: GLWESwitchingKeyPreparedToRef<BE>,
M: GLWEKeySwitching<BE>, M: GLWEKeySwitch<BE>,
Scratch<BE>: ScratchTakeCore<BE>, Scratch<BE>: ScratchTakeCore<BE>,
{ {
module.glwe_keyswitch(self, a, b, scratch); module.glwe_keyswitch(self, a, b, scratch);
@@ -41,14 +41,14 @@ impl<D: DataMut> GLWE<D> {
pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>)
where where
A: GLWESwitchingKeyPreparedToRef<BE>, A: GLWESwitchingKeyPreparedToRef<BE>,
M: GLWEKeySwitching<BE>, M: GLWEKeySwitch<BE>,
Scratch<BE>: ScratchTakeCore<BE>, Scratch<BE>: ScratchTakeCore<BE>,
{ {
module.glwe_keyswitch_inplace(self, a, scratch); module.glwe_keyswitch_inplace(self, a, scratch);
} }
} }
impl<BE: Backend> GLWEKeySwitching<BE> for Module<BE> where impl<BE: Backend> GLWEKeySwitch<BE> for Module<BE> where
Self: Sized Self: Sized
+ ModuleN + ModuleN
+ VecZnxDftBytesOf + VecZnxDftBytesOf
@@ -69,7 +69,7 @@ impl<BE: Backend> GLWEKeySwitching<BE> for Module<BE> where
{ {
} }
pub trait GLWEKeySwitching<BE: Backend> pub trait GLWEKeySwitch<BE: Backend>
where where
Self: Sized Self: Sized
+ ModuleN + ModuleN

View File

@@ -7,85 +7,58 @@ use poulpy_hal::{
layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero}, layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero},
}; };
use crate::layouts::{GGLWEInfos, GLWE, GLWELayout, LWE, LWEInfos, Rank, TorusPrecision, prepared::LWESwitchingKeyPrepared}; use crate::{
keyswitching::glwe_ct::GLWEKeySwitch,
layouts::{prepared::LWESwitchingKeyPrepared, GGLWEInfos, GLWEAlloc, GLWELayout, GetDegree, LWEToRef, LWEInfos, Rank, TorusPrecision, GLWE, LWE},
};
impl LWE<Vec<u8>> { pub trait LWEKeySwitch<BE: Backend>
pub fn keyswitch_tmp_bytes<B: Backend, OUT, IN, KEY>( where
module: &Module<B>, Self: GLWEKeySwitch<BE> + GLWEAlloc,
out_infos: &OUT, {
in_infos: &IN, fn keyswitch_tmp_bytes<B: Backend, R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
key_infos: &KEY,
) -> usize
where where
OUT: LWEInfos, R: LWEInfos,
IN: LWEInfos, A: LWEInfos,
KEY: GGLWEInfos, K: GGLWEInfos,
Module<B>: VecZnxDftBytesOf
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDftTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalizeTmpBytes,
{ {
let max_k: TorusPrecision = in_infos.k().max(out_infos.k()); let max_k: TorusPrecision = a_infos.k().max(res_infos.k());
let glwe_in_infos: GLWELayout = GLWELayout { let glwe_a_infos: GLWELayout = GLWELayout {
n: module.n().into(), n: GetDegree::n(self),
base2k: in_infos.base2k(), base2k: a_infos.base2k(),
k: max_k, k: max_k,
rank: Rank(1), rank: Rank(1),
}; };
let glwe_out_infos: GLWELayout = GLWELayout { let glwe_res_infos: GLWELayout = GLWELayout {
n: module.n().into(), n: GetDegree::n(self),
base2k: out_infos.base2k(), base2k: res_infos.base2k(),
k: max_k, k: max_k,
rank: Rank(1), rank: Rank(1),
}; };
let glwe_in: usize = GLWE::bytes_of_from_infos(module, &glwe_in_infos); let glwe_in: usize = GLWE::bytes_of_from_infos(self, &glwe_a_infos);
let glwe_out: usize = GLWE::bytes_of_from_infos(module, &glwe_out_infos); let glwe_out: usize = GLWE::bytes_of_from_infos(self, &glwe_res_infos);
let ks: usize = GLWE::keyswitch_tmp_bytes(module, &glwe_out_infos, &glwe_in_infos, key_infos); let ks: usize = self.glwe_keyswitch_tmp_bytes(&glwe_res_infos, &glwe_a_infos, key_infos);
glwe_in + glwe_out + ks glwe_in + glwe_out + ks
} }
}
impl<DLwe: DataMut> LWE<DLwe> { fn keyswitch<A, DKs, B: Backend>(
pub fn keyswitch<A, DKs, B: Backend>(
&mut self, &mut self,
module: &Module<B>, module: &Module<B>,
a: &LWE<A>, a: &A,
ksk: &LWESwitchingKeyPrepared<DKs, B>, ksk: &K,
scratch: &mut Scratch<B>, scratch: &mut Scratch<B>,
) where ) where
A: DataRef, A: LWEToRef,
DKs: DataRef, DKs: DataRef,
Module<B>: VecZnxDftBytesOf
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalize<B>
+ VecZnxNormalizeTmpBytes
+ VecZnxCopy,
Scratch<B>: ScratchAvailable, Scratch<B>: ScratchAvailable,
{ {
#[cfg(debug_assertions)] assert!(self.n() <= module.n() as u32);
{
assert!(self.n() <= module.n() as u32);
assert!(a.n() <= module.n() as u32); assert!(a.n() <= module.n() as u32);
assert!(scratch.available() >= LWE::keyswitch_tmp_bytes(module, self, a, ksk)); assert!(scratch.available() >= LWE::keyswitch_tmp_bytes(module, self, a, ksk));
}
let max_k: TorusPrecision = self.k().max(a.k()); let max_k: TorusPrecision = self.k().max(a.k());
@@ -118,3 +91,9 @@ impl<DLwe: DataMut> LWE<DLwe> {
self.sample_extract(&glwe_out); self.sample_extract(&glwe_out);
} }
} }
impl LWE<Vec<u8>> {}
impl<DLwe: DataMut> LWE<DLwe> {
}

View File

@@ -18,8 +18,8 @@ where
fn dsize(&self) -> Dsize; fn dsize(&self) -> Dsize;
fn rank_in(&self) -> Rank; fn rank_in(&self) -> Rank;
fn rank_out(&self) -> Rank; fn rank_out(&self) -> Rank;
fn gglwe_layout(&self) -> GGLWECiphertextLayout { fn gglwe_layout(&self) -> GGLWELayout {
GGLWECiphertextLayout { GGLWELayout {
n: self.n(), n: self.n(),
base2k: self.base2k(), base2k: self.base2k(),
k: self.k(), k: self.k(),
@@ -36,7 +36,7 @@ pub trait SetGGLWEInfos {
} }
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct GGLWECiphertextLayout { pub struct GGLWELayout {
pub n: Degree, pub n: Degree,
pub base2k: Base2K, pub base2k: Base2K,
pub k: TorusPrecision, pub k: TorusPrecision,
@@ -46,7 +46,7 @@ pub struct GGLWECiphertextLayout {
pub dsize: Dsize, pub dsize: Dsize,
} }
impl LWEInfos for GGLWECiphertextLayout { impl LWEInfos for GGLWELayout {
fn base2k(&self) -> Base2K { fn base2k(&self) -> Base2K {
self.base2k self.base2k
} }
@@ -60,13 +60,13 @@ impl LWEInfos for GGLWECiphertextLayout {
} }
} }
impl GLWEInfos for GGLWECiphertextLayout { impl GLWEInfos for GGLWELayout {
fn rank(&self) -> Rank { fn rank(&self) -> Rank {
self.rank_out self.rank_out
} }
} }
impl GGLWEInfos for GGLWECiphertextLayout { impl GGLWEInfos for GGLWELayout {
fn rank_in(&self) -> Rank { fn rank_in(&self) -> Rank {
self.rank_in self.rank_in
} }

View File

@@ -14,8 +14,8 @@ where
{ {
fn dnum(&self) -> Dnum; fn dnum(&self) -> Dnum;
fn dsize(&self) -> Dsize; fn dsize(&self) -> Dsize;
fn ggsw_layout(&self) -> GGSWCiphertextLayout { fn ggsw_layout(&self) -> GGSWLayout {
GGSWCiphertextLayout { GGSWLayout {
n: self.n(), n: self.n(),
base2k: self.base2k(), base2k: self.base2k(),
k: self.k(), k: self.k(),
@@ -27,7 +27,7 @@ where
} }
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct GGSWCiphertextLayout { pub struct GGSWLayout {
pub n: Degree, pub n: Degree,
pub base2k: Base2K, pub base2k: Base2K,
pub k: TorusPrecision, pub k: TorusPrecision,
@@ -36,7 +36,7 @@ pub struct GGSWCiphertextLayout {
pub dsize: Dsize, pub dsize: Dsize,
} }
impl LWEInfos for GGSWCiphertextLayout { impl LWEInfos for GGSWLayout {
fn base2k(&self) -> Base2K { fn base2k(&self) -> Base2K {
self.base2k self.base2k
} }
@@ -49,13 +49,13 @@ impl LWEInfos for GGSWCiphertextLayout {
self.n self.n
} }
} }
impl GLWEInfos for GGSWCiphertextLayout { impl GLWEInfos for GGSWLayout {
fn rank(&self) -> Rank { fn rank(&self) -> Rank {
self.rank self.rank
} }
} }
impl GGSWInfos for GGSWCiphertextLayout { impl GGSWInfos for GGSWLayout {
fn dsize(&self) -> Dsize { fn dsize(&self) -> Dsize {
self.dsize self.dsize
} }
@@ -117,7 +117,7 @@ impl<D: DataRef> fmt::Display for GGSW<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"(GGSWCiphertext: k: {} base2k: {} dsize: {}) {}", "(GGSW: k: {} base2k: {} dsize: {}) {}",
self.k().0, self.k().0,
self.base2k().0, self.base2k().0,
self.dsize().0, self.dsize().0,

View File

@@ -57,7 +57,7 @@ impl GGLWEInfos for GLWEToLWEKeyLayout {
} }
} }
/// A special [GLWESwitchingKey] required to for the conversion from [GLWECiphertext] to [LWECiphertext]. /// A special [GLWESwitchingKey] required to for the conversion from [GLWE] to [LWE].
#[derive(PartialEq, Eq, Clone)] #[derive(PartialEq, Eq, Clone)]
pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>); pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);

View File

@@ -18,8 +18,8 @@ pub trait LWEInfos {
fn size(&self) -> usize { fn size(&self) -> usize {
self.k().0.div_ceil(self.base2k().0) as usize self.k().0.div_ceil(self.base2k().0) as usize
} }
fn lwe_layout(&self) -> LWECiphertextLayout { fn lwe_layout(&self) -> LWELayout {
LWECiphertextLayout { LWELayout {
n: self.n(), n: self.n(),
k: self.k(), k: self.k(),
base2k: self.base2k(), base2k: self.base2k(),
@@ -33,13 +33,13 @@ pub trait SetLWEInfos {
} }
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct LWECiphertextLayout { pub struct LWELayout {
pub n: Degree, pub n: Degree,
pub k: TorusPrecision, pub k: TorusPrecision,
pub base2k: Base2K, pub base2k: Base2K,
} }
impl LWEInfos for LWECiphertextLayout { impl LWEInfos for LWELayout {
fn base2k(&self) -> Base2K { fn base2k(&self) -> Base2K {
self.base2k self.base2k
} }
@@ -108,7 +108,7 @@ impl<D: DataRef> fmt::Display for LWE<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"LWECiphertext: base2k={} k={}: {}", "LWE: base2k={} k={}: {}",
self.base2k().0, self.base2k().0,
self.k().0, self.k().0,
self.data self.data
@@ -187,11 +187,11 @@ impl LWE<Vec<u8>> {
} }
} }
pub trait LWECiphertextToRef { pub trait LWEToRef {
fn to_ref(&self) -> LWE<&[u8]>; fn to_ref(&self) -> LWE<&[u8]>;
} }
impl<D: DataRef> LWECiphertextToRef for LWE<D> { impl<D: DataRef> LWEToRef for LWE<D> {
fn to_ref(&self) -> LWE<&[u8]> { fn to_ref(&self) -> LWE<&[u8]> {
LWE { LWE {
k: self.k, k: self.k,

View File

@@ -8,7 +8,7 @@ use crate::layouts::{
}, },
}; };
/// A special [GLWESwitchingKey] required to for the conversion from [LWECiphertext] to [GLWECiphertext]. /// A special [GLWESwitchingKey] required to for the conversion from [LWE] to [GLWE].
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>); pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);

View File

@@ -326,7 +326,7 @@ where
let mut scratch: &mut Self = self; let mut scratch: &mut Self = self;
let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.gglwe_layout(); let mut ksk_infos: crate::layouts::GGLWELayout = infos.gglwe_layout();
ksk_infos.rank_in = Rank(1); ksk_infos.rank_in = Rank(1);
if pairs != 0 { if pairs != 0 {
@@ -359,7 +359,7 @@ where
let mut scratch: &mut Self = self; let mut scratch: &mut Self = self;
let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.gglwe_layout(); let mut ksk_infos: crate::layouts::GGLWELayout = infos.gglwe_layout();
ksk_infos.rank_in = Rank(1); ksk_infos.rank_in = Rank(1);
if pairs != 0 { if pairs != 0 {

View File

@@ -3,7 +3,7 @@ use std::hint::black_box;
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use poulpy_backend::{FFT64Avx, FFT64Ref, FFT64Spqlios}; use poulpy_backend::{FFT64Avx, FFT64Ref, FFT64Spqlios};
use poulpy_core::layouts::{ use poulpy_core::layouts::{
AutomorphismKeyLayout, Dsize, GGSW, GGSWCiphertextLayout, GLWESecret, LWE, LWECiphertextLayout, LWESecret, TensorKeyLayout, AutomorphismKeyLayout, Dsize, GGSW, GGSWLayout, GLWESecret, LWE, LWELayout, LWESecret, TensorKeyLayout,
prepared::PrepareAlloc, prepared::PrepareAlloc,
}; };
use poulpy_hal::{ use poulpy_hal::{
@@ -113,8 +113,8 @@ where
extension_factor: usize, extension_factor: usize,
k_pt: usize, k_pt: usize,
block_size: usize, block_size: usize,
lwe_infos: LWECiphertextLayout, lwe_infos: LWELayout,
ggsw_infos: GGSWCiphertextLayout, ggsw_infos: GGSWLayout,
cbt_infos: CircuitBootstrappingKeyLayout, cbt_infos: CircuitBootstrappingKeyLayout,
} }
@@ -238,13 +238,13 @@ where
name: String::from("1-bit"), name: String::from("1-bit"),
extension_factor: 1, extension_factor: 1,
k_pt: 1, k_pt: 1,
lwe_infos: LWECiphertextLayout { lwe_infos: LWELayout {
n: 574_u32.into(), n: 574_u32.into(),
k: 13_u32.into(), k: 13_u32.into(),
base2k: 13_u32.into(), base2k: 13_u32.into(),
}, },
block_size: 7, block_size: 7,
ggsw_infos: GGSWCiphertextLayout { ggsw_infos: GGSWLayout {
n: 1024_u32.into(), n: 1024_u32.into(),
base2k: 13_u32.into(), base2k: 13_u32.into(),
k: 26_u32.into(), k: 26_u32.into(),

View File

@@ -1,7 +1,7 @@
use poulpy_core::{ use poulpy_core::{
GLWEOperations, GLWEOperations,
layouts::{ layouts::{
AutomorphismKeyLayout, GGSW, GGSWCiphertextLayout, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWE, LWECiphertextLayout, AutomorphismKeyLayout, GGSW, GGSWLayout, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWE, LWELayout,
LWEInfos, LWEPlaintext, LWESecret, TensorKeyLayout, LWEInfos, LWEPlaintext, LWESecret, TensorKeyLayout,
prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc}, prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc},
}, },
@@ -107,7 +107,7 @@ fn main() {
}, },
}; };
let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout { let ggsw_infos: GGSWLayout = GGSWLayout {
n: n_glwe.into(), n: n_glwe.into(),
base2k: base2k.into(), base2k: base2k.into(),
k: k_ggsw_res.into(), k: k_ggsw_res.into(),
@@ -116,7 +116,7 @@ fn main() {
rank: rank.into(), rank: rank.into(),
}; };
let lwe_infos = LWECiphertextLayout { let lwe_infos = LWELayout {
n: n_lwe.into(), n: n_lwe.into(),
k: k_lwe_ct.into(), k: k_lwe_ct.into(),
base2k: base2k.into(), base2k: base2k.into(),

View File

@@ -1,6 +1,6 @@
#[cfg(test)] #[cfg(test)]
use poulpy_core::layouts::{ use poulpy_core::layouts::{
AutomorphismKeyLayout, Base2K, Degree, Dnum, Dsize, GGSWCiphertextLayout, GLWELayout, GLWEToLWEKeyLayout, Rank, AutomorphismKeyLayout, Base2K, Degree, Dnum, Dsize, GGSWLayout, GLWELayout, GLWEToLWEKeyLayout, Rank,
TensorKeyLayout, TorusPrecision, TensorKeyLayout, TorusPrecision,
}; };
@@ -33,7 +33,7 @@ pub(crate) static TEST_GLWE_INFOS: GLWELayout = GLWELayout {
}; };
#[cfg(test)] #[cfg(test)]
pub(crate) static TEST_GGSW_INFOS: GGSWCiphertextLayout = GGSWCiphertextLayout { pub(crate) static TEST_GGSW_INFOS: GGSWLayout = GGSWLayout {
n: Degree(TEST_N_GLWE), n: Degree(TEST_N_GLWE),
base2k: Base2K(TEST_BASE2K), base2k: Base2K(TEST_BASE2K),
k: TorusPrecision(TEST_K_GGSW), k: TorusPrecision(TEST_K_GGSW),

View File

@@ -4,7 +4,7 @@ use poulpy_backend::FFT64Ref;
use poulpy_core::{ use poulpy_core::{
TakeGGSW, TakeGLWEPlaintext, TakeGGSW, TakeGLWEPlaintext,
layouts::{ layouts::{
GGSWCiphertextLayout, GLWELayout, GLWESecret, LWEInfos, LWESecret, GGSWLayout, GLWELayout, GLWESecret, LWEInfos, LWESecret,
prepared::{GLWESecretPrepared, PrepareAlloc}, prepared::{GLWESecretPrepared, PrepareAlloc},
}, },
}; };
@@ -108,7 +108,7 @@ where
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<BE>, BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<BE>,
{ {
let glwe_infos: GLWELayout = TEST_GLWE_INFOS; let glwe_infos: GLWELayout = TEST_GLWE_INFOS;
let ggsw_infos: GGSWCiphertextLayout = TEST_GGSW_INFOS; let ggsw_infos: GGSWLayout = TEST_GGSW_INFOS;
let n_glwe: usize = glwe_infos.n().into(); let n_glwe: usize = glwe_infos.n().into();

View File

@@ -13,7 +13,7 @@ use poulpy_hal::{
use poulpy_core::{ use poulpy_core::{
Distribution, GLWEOperations, TakeGLWE, Distribution, GLWEOperations, TakeGLWE,
layouts::{GGSWInfos, GLWE, GLWEInfos, GLWEToMut, LWE, LWECiphertextToRef, LWEInfos}, layouts::{GGSWInfos, GLWE, GLWEInfos, GLWEToMut, LWE, LWEToRef, LWEInfos},
}; };
use crate::tfhe::blind_rotation::{ use crate::tfhe::blind_rotation::{

View File

@@ -23,7 +23,7 @@ use crate::tfhe::blind_rotation::{
}; };
use poulpy_core::layouts::{ use poulpy_core::layouts::{
GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWE, LWECiphertextLayout, LWECiphertextToRef, LWEInfos, LWEPlaintext, LWESecret, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWE, LWELayout, LWEToRef, LWEInfos, LWEPlaintext, LWESecret,
prepared::{GLWESecretPrepared, PrepareAlloc}, prepared::{GLWESecretPrepared, PrepareAlloc},
}; };
@@ -117,7 +117,7 @@ where
rank: rank.into(), rank: rank.into(),
}; };
let lwe_infos: LWECiphertextLayout = LWECiphertextLayout { let lwe_infos: LWELayout = LWELayout {
n: n_lwe.into(), n: n_lwe.into(),
k: k_lwe.into(), k: k_lwe.into(),
base2k: base2k.into(), base2k: base2k.into(),

View File

@@ -16,7 +16,7 @@ use poulpy_hal::{
use poulpy_core::{ use poulpy_core::{
GLWEOperations, TakeGGLWE, TakeGLWE, GLWEOperations, TakeGGLWE, TakeGLWE,
layouts::{Dsize, GGLWECiphertextLayout, GGSWInfos, GLWEInfos, LWEInfos}, layouts::{Dsize, GGLWELayout, GGSWInfos, GLWEInfos, LWEInfos},
}; };
use poulpy_core::glwe_packing; use poulpy_core::glwe_packing;
@@ -214,7 +214,7 @@ pub fn circuit_bootstrap_core<DRes, DLwe, DBrk, BRA: BlindRotationAlgo, B>(
// TODO: separate GGSW k from output of blind rotation k // TODO: separate GGSW k from output of blind rotation k
let (mut res_glwe, scratch_1) = scratch.take_glwe_ct(res); let (mut res_glwe, scratch_1) = scratch.take_glwe_ct(res);
let gglwe_infos: GGLWECiphertextLayout = GGLWECiphertextLayout { let gglwe_infos: GGLWELayout = GGLWELayout {
n: n.into(), n: n.into(),
base2k: base2k.into(), base2k: base2k.into(),
k: k.into(), k: k.into(),

View File

@@ -32,7 +32,7 @@ use crate::tfhe::{
}; };
use poulpy_core::layouts::{ use poulpy_core::layouts::{
AutomorphismKeyLayout, Dsize, GGSWCiphertextLayout, LWECiphertextLayout, TensorKeyLayout, prepared::PrepareAlloc, AutomorphismKeyLayout, Dsize, GGSWLayout, LWELayout, TensorKeyLayout, prepared::PrepareAlloc,
}; };
use poulpy_core::layouts::{ use poulpy_core::layouts::{
@@ -128,7 +128,7 @@ where
let k_ggsw_res: usize = 4 * base2k; let k_ggsw_res: usize = 4 * base2k;
let rows_ggsw_res: usize = 2; let rows_ggsw_res: usize = 2;
let lwe_infos: LWECiphertextLayout = LWECiphertextLayout { let lwe_infos: LWELayout = LWELayout {
n: n_lwe.into(), n: n_lwe.into(),
k: k_lwe_ct.into(), k: k_lwe_ct.into(),
base2k: base2k.into(), base2k: base2k.into(),
@@ -161,7 +161,7 @@ where
}, },
}; };
let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout { let ggsw_infos: GGSWLayout = GGSWLayout {
n: n_glwe.into(), n: n_glwe.into(),
base2k: base2k.into(), base2k: base2k.into(),
k: k_ggsw_res.into(), k: k_ggsw_res.into(),
@@ -350,7 +350,7 @@ where
let k_ggsw_res: usize = 4 * base2k; let k_ggsw_res: usize = 4 * base2k;
let rows_ggsw_res: usize = 3; let rows_ggsw_res: usize = 3;
let lwe_infos: LWECiphertextLayout = LWECiphertextLayout { let lwe_infos: LWELayout = LWELayout {
n: n_lwe.into(), n: n_lwe.into(),
k: k_lwe_ct.into(), k: k_lwe_ct.into(),
base2k: base2k.into(), base2k: base2k.into(),
@@ -383,7 +383,7 @@ where
}, },
}; };
let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout { let ggsw_infos: GGSWLayout = GGSWLayout {
n: n_glwe.into(), n: n_glwe.into(),
base2k: base2k.into(), base2k: base2k.into(),
k: k_ggsw_res.into(), k: k_ggsw_res.into(),