mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
wip
This commit is contained in:
@@ -1,224 +1,205 @@
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ScratchAvailable, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply,
|
||||
VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft,
|
||||
VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
|
||||
},
|
||||
layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, DataMut, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
AutomorphismKey, GGLWEInfos, GLWE, GLWEInfos, GLWESwitchingKey,
|
||||
prepared::{AutomorphismKeyPrepared, GLWESwitchingKeyPrepared},
|
||||
use crate::{
|
||||
ScratchTakeCore,
|
||||
keyswitching::glwe_ct::GLWEKeySwitch,
|
||||
layouts::{
|
||||
AutomorphismKey, AutomorphismKeyToRef, GGLWE, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWESwitchingKey,
|
||||
GLWESwitchingKeyToRef,
|
||||
prepared::{GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedToRef},
|
||||
},
|
||||
};
|
||||
|
||||
impl AutomorphismKey<Vec<u8>> {
|
||||
pub fn keyswitch_tmp_bytes<B: Backend, OUT, IN, KEY>(
|
||||
module: &Module<B>,
|
||||
out_infos: &OUT,
|
||||
in_infos: &IN,
|
||||
key_infos: &KEY,
|
||||
) -> usize
|
||||
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
|
||||
OUT: GGLWEInfos,
|
||||
IN: GGLWEInfos,
|
||||
KEY: GGLWEInfos,
|
||||
Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
|
||||
R: GGLWEInfos,
|
||||
A: GGLWEInfos,
|
||||
K: GGLWEInfos,
|
||||
M: GGLWEKeySwitch<BE>,
|
||||
{
|
||||
GLWESwitchingKey::keyswitch_tmp_bytes(module, out_infos, in_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)
|
||||
module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DataSelf: DataMut> AutomorphismKey<DataSelf> {
|
||||
pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
lhs: &AutomorphismKey<DataLhs>,
|
||||
rhs: &GLWESwitchingKeyPrepared<DataRhs, B>,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
Module<B>: VecZnxDftBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
Scratch<B>: ScratchAvailable,
|
||||
pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
A: AutomorphismKeyToRef,
|
||||
B: GLWESwitchingKeyPreparedToRef<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
M: GGLWEKeySwitch<BE>,
|
||||
{
|
||||
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>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
rhs: &AutomorphismKeyPrepared<DataRhs, B>,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
Module<B>: VecZnxDftBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
Scratch<B>: ScratchAvailable,
|
||||
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>,
|
||||
{
|
||||
self.key.keyswitch_inplace(module, &rhs.key, scratch);
|
||||
module.gglwe_keyswitch_inplace(&mut self.key.key, a, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWESwitchingKey<Vec<u8>> {
|
||||
pub fn keyswitch_tmp_bytes<B: Backend, OUT, IN, KEY>(
|
||||
module: &Module<B>,
|
||||
out_infos: &OUT,
|
||||
in_infos: &IN,
|
||||
key_apply: &KEY,
|
||||
) -> usize
|
||||
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
|
||||
OUT: GGLWEInfos,
|
||||
IN: GGLWEInfos,
|
||||
KEY: GGLWEInfos,
|
||||
Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
|
||||
R: GGLWEInfos,
|
||||
A: GGLWEInfos,
|
||||
K: GGLWEInfos,
|
||||
M: GGLWEKeySwitch<BE>,
|
||||
{
|
||||
GLWE::keyswitch_tmp_bytes(module, out_infos, in_infos, key_apply)
|
||||
}
|
||||
|
||||
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)
|
||||
module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
|
||||
pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
lhs: &GLWESwitchingKey<DataLhs>,
|
||||
rhs: &GLWESwitchingKeyPrepared<DataRhs, B>,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
Module<B>: VecZnxDftBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
Scratch<B>: ScratchAvailable,
|
||||
pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
A: GLWESwitchingKeyToRef,
|
||||
B: GLWESwitchingKeyPreparedToRef<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
M: GGLWEKeySwitch<BE>,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
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();
|
||||
});
|
||||
});
|
||||
module.gglwe_keyswitch(&mut self.key, &a.to_ref().key, b, scratch);
|
||||
}
|
||||
|
||||
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
rhs: &GLWESwitchingKeyPrepared<DataRhs, B>,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
Module<B>: VecZnxDftBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
Scratch<B>: ScratchAvailable,
|
||||
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>,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
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)
|
||||
});
|
||||
});
|
||||
module.gglwe_keyswitch_inplace(&mut self.key, a, 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> {}
|
||||
|
||||
@@ -2,7 +2,7 @@ use poulpy_hal::layouts::{Backend, DataMut, Scratch, VecZnx};
|
||||
|
||||
use crate::{
|
||||
GGSWExpandRows, ScratchTakeCore,
|
||||
keyswitching::glwe_ct::GLWEKeySwitching,
|
||||
keyswitching::glwe_ct::GLWEKeySwitch,
|
||||
layouts::{
|
||||
GGLWEInfos, GGSW, GGSWInfos, GGSWToMut, GGSWToRef,
|
||||
prepared::{GLWESwitchingKeyPreparedToRef, TensorKeyPreparedToRef},
|
||||
@@ -53,7 +53,7 @@ impl<D: DataMut> GGSW<D> {
|
||||
|
||||
pub trait GGSWKeySwitch<BE: Backend>
|
||||
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
|
||||
where
|
||||
|
||||
@@ -21,7 +21,7 @@ impl GLWE<Vec<u8>> {
|
||||
R: GLWEInfos,
|
||||
A: GLWEInfos,
|
||||
B: GGLWEInfos,
|
||||
M: GLWEKeySwitching<BE>,
|
||||
M: GLWEKeySwitch<BE>,
|
||||
{
|
||||
module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, b_infos)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ impl<D: DataMut> GLWE<D> {
|
||||
where
|
||||
A: GLWEToRef,
|
||||
B: GLWESwitchingKeyPreparedToRef<BE>,
|
||||
M: GLWEKeySwitching<BE>,
|
||||
M: GLWEKeySwitch<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
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>)
|
||||
where
|
||||
A: GLWESwitchingKeyPreparedToRef<BE>,
|
||||
M: GLWEKeySwitching<BE>,
|
||||
M: GLWEKeySwitch<BE>,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
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
|
||||
+ ModuleN
|
||||
+ 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
|
||||
Self: Sized
|
||||
+ ModuleN
|
||||
|
||||
@@ -7,85 +7,58 @@ use poulpy_hal::{
|
||||
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 fn keyswitch_tmp_bytes<B: Backend, OUT, IN, KEY>(
|
||||
module: &Module<B>,
|
||||
out_infos: &OUT,
|
||||
in_infos: &IN,
|
||||
key_infos: &KEY,
|
||||
) -> usize
|
||||
pub trait LWEKeySwitch<BE: Backend>
|
||||
where
|
||||
Self: GLWEKeySwitch<BE> + GLWEAlloc,
|
||||
{
|
||||
fn keyswitch_tmp_bytes<B: Backend, R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize
|
||||
where
|
||||
OUT: LWEInfos,
|
||||
IN: LWEInfos,
|
||||
KEY: GGLWEInfos,
|
||||
Module<B>: VecZnxDftBytesOf
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VecZnxBigNormalizeTmpBytes
|
||||
+ VmpApplyDftToDftTmpBytes
|
||||
+ VmpApplyDftToDft<B>
|
||||
+ VmpApplyDftToDftAdd<B>
|
||||
+ VecZnxDftApply<B>
|
||||
+ VecZnxIdftApplyConsume<B>
|
||||
+ VecZnxBigAddSmallInplace<B>
|
||||
+ VecZnxBigNormalize<B>
|
||||
+ VecZnxNormalizeTmpBytes,
|
||||
R: LWEInfos,
|
||||
A: LWEInfos,
|
||||
K: GGLWEInfos,
|
||||
{
|
||||
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 {
|
||||
n: module.n().into(),
|
||||
base2k: in_infos.base2k(),
|
||||
let glwe_a_infos: GLWELayout = GLWELayout {
|
||||
n: GetDegree::n(self),
|
||||
base2k: a_infos.base2k(),
|
||||
k: max_k,
|
||||
rank: Rank(1),
|
||||
};
|
||||
|
||||
let glwe_out_infos: GLWELayout = GLWELayout {
|
||||
n: module.n().into(),
|
||||
base2k: out_infos.base2k(),
|
||||
let glwe_res_infos: GLWELayout = GLWELayout {
|
||||
n: GetDegree::n(self),
|
||||
base2k: res_infos.base2k(),
|
||||
k: max_k,
|
||||
rank: Rank(1),
|
||||
};
|
||||
|
||||
let glwe_in: usize = GLWE::bytes_of_from_infos(module, &glwe_in_infos);
|
||||
let glwe_out: usize = GLWE::bytes_of_from_infos(module, &glwe_out_infos);
|
||||
let ks: usize = GLWE::keyswitch_tmp_bytes(module, &glwe_out_infos, &glwe_in_infos, key_infos);
|
||||
let glwe_in: usize = GLWE::bytes_of_from_infos(self, &glwe_a_infos);
|
||||
let glwe_out: usize = GLWE::bytes_of_from_infos(self, &glwe_res_infos);
|
||||
let ks: usize = self.glwe_keyswitch_tmp_bytes(&glwe_res_infos, &glwe_a_infos, key_infos);
|
||||
|
||||
glwe_in + glwe_out + ks
|
||||
}
|
||||
}
|
||||
|
||||
impl<DLwe: DataMut> LWE<DLwe> {
|
||||
pub fn keyswitch<A, DKs, B: Backend>(
|
||||
fn keyswitch<A, DKs, B: Backend>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
a: &LWE<A>,
|
||||
ksk: &LWESwitchingKeyPrepared<DKs, B>,
|
||||
a: &A,
|
||||
ksk: &K,
|
||||
scratch: &mut Scratch<B>,
|
||||
) where
|
||||
A: DataRef,
|
||||
A: LWEToRef,
|
||||
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,
|
||||
{
|
||||
#[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!(scratch.available() >= LWE::keyswitch_tmp_bytes(module, self, a, ksk));
|
||||
}
|
||||
|
||||
let max_k: TorusPrecision = self.k().max(a.k());
|
||||
|
||||
@@ -118,3 +91,9 @@ impl<DLwe: DataMut> LWE<DLwe> {
|
||||
self.sample_extract(&glwe_out);
|
||||
}
|
||||
}
|
||||
|
||||
impl LWE<Vec<u8>> {}
|
||||
|
||||
impl<DLwe: DataMut> LWE<DLwe> {
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ where
|
||||
fn dsize(&self) -> Dsize;
|
||||
fn rank_in(&self) -> Rank;
|
||||
fn rank_out(&self) -> Rank;
|
||||
fn gglwe_layout(&self) -> GGLWECiphertextLayout {
|
||||
GGLWECiphertextLayout {
|
||||
fn gglwe_layout(&self) -> GGLWELayout {
|
||||
GGLWELayout {
|
||||
n: self.n(),
|
||||
base2k: self.base2k(),
|
||||
k: self.k(),
|
||||
@@ -36,7 +36,7 @@ pub trait SetGGLWEInfos {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGLWECiphertextLayout {
|
||||
pub struct GGLWELayout {
|
||||
pub n: Degree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
@@ -46,7 +46,7 @@ pub struct GGLWECiphertextLayout {
|
||||
pub dsize: Dsize,
|
||||
}
|
||||
|
||||
impl LWEInfos for GGLWECiphertextLayout {
|
||||
impl LWEInfos for GGLWELayout {
|
||||
fn 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 {
|
||||
self.rank_out
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEInfos for GGLWECiphertextLayout {
|
||||
impl GGLWEInfos for GGLWELayout {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_in
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ where
|
||||
{
|
||||
fn dnum(&self) -> Dnum;
|
||||
fn dsize(&self) -> Dsize;
|
||||
fn ggsw_layout(&self) -> GGSWCiphertextLayout {
|
||||
GGSWCiphertextLayout {
|
||||
fn ggsw_layout(&self) -> GGSWLayout {
|
||||
GGSWLayout {
|
||||
n: self.n(),
|
||||
base2k: self.base2k(),
|
||||
k: self.k(),
|
||||
@@ -27,7 +27,7 @@ where
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGSWCiphertextLayout {
|
||||
pub struct GGSWLayout {
|
||||
pub n: Degree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
@@ -36,7 +36,7 @@ pub struct GGSWCiphertextLayout {
|
||||
pub dsize: Dsize,
|
||||
}
|
||||
|
||||
impl LWEInfos for GGSWCiphertextLayout {
|
||||
impl LWEInfos for GGSWLayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -49,13 +49,13 @@ impl LWEInfos for GGSWCiphertextLayout {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
impl GLWEInfos for GGSWCiphertextLayout {
|
||||
impl GLWEInfos for GGSWLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
impl GGSWInfos for GGSWCiphertextLayout {
|
||||
impl GGSWInfos for GGSWLayout {
|
||||
fn 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 {
|
||||
write!(
|
||||
f,
|
||||
"(GGSWCiphertext: k: {} base2k: {} dsize: {}) {}",
|
||||
"(GGSW: k: {} base2k: {} dsize: {}) {}",
|
||||
self.k().0,
|
||||
self.base2k().0,
|
||||
self.dsize().0,
|
||||
|
||||
@@ -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)]
|
||||
pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ pub trait LWEInfos {
|
||||
fn size(&self) -> usize {
|
||||
self.k().0.div_ceil(self.base2k().0) as usize
|
||||
}
|
||||
fn lwe_layout(&self) -> LWECiphertextLayout {
|
||||
LWECiphertextLayout {
|
||||
fn lwe_layout(&self) -> LWELayout {
|
||||
LWELayout {
|
||||
n: self.n(),
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
@@ -33,13 +33,13 @@ pub trait SetLWEInfos {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct LWECiphertextLayout {
|
||||
pub struct LWELayout {
|
||||
pub n: Degree,
|
||||
pub k: TorusPrecision,
|
||||
pub base2k: Base2K,
|
||||
}
|
||||
|
||||
impl LWEInfos for LWECiphertextLayout {
|
||||
impl LWEInfos for LWELayout {
|
||||
fn 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 {
|
||||
write!(
|
||||
f,
|
||||
"LWECiphertext: base2k={} k={}: {}",
|
||||
"LWE: base2k={} k={}: {}",
|
||||
self.base2k().0,
|
||||
self.k().0,
|
||||
self.data
|
||||
@@ -187,11 +187,11 @@ impl LWE<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWECiphertextToRef {
|
||||
pub trait LWEToRef {
|
||||
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]> {
|
||||
LWE {
|
||||
k: self.k,
|
||||
|
||||
@@ -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)]
|
||||
pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ where
|
||||
|
||||
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);
|
||||
|
||||
if pairs != 0 {
|
||||
@@ -359,7 +359,7 @@ where
|
||||
|
||||
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);
|
||||
|
||||
if pairs != 0 {
|
||||
|
||||
Reference in New Issue
Block a user