Add BDD Arithmetic (#98)

* Added some circuit, evaluation + some layouts

* Refactor + memory reduction

* Rows -> Dnum, Digits -> Dsize

* fix #96 + glwe_packing (indirectly CBT)

* clippy
This commit is contained in:
Jean-Philippe Bossuat
2025-10-08 17:52:03 +02:00
committed by GitHub
parent 37e13b965c
commit 6357a05509
119 changed files with 15996 additions and 1659 deletions

View File

@@ -1,5 +1,5 @@
use poulpy_core::layouts::{
Base2K, Degree, Digits, GGSWCiphertext, GGSWCiphertextLayout, GLWECiphertext, GLWECiphertextLayout, GLWESecret, Rank, Rows,
Base2K, Degree, Dnum, Dsize, GGSWCiphertext, GGSWCiphertextLayout, GLWECiphertext, GLWECiphertextLayout, GLWESecret, Rank,
TorusPrecision,
prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc},
};
@@ -35,16 +35,16 @@ fn bench_external_product_glwe_fft64(c: &mut Criterion) {
let k_ct_out: TorusPrecision = p.k_ct_out;
let k_ggsw: TorusPrecision = p.k_ggsw;
let rank: Rank = p.rank;
let digits: Digits = Digits(1);
let dsize: Dsize = Dsize(1);
let rows: Rows = Rows(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 {
n,
base2k,
k: k_ggsw,
rows,
digits,
dnum: dnum,
dsize: dsize,
rank,
};
@@ -143,16 +143,16 @@ fn bench_external_product_glwe_inplace_fft64(c: &mut Criterion) {
let k_glwe: TorusPrecision = p.k_ct;
let k_ggsw: TorusPrecision = p.k_ggsw;
let rank: Rank = p.rank;
let digits: Digits = Digits(1);
let dsize: Dsize = Dsize(1);
let rows: Rows = p.k_ct.div_ceil(p.base2k).into();
let dnum: Dnum = p.k_ct.div_ceil(p.base2k).into();
let ggsw_layout: GGSWCiphertextLayout = GGSWCiphertextLayout {
n,
base2k,
k: k_ggsw,
rows,
digits,
dnum: dnum,
dsize: dsize,
rank,
};

View File

@@ -1,6 +1,6 @@
use poulpy_core::layouts::{
Base2K, Degree, Digits, GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWESwitchingKey, GGLWESwitchingKeyLayout,
GLWECiphertext, GLWECiphertextLayout, GLWESecret, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWESwitchingKey, GGLWESwitchingKeyLayout,
GLWECiphertext, GLWECiphertextLayout, GLWESecret, Rank, TorusPrecision,
prepared::{GGLWEAutomorphismKeyPrepared, GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc},
};
use std::{hint::black_box, time::Duration};
@@ -22,7 +22,7 @@ fn bench_keyswitch_glwe_fft64(c: &mut Criterion) {
k_ct_in: TorusPrecision,
k_ct_out: TorusPrecision,
k_ksk: TorusPrecision,
digits: Digits,
dsize: Dsize,
rank: Rank,
}
@@ -35,17 +35,17 @@ fn bench_keyswitch_glwe_fft64(c: &mut Criterion) {
let k_glwe_out: TorusPrecision = p.k_ct_out;
let k_gglwe: TorusPrecision = p.k_ksk;
let rank: Rank = p.rank;
let digits: Digits = p.digits;
let dsize: Dsize = p.dsize;
let rows: Rows = p.k_ct_in.div_ceil(p.base2k.0 * digits.0).into();
let dnum: Dnum = p.k_ct_in.div_ceil(p.base2k.0 * dsize.0).into();
let gglwe_atk_layout: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout {
n,
base2k,
k: k_gglwe,
rows,
dnum,
rank,
digits,
dsize,
};
let glwe_in_layout: GLWECiphertextLayout = GLWECiphertextLayout {
@@ -111,15 +111,15 @@ fn bench_keyswitch_glwe_fft64(c: &mut Criterion) {
}
let base2k: usize = 19;
let digits = 1;
let dsize = 1;
let params_set: Vec<Params> = vec![Params {
log_n: 15,
base2k: base2k.into(),
k_ct_in: (874 - digits * base2k).into(),
k_ct_out: (874 - digits * base2k).into(),
k_ct_in: (874 - dsize * base2k).into(),
k_ct_out: (874 - dsize * base2k).into(),
k_ksk: 874_u32.into(),
digits: 1_u32.into(),
dsize: 1_u32.into(),
rank: 1_u32.into(),
}];
@@ -153,16 +153,16 @@ fn bench_keyswitch_glwe_inplace_fft64(c: &mut Criterion) {
let k_ct: TorusPrecision = p.k_ct;
let k_ksk: TorusPrecision = p.k_ksk;
let rank: Rank = p.rank;
let digits: Digits = Digits(1);
let dsize: Dsize = Dsize(1);
let rows: Rows = p.k_ct.div_ceil(p.base2k).into();
let dnum: Dnum = p.k_ct.div_ceil(p.base2k).into();
let gglwe_layout: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout {
n,
base2k,
k: k_ksk,
rows,
digits,
dnum,
dsize,
rank_in: rank,
rank_out: rank,
};

View File

@@ -7,7 +7,7 @@ use poulpy_hal::{
layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero},
};
use crate::layouts::{GGLWEAutomorphismKey, GGLWELayoutInfos, GLWECiphertext, prepared::GGLWEAutomorphismKeyPrepared};
use crate::layouts::{GGLWEAutomorphismKey, GGLWEInfos, GLWECiphertext, prepared::GGLWEAutomorphismKeyPrepared};
impl GGLWEAutomorphismKey<Vec<u8>> {
pub fn automorphism_scratch_space<B: Backend, OUT, IN, KEY>(
@@ -17,9 +17,9 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
key_infos: &KEY,
) -> usize
where
OUT: GGLWELayoutInfos,
IN: GGLWELayoutInfos,
KEY: GGLWELayoutInfos,
OUT: GGLWEInfos,
IN: GGLWEInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GLWECiphertext::keyswitch_scratch_space(
@@ -32,8 +32,8 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
pub fn automorphism_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GGLWELayoutInfos,
KEY: GGLWELayoutInfos,
OUT: GGLWEInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GGLWEAutomorphismKey::automorphism_scratch_space(module, out_infos, out_infos, key_infos)
@@ -102,7 +102,7 @@ impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> {
let p_inv: i64 = module.galois_element_inv(p);
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.rows().into()).for_each(|row_j| {
(0..self.dnum().into()).for_each(|row_j| {
let mut res_ct: GLWECiphertext<&mut [u8]> = self.at_mut(row_j, col_i);
let lhs_ct: GLWECiphertext<&[u8]> = lhs.at(row_j, col_i);
@@ -121,7 +121,7 @@ impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> {
});
});
(self.rows().min(lhs.rows()).into()..self.rows().into()).for_each(|row_i| {
(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();
});
@@ -175,7 +175,7 @@ impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> {
let p_inv = module.galois_element_inv(p);
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.rows().into()).for_each(|row_j| {
(0..self.dnum().into()).for_each(|row_j| {
let mut res_ct: GLWECiphertext<&mut [u8]> = self.at_mut(row_j, col_i);
// Reverts the automorphism X^{-k}: (-pi^{-1}_{k}(s)a + s, a) to (-sa + pi_{k}(s), a)

View File

@@ -9,7 +9,7 @@ use poulpy_hal::{
};
use crate::layouts::{
GGLWELayoutInfos, GGSWCiphertext, GGSWInfos, GLWECiphertext,
GGLWEInfos, GGSWCiphertext, GGSWInfos, GLWECiphertext,
prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared},
};
@@ -24,8 +24,8 @@ impl GGSWCiphertext<Vec<u8>> {
where
OUT: GGSWInfos,
IN: GGSWInfos,
KEY: GGLWELayoutInfos,
TSK: GGLWELayoutInfos,
KEY: GGLWEInfos,
TSK: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigAllocBytes
@@ -52,8 +52,8 @@ impl GGSWCiphertext<Vec<u8>> {
) -> usize
where
OUT: GGSWInfos,
KEY: GGLWELayoutInfos,
TSK: GGLWELayoutInfos,
KEY: GGLWEInfos,
TSK: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigAllocBytes
@@ -125,7 +125,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
};
// Keyswitch the j-th row of the col 0
(0..lhs.rows().into()).for_each(|row_i| {
(0..lhs.dnum().into()).for_each(|row_i| {
// Key-switch column 0, i.e.
// col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0pi^-1(s0) + a1pi^-1(s1) + a2pi^-1(s2)) + M[i], a0, a1, a2)
self.at_mut(row_i, 0)
@@ -160,7 +160,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnxBig<B> + TakeVecZnx,
{
// Keyswitch the j-th row of the col 0
(0..self.rows().into()).for_each(|row_i| {
(0..self.dnum().into()).for_each(|row_i| {
// Key-switch column 0, i.e.
// col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0pi^-1(s0) + a1pi^-1(s1) + a2pi^-1(s2)) + M[i], a0, a1, a2)
self.at_mut(row_i, 0)

View File

@@ -8,7 +8,7 @@ use poulpy_hal::{
layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig},
};
use crate::layouts::{GGLWELayoutInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared};
use crate::layouts::{GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared};
impl GLWECiphertext<Vec<u8>> {
pub fn automorphism_scratch_space<B: Backend, OUT, IN, KEY>(
@@ -20,7 +20,7 @@ impl GLWECiphertext<Vec<u8>> {
where
OUT: GLWEInfos,
IN: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
Self::keyswitch_scratch_space(module, out_infos, in_infos, key_infos)
@@ -29,7 +29,7 @@ impl GLWECiphertext<Vec<u8>> {
pub fn automorphism_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
Self::keyswitch_inplace_scratch_space(module, out_infos, key_infos)

View File

@@ -10,7 +10,7 @@ use poulpy_hal::{
use crate::{
TakeGLWECt,
layouts::{
GGLWELayoutInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWECiphertext, LWEInfos, Rank,
GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWECiphertext, LWEInfos, Rank,
prepared::GLWEToLWESwitchingKeyPrepared,
},
};
@@ -25,7 +25,7 @@ impl LWECiphertext<Vec<u8>> {
where
OUT: LWEInfos,
IN: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
let glwe_layout: GLWECiphertextLayout = GLWECiphertextLayout {

View File

@@ -10,7 +10,7 @@ use poulpy_hal::{
use crate::{
TakeGLWECt,
layouts::{
GGLWELayoutInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWECiphertext, LWEInfos,
GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWECiphertext, LWEInfos,
prepared::LWEToGLWESwitchingKeyPrepared,
},
};
@@ -25,7 +25,7 @@ impl GLWECiphertext<Vec<u8>> {
where
OUT: GLWEInfos,
IN: LWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
let ct: usize = GLWECiphertext::alloc_bytes_with(

View File

@@ -12,7 +12,7 @@ use poulpy_hal::{
use crate::{
TakeGLWESecret, TakeGLWESecretPrepared,
layouts::{
GGLWELayoutInfos, GLWEInfos, GLWESecret, LWEInfos,
GGLWEInfos, GLWEInfos, GLWESecret, LWEInfos,
compressed::{GGLWEAutomorphismKeyCompressed, GGLWESwitchingKeyCompressed},
},
};
@@ -20,7 +20,7 @@ use crate::{
impl GGLWEAutomorphismKeyCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + SvpPPolAllocBytes,
{
assert_eq!(module.n() as u32, infos.n());

View File

@@ -11,13 +11,13 @@ use poulpy_hal::{
use crate::{
TakeGLWEPt,
encryption::{SIGMA, glwe_encrypt_sk_internal},
layouts::{GGLWECiphertext, GGLWELayoutInfos, LWEInfos, compressed::GGLWECiphertextCompressed, prepared::GLWESecretPrepared},
layouts::{GGLWECiphertext, GGLWEInfos, LWEInfos, compressed::GGLWECiphertextCompressed, prepared::GLWESecretPrepared},
};
impl GGLWECiphertextCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
{
GGLWECiphertext::encrypt_sk_scratch_space(module, infos)
@@ -78,18 +78,18 @@ impl<D: DataMut> GGLWECiphertextCompressed<D> {
GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, self)
);
assert!(
self.rows().0 * self.digits().0 * self.base2k().0 <= self.k().0,
"self.rows() : {} * self.digits() : {} * self.base2k() : {} = {} >= self.k() = {}",
self.rows(),
self.digits(),
self.dnum().0 * self.dsize().0 * self.base2k().0 <= self.k().0,
"self.dnum() : {} * self.dsize() : {} * self.base2k() : {} = {} >= self.k() = {}",
self.dnum(),
self.dsize(),
self.base2k(),
self.rows().0 * self.digits().0 * self.base2k().0,
self.dnum().0 * self.dsize().0 * self.base2k().0,
self.k()
);
}
let rows: usize = self.rows().into();
let digits: usize = self.digits().into();
let dnum: usize = self.dnum().into();
let dsize: usize = self.dsize().into();
let base2k: usize = self.base2k().into();
let rank_in: usize = self.rank_in().into();
let cols: usize = (self.rank_out() + 1).into();
@@ -98,26 +98,20 @@ impl<D: DataMut> GGLWECiphertextCompressed<D> {
let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(self);
(0..rank_in).for_each(|col_i| {
(0..rows).for_each(|row_i| {
(0..dnum).for_each(|d_i| {
// Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
tmp_pt.data.zero(); // zeroes for next iteration
module.vec_znx_add_scalar_inplace(
&mut tmp_pt.data,
0,
(digits - 1) + row_i * digits,
pt,
col_i,
);
module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + d_i * dsize, pt, col_i);
module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scrach_1);
let (seed, mut source_xa_tmp) = source_xa.branch();
self.seed[col_i * rows + row_i] = seed;
self.seed[col_i * dnum + d_i] = seed;
glwe_encrypt_sk_internal(
module,
self.base2k().into(),
self.k().into(),
&mut self.at_mut(row_i, col_i).data,
&mut self.at_mut(d_i, col_i).data,
cols,
true,
Some((&tmp_pt, 0)),

View File

@@ -12,7 +12,7 @@ use poulpy_hal::{
use crate::{
TakeGLWESecretPrepared,
layouts::{
Degree, GGLWECiphertext, GGLWELayoutInfos, GLWEInfos, GLWESecret, LWEInfos, compressed::GGLWESwitchingKeyCompressed,
Degree, GGLWECiphertext, GGLWEInfos, GLWEInfos, GLWESecret, LWEInfos, compressed::GGLWESwitchingKeyCompressed,
prepared::GLWESecretPrepared,
},
};
@@ -20,7 +20,7 @@ use crate::{
impl GGLWESwitchingKeyCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + SvpPPolAllocBytes,
{
(GGLWECiphertext::encrypt_sk_scratch_space(module, infos) | ScalarZnx::alloc_bytes(module.n(), 1))

View File

@@ -12,7 +12,7 @@ use poulpy_hal::{
use crate::{
TakeGLWESecret, TakeGLWESecretPrepared,
layouts::{
GGLWELayoutInfos, GGLWETensorKey, GLWEInfos, GLWESecret, LWEInfos, Rank, compressed::GGLWETensorKeyCompressed,
GGLWEInfos, GGLWETensorKey, GLWEInfos, GLWESecret, LWEInfos, Rank, compressed::GGLWETensorKeyCompressed,
prepared::Prepare,
},
};
@@ -20,7 +20,7 @@ use crate::{
impl GGLWETensorKeyCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>:
SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + VecZnxBigAllocBytes,
{

View File

@@ -65,19 +65,19 @@ impl<DataSelf: DataMut> GGSWCiphertextCompressed<DataSelf> {
let base2k: usize = self.base2k().into();
let rank: usize = self.rank().into();
let cols: usize = rank + 1;
let digits: usize = self.digits().into();
let dsize: usize = self.dsize().into();
let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(&self.glwe_layout());
let mut source = Source::new(seed_xa);
self.seed = vec![[0u8; 32]; self.rows().0 as usize * cols];
self.seed = vec![[0u8; 32]; self.dnum().0 as usize * cols];
(0..self.rows().into()).for_each(|row_i| {
(0..self.dnum().into()).for_each(|row_i| {
tmp_pt.data.zero();
// Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (digits - 1) + row_i * digits, pt, 0);
module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, 0);
module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scratch_1);
(0..rank + 1).for_each(|col_j| {

View File

@@ -11,13 +11,13 @@ use poulpy_hal::{
use crate::{
TakeGLWESecret, TakeGLWESecretPrepared,
layouts::{GGLWEAutomorphismKey, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, GLWESecret, LWEInfos},
layouts::{GGLWEAutomorphismKey, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, GLWESecret, LWEInfos},
};
impl GGLWEAutomorphismKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
{
assert_eq!(
@@ -30,7 +30,7 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
pub fn encrypt_pk_scratch_space<B: Backend, A>(module: &Module<B>, _infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
_infos.rank_in(),

View File

@@ -10,13 +10,13 @@ use poulpy_hal::{
use crate::{
TakeGLWEPt,
layouts::{GGLWECiphertext, GGLWELayoutInfos, GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared},
layouts::{GGLWECiphertext, GGLWEInfos, GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared},
};
impl GGLWECiphertext<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
{
GLWECiphertext::encrypt_sk_scratch_space(module, &infos.glwe_layout())
@@ -25,7 +25,7 @@ impl GGLWECiphertext<Vec<u8>> {
pub fn encrypt_pk_scratch_space<B: Backend, A>(_module: &Module<B>, _infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
unimplemented!()
}
@@ -87,18 +87,18 @@ impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> {
GGLWECiphertext::encrypt_sk_scratch_space(module, self)
);
assert!(
self.rows().0 * self.digits().0 * self.base2k().0 <= self.k().0,
"self.rows() : {} * self.digits() : {} * self.base2k() : {} = {} >= self.k() = {}",
self.rows(),
self.digits(),
self.dnum().0 * self.dsize().0 * self.base2k().0 <= self.k().0,
"self.dnum() : {} * self.dsize() : {} * self.base2k() : {} = {} >= self.k() = {}",
self.dnum(),
self.dsize(),
self.base2k(),
self.rows().0 * self.digits().0 * self.base2k().0,
self.dnum().0 * self.dsize().0 * self.base2k().0,
self.k()
);
}
let rows: usize = self.rows().into();
let digits: usize = self.digits().into();
let dnum: usize = self.dnum().into();
let dsize: usize = self.dsize().into();
let base2k: usize = self.base2k().into();
let rank_in: usize = self.rank_in().into();
@@ -115,16 +115,10 @@ impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> {
// (-(a*s) + s0, a)
// (-(b*s) + s1, b)
(0..rank_in).for_each(|col_i| {
(0..rows).for_each(|row_i| {
(0..dnum).for_each(|row_i| {
// Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
tmp_pt.data.zero(); // zeroes for next iteration
module.vec_znx_add_scalar_inplace(
&mut tmp_pt.data,
0,
(digits - 1) + row_i * digits,
pt,
col_i,
);
module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, col_i);
module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scrach_1);
// rlwe encrypt of vec_znx_pt into vec_znx_ct

View File

@@ -12,15 +12,14 @@ use poulpy_hal::{
use crate::{
TakeGLWESecretPrepared,
layouts::{
Degree, GGLWECiphertext, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, GLWESecret, LWEInfos,
prepared::GLWESecretPrepared,
Degree, GGLWECiphertext, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, GLWESecret, LWEInfos, prepared::GLWESecretPrepared,
},
};
impl GGLWESwitchingKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
{
(GGLWECiphertext::encrypt_sk_scratch_space(module, infos) | ScalarZnx::alloc_bytes(module.n(), 1))
@@ -30,7 +29,7 @@ impl GGLWESwitchingKey<Vec<u8>> {
pub fn encrypt_pk_scratch_space<B: Backend, A>(module: &Module<B>, _infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
GGLWECiphertext::encrypt_pk_scratch_space(module, _infos)
}

View File

@@ -12,7 +12,7 @@ use poulpy_hal::{
use crate::{
TakeGLWESecret, TakeGLWESecretPrepared,
layouts::{
Degree, GGLWELayoutInfos, GGLWESwitchingKey, GGLWETensorKey, GLWEInfos, GLWESecret, LWEInfos, Rank,
Degree, GGLWEInfos, GGLWESwitchingKey, GGLWETensorKey, GLWEInfos, GLWESecret, LWEInfos, Rank,
prepared::{GLWESecretPrepared, Prepare},
},
};
@@ -20,7 +20,7 @@ use crate::{
impl GGLWETensorKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>:
SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + VecZnxBigAllocBytes,
{

View File

@@ -65,15 +65,15 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
let base2k: usize = self.base2k().into();
let rank: usize = self.rank().into();
let digits: usize = self.digits().into();
let dsize: usize = self.dsize().into();
let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(&self.glwe_layout());
(0..self.rows().into()).for_each(|row_i| {
(0..self.dnum().into()).for_each(|row_i| {
tmp_pt.data.zero();
// Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (digits - 1) + row_i * digits, pt, 0);
module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, 0);
module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scratch_1);
(0..rank + 1).for_each(|col_j| {

View File

@@ -11,16 +11,13 @@ use poulpy_hal::{
use crate::{
TakeGLWESecret, TakeGLWESecretPrepared,
layouts::{
GGLWELayoutInfos, GGLWESwitchingKey, GLWESecret, GLWEToLWESwitchingKey, LWEInfos, LWESecret, Rank,
prepared::GLWESecretPrepared,
},
layouts::{GGLWEInfos, GGLWESwitchingKey, GLWESecret, GLWEToLWEKey, LWEInfos, LWESecret, Rank, prepared::GLWESecretPrepared},
};
impl GLWEToLWESwitchingKey<Vec<u8>> {
impl GLWEToLWEKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
{
GLWESecretPrepared::alloc_bytes_with(module, infos.rank_in())
@@ -29,7 +26,7 @@ impl GLWEToLWESwitchingKey<Vec<u8>> {
}
}
impl<D: DataMut> GLWEToLWESwitchingKey<D> {
impl<D: DataMut> GLWEToLWEKey<D> {
#[allow(clippy::too_many_arguments)]
pub fn encrypt_sk<DLwe, DGlwe, B: Backend>(
&mut self,

View File

@@ -12,7 +12,7 @@ use poulpy_hal::{
use crate::{
TakeGLWESecret, TakeGLWESecretPrepared,
layouts::{
Degree, GGLWELayoutInfos, GGLWESwitchingKey, GLWESecret, LWEInfos, LWESecret, LWESwitchingKey, Rank,
Degree, GGLWEInfos, GGLWESwitchingKey, GLWESecret, LWEInfos, LWESecret, LWESwitchingKey, Rank,
prepared::GLWESecretPrepared,
},
};
@@ -20,13 +20,13 @@ use crate::{
impl LWESwitchingKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWESwitchingKey"
"dsize > 1 is not supported for LWESwitchingKey"
);
debug_assert_eq!(
infos.rank_in().0,

View File

@@ -11,13 +11,13 @@ use poulpy_hal::{
use crate::{
TakeGLWESecret, TakeGLWESecretPrepared,
layouts::{Degree, GGLWELayoutInfos, GGLWESwitchingKey, GLWESecret, LWEInfos, LWESecret, LWEToGLWESwitchingKey, Rank},
layouts::{Degree, GGLWEInfos, GGLWESwitchingKey, GLWESecret, LWEInfos, LWESecret, LWEToGLWESwitchingKey, Rank},
};
impl LWEToGLWESwitchingKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
{
debug_assert_eq!(

View File

@@ -7,7 +7,7 @@ use poulpy_hal::{
layouts::{Backend, DataMut, DataRef, Module, Scratch},
};
use crate::layouts::{GGLWEAutomorphismKey, GGLWELayoutInfos, GGLWESwitchingKey, GGSWInfos, prepared::GGSWCiphertextPrepared};
use crate::layouts::{GGLWEAutomorphismKey, GGLWEInfos, GGLWESwitchingKey, GGSWInfos, prepared::GGSWCiphertextPrepared};
impl GGLWEAutomorphismKey<Vec<u8>> {
pub fn external_product_scratch_space<B: Backend, OUT, IN, GGSW>(
@@ -17,8 +17,8 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
ggsw_infos: &GGSW,
) -> usize
where
OUT: GGLWELayoutInfos,
IN: GGLWELayoutInfos,
OUT: GGLWEInfos,
IN: GGLWEInfos,
GGSW: GGSWInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes,
{
@@ -31,7 +31,7 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
ggsw_infos: &GGSW,
) -> usize
where
OUT: GGLWELayoutInfos,
OUT: GGLWEInfos,
GGSW: GGSWInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes,
{

View File

@@ -7,7 +7,7 @@ use poulpy_hal::{
layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero},
};
use crate::layouts::{GGLWELayoutInfos, GGLWESwitchingKey, GGSWInfos, GLWECiphertext, prepared::GGSWCiphertextPrepared};
use crate::layouts::{GGLWEInfos, GGLWESwitchingKey, GGSWInfos, GLWECiphertext, prepared::GGSWCiphertextPrepared};
impl GGLWESwitchingKey<Vec<u8>> {
pub fn external_product_scratch_space<B: Backend, OUT, IN, GGSW>(
@@ -17,8 +17,8 @@ impl GGLWESwitchingKey<Vec<u8>> {
ggsw_infos: &GGSW,
) -> usize
where
OUT: GGLWELayoutInfos,
IN: GGLWELayoutInfos,
OUT: GGLWEInfos,
IN: GGLWEInfos,
GGSW: GGSWInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes,
{
@@ -36,7 +36,7 @@ impl GGLWESwitchingKey<Vec<u8>> {
ggsw_infos: &GGSW,
) -> usize
where
OUT: GGLWELayoutInfos,
OUT: GGLWEInfos,
GGSW: GGSWInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes,
{
@@ -91,13 +91,13 @@ impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> {
}
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.rows().into()).for_each(|row_j| {
(0..self.dnum().into()).for_each(|row_j| {
self.at_mut(row_j, col_i)
.external_product(module, &lhs.at(row_j, col_i), rhs, scratch);
});
});
(self.rows().min(lhs.rows()).into()..self.rows().into()).for_each(|row_i| {
(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();
});
@@ -135,7 +135,7 @@ impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> {
}
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.rows().into()).for_each(|row_j| {
(0..self.dnum().into()).for_each(|row_j| {
self.at_mut(row_j, col_i)
.external_product_inplace(module, rhs, scratch);
});

View File

@@ -89,14 +89,14 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
assert!(scratch.available() >= GGSWCiphertext::external_product_scratch_space(module, self, lhs, rhs))
}
let min_rows: usize = self.rows().min(lhs.rows()).into();
let min_dnum: usize = self.dnum().min(lhs.dnum()).into();
(0..(self.rank() + 1).into()).for_each(|col_i| {
(0..min_rows).for_each(|row_j| {
(0..min_dnum).for_each(|row_j| {
self.at_mut(row_j, col_i)
.external_product(module, &lhs.at(row_j, col_i), rhs, scratch);
});
(min_rows..self.rows().into()).for_each(|row_i| {
(min_dnum..self.dnum().into()).for_each(|row_i| {
self.at_mut(row_i, col_i).data.zero();
});
});
@@ -134,7 +134,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
}
(0..(self.rank() + 1).into()).for_each(|col_i| {
(0..self.rows().into()).for_each(|row_j| {
(0..self.dnum().into()).for_each(|row_j| {
self.at_mut(row_j, col_i)
.external_product_inplace(module, rhs, scratch);
});

View File

@@ -7,7 +7,13 @@ use poulpy_hal::{
layouts::{Backend, DataMut, DataRef, DataViewMut, Module, Scratch, VecZnx, VecZnxBig},
};
use crate::layouts::{GGSWInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGSWCiphertextPrepared};
use crate::{
GLWEExternalProduct, GLWEExternalProductInplace,
layouts::{
GGSWInfos, GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEInfos, LWEInfos,
prepared::{GGSWCiphertextPrepared, GGSWCiphertextPreparedToRef},
},
};
impl GLWECiphertext<Vec<u8>> {
#[allow(clippy::too_many_arguments)]
@@ -26,7 +32,7 @@ impl GLWECiphertext<Vec<u8>> {
let in_size: usize = in_infos
.k()
.div_ceil(apply_infos.base2k())
.div_ceil(apply_infos.digits().into()) as usize;
.div_ceil(apply_infos.dsize().into()) as usize;
let out_size: usize = out_infos.size();
let ggsw_size: usize = apply_infos.size();
let res_dft: usize = module.vec_znx_dft_alloc_bytes((apply_infos.rank() + 1).into(), ggsw_size);
@@ -71,70 +77,221 @@ impl<DataSelf: DataMut> GLWECiphertext<DataSelf> {
rhs: &GGSWCiphertextPrepared<DataRhs, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxNormalizeTmpBytes
+ VecZnxDftApply<B>
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalize<B>,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
Module<B>: GLWEExternalProduct<B>,
{
module.external_product(self, lhs, rhs, scratch);
}
pub fn external_product_inplace<DataRhs: DataRef, B: Backend>(
&mut self,
module: &Module<B>,
rhs: &GGSWCiphertextPrepared<DataRhs, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWEExternalProductInplace<B>,
{
module.external_product_inplace(self, rhs, scratch);
}
}
impl<BE: Backend> GLWEExternalProductInplace<BE> for Module<BE>
where
Module<BE>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxNormalizeTmpBytes
+ VecZnxDftApply<BE>
+ VmpApplyDftToDft<BE>
+ VmpApplyDftToDftAdd<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxBigNormalize<BE>
+ VecZnxNormalize<BE>,
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx,
{
fn external_product_inplace<R, D>(&self, res: &mut R, ggsw: &D, scratch: &mut Scratch<BE>)
where
R: GLWECiphertextToMut,
D: GGSWCiphertextPreparedToRef<BE>,
{
let res: &mut GLWECiphertext<&mut [u8]> = &mut res.to_mut();
let rhs: &GGSWCiphertextPrepared<&[u8], BE> = &ggsw.to_ref();
let basek_in: usize = res.base2k().into();
let basek_ggsw: usize = rhs.base2k().into();
#[cfg(debug_assertions)]
{
use poulpy_hal::api::ScratchAvailable;
assert_eq!(rhs.rank(), res.rank());
assert_eq!(rhs.n(), res.n());
assert!(scratch.available() >= GLWECiphertext::external_product_inplace_scratch_space(self, res, rhs));
}
let cols: usize = (rhs.rank() + 1).into();
let dsize: usize = rhs.dsize().into();
let a_size: usize = (res.size() * basek_in).div_ceil(basek_ggsw);
let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(res.n().into(), cols, rhs.size()); // Todo optimise
let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(res.n().into(), cols, a_size.div_ceil(dsize));
a_dft.data_mut().fill(0);
if basek_in == basek_ggsw {
for di in 0..dsize {
// (lhs.size() + di) / dsize = (a - (digit - di - 1)).div_ceil(dsize)
a_dft.set_size((res.size() + di) / dsize);
// Small optimization for dsize > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}.
// As such we can ignore the last dsize-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last dsize-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(rhs.size() - ((dsize - di) as isize - 2).max(0) as usize);
for j in 0..cols {
self.vec_znx_dft_apply(dsize, dsize - 1 - di, &mut a_dft, j, &res.data, j);
}
if di == 0 {
self.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_2);
} else {
self.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);
}
}
} else {
let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(self.n(), cols, a_size);
for j in 0..cols {
self.vec_znx_normalize(
basek_ggsw,
&mut a_conv,
j,
basek_in,
&res.data,
j,
scratch_3,
);
}
for di in 0..dsize {
// (lhs.size() + di) / dsize = (a - (digit - di - 1)).div_ceil(dsize)
a_dft.set_size((res.size() + di) / dsize);
// Small optimization for dsize > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}.
// As such we can ignore the last dsize-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last dsize-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(rhs.size() - ((dsize - di) as isize - 2).max(0) as usize);
for j in 0..cols {
self.vec_znx_dft_apply(dsize, dsize - 1 - di, &mut a_dft, j, &res.data, j);
}
if di == 0 {
self.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_2);
} else {
self.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);
}
}
}
let res_big: VecZnxBig<&mut [u8], BE> = self.vec_znx_idft_apply_consume(res_dft);
for j in 0..cols {
self.vec_znx_big_normalize(
basek_in,
&mut res.data,
j,
basek_ggsw,
&res_big,
j,
scratch_1,
);
}
}
}
impl<BE: Backend> GLWEExternalProduct<BE> for Module<BE>
where
Module<BE>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxNormalizeTmpBytes
+ VecZnxDftApply<BE>
+ VmpApplyDftToDft<BE>
+ VmpApplyDftToDftAdd<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxBigNormalize<BE>
+ VecZnxNormalize<BE>,
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx,
{
fn external_product<R, A, D>(&self, res: &mut R, lhs: &A, rhs: &D, scratch: &mut Scratch<BE>)
where
R: GLWECiphertextToMut,
A: GLWECiphertextToRef,
D: GGSWCiphertextPreparedToRef<BE>,
{
let res: &mut GLWECiphertext<&mut [u8]> = &mut res.to_mut();
let lhs: &GLWECiphertext<&[u8]> = &lhs.to_ref();
let rhs: &GGSWCiphertextPrepared<&[u8], BE> = &rhs.to_ref();
let basek_in: usize = lhs.base2k().into();
let basek_ggsw: usize = rhs.base2k().into();
let basek_out: usize = self.base2k().into();
let basek_out: usize = res.base2k().into();
#[cfg(debug_assertions)]
{
use poulpy_hal::api::ScratchAvailable;
assert_eq!(rhs.rank(), lhs.rank());
assert_eq!(rhs.rank(), self.rank());
assert_eq!(rhs.n(), self.n());
assert_eq!(lhs.n(), self.n());
assert!(scratch.available() >= GLWECiphertext::external_product_scratch_space(module, self, lhs, rhs));
assert_eq!(rhs.rank(), res.rank());
assert_eq!(rhs.n(), res.n());
assert_eq!(lhs.n(), res.n());
assert!(scratch.available() >= GLWECiphertext::external_product_scratch_space(self, res, lhs, rhs));
}
let cols: usize = (rhs.rank() + 1).into();
let digits: usize = rhs.digits().into();
let dsize: usize = rhs.dsize().into();
let a_size: usize = (lhs.size() * basek_in).div_ceil(basek_ggsw);
let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), cols, rhs.size()); // Todo optimise
let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(self.n().into(), cols, a_size.div_ceil(digits));
let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n(), cols, rhs.size()); // Todo optimise
let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(self.n(), cols, a_size.div_ceil(dsize));
a_dft.data_mut().fill(0);
if basek_in == basek_ggsw {
for di in 0..digits {
// (lhs.size() + di) / digits = (a - (digit - di - 1)).div_ceil(digits)
a_dft.set_size((lhs.size() + di) / digits);
for di in 0..dsize {
// (lhs.size() + di) / dsize = (a - (digit - di - 1)).div_ceil(dsize)
a_dft.set_size((lhs.size() + di) / dsize);
// Small optimization for digits > 2
// Small optimization for dsize > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}.
// As such we can ignore the last digits-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last digits-1 limbs, but this introduce
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}.
// As such we can ignore the last dsize-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last dsize-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize);
res_dft.set_size(rhs.size() - ((dsize - di) as isize - 2).max(0) as usize);
for j in 0..cols {
module.vec_znx_dft_apply(digits, digits - 1 - di, &mut a_dft, j, &lhs.data, j);
self.vec_znx_dft_apply(dsize, dsize - 1 - di, &mut a_dft, j, &lhs.data, j);
}
if di == 0 {
module.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_2);
self.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_2);
} else {
module.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);
self.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);
}
}
} else {
let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(module.n(), cols, a_size);
let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(self.n(), cols, a_size);
for j in 0..cols {
module.vec_znx_normalize(
self.vec_znx_normalize(
basek_ggsw,
&mut a_conv,
j,
@@ -145,37 +302,37 @@ impl<DataSelf: DataMut> GLWECiphertext<DataSelf> {
);
}
for di in 0..digits {
// (lhs.size() + di) / digits = (a - (digit - di - 1)).div_ceil(digits)
a_dft.set_size((a_size + di) / digits);
for di in 0..dsize {
// (lhs.size() + di) / dsize = (a - (digit - di - 1)).div_ceil(dsize)
a_dft.set_size((a_size + di) / dsize);
// Small optimization for digits > 2
// Small optimization for dsize > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}.
// As such we can ignore the last digits-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last digits-1 limbs, but this introduce
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}.
// As such we can ignore the last dsize-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last dsize-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize);
res_dft.set_size(rhs.size() - ((dsize - di) as isize - 2).max(0) as usize);
for j in 0..cols {
module.vec_znx_dft_apply(digits, digits - 1 - di, &mut a_dft, j, &a_conv, j);
self.vec_znx_dft_apply(dsize, dsize - 1 - di, &mut a_dft, j, &a_conv, j);
}
if di == 0 {
module.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_3);
self.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_3);
} else {
module.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_3);
self.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_3);
}
}
}
let res_big: VecZnxBig<&mut [u8], B> = module.vec_znx_idft_apply_consume(res_dft);
let res_big: VecZnxBig<&mut [u8], BE> = self.vec_znx_idft_apply_consume(res_dft);
(0..cols).for_each(|i| {
module.vec_znx_big_normalize(
self.vec_znx_big_normalize(
basek_out,
&mut self.data,
res.data_mut(),
i,
basek_ggsw,
&res_big,
@@ -184,120 +341,4 @@ impl<DataSelf: DataMut> GLWECiphertext<DataSelf> {
);
});
}
pub fn external_product_inplace<DataRhs: DataRef, B: Backend>(
&mut self,
module: &Module<B>,
rhs: &GGSWCiphertextPrepared<DataRhs, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxNormalizeTmpBytes
+ VecZnxDftApply<B>
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigNormalize<B>
+ VecZnxNormalize<B>,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
{
let basek_in: usize = self.base2k().into();
let basek_ggsw: usize = rhs.base2k().into();
#[cfg(debug_assertions)]
{
use poulpy_hal::api::ScratchAvailable;
assert_eq!(rhs.rank(), self.rank());
assert_eq!(rhs.n(), self.n());
assert!(scratch.available() >= GLWECiphertext::external_product_inplace_scratch_space(module, self, rhs,));
}
let cols: usize = (rhs.rank() + 1).into();
let digits: usize = rhs.digits().into();
let a_size: usize = (self.size() * basek_in).div_ceil(basek_ggsw);
let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), cols, rhs.size()); // Todo optimise
let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(self.n().into(), cols, a_size.div_ceil(digits));
a_dft.data_mut().fill(0);
if basek_in == basek_ggsw {
for di in 0..digits {
// (lhs.size() + di) / digits = (a - (digit - di - 1)).div_ceil(digits)
a_dft.set_size((self.size() + di) / digits);
// Small optimization for digits > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}.
// As such we can ignore the last digits-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last digits-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize);
for j in 0..cols {
module.vec_znx_dft_apply(digits, digits - 1 - di, &mut a_dft, j, &self.data, j);
}
if di == 0 {
module.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_2);
} else {
module.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);
}
}
} else {
let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(module.n(), cols, a_size);
for j in 0..cols {
module.vec_znx_normalize(
basek_ggsw,
&mut a_conv,
j,
basek_in,
&self.data,
j,
scratch_3,
);
}
for di in 0..digits {
// (lhs.size() + di) / digits = (a - (digit - di - 1)).div_ceil(digits)
a_dft.set_size((self.size() + di) / digits);
// Small optimization for digits > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}.
// As such we can ignore the last digits-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last digits-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(rhs.size() - ((digits - di) as isize - 2).max(0) as usize);
for j in 0..cols {
module.vec_znx_dft_apply(digits, digits - 1 - di, &mut a_dft, j, &self.data, j);
}
if di == 0 {
module.vmp_apply_dft_to_dft(&mut res_dft, &a_dft, &rhs.data, scratch_2);
} else {
module.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);
}
}
}
let res_big: VecZnxBig<&mut [u8], B> = module.vec_znx_idft_apply_consume(res_dft);
for j in 0..cols {
module.vec_znx_big_normalize(
basek_in,
&mut self.data,
j,
basek_ggsw,
&res_big,
j,
scratch_1,
);
}
}
}

View File

@@ -1,4 +1,23 @@
use poulpy_hal::layouts::{Backend, Scratch};
use crate::layouts::{GLWECiphertextToMut, GLWECiphertextToRef, prepared::GGSWCiphertextPreparedToRef};
mod gglwe_atk;
mod gglwe_ksk;
mod ggsw_ct;
mod glwe_ct;
pub trait GLWEExternalProduct<BE: Backend> {
fn external_product<R, A, D>(&self, res: &mut R, a: &A, ggsw: &D, scratch: &mut Scratch<BE>)
where
R: GLWECiphertextToMut,
A: GLWECiphertextToRef,
D: GGSWCiphertextPreparedToRef<BE>;
}
pub trait GLWEExternalProductInplace<BE: Backend> {
fn external_product_inplace<R, D>(&self, res: &mut R, ggsw: &D, scratch: &mut Scratch<BE>)
where
R: GLWECiphertextToMut,
D: GGSWCiphertextPreparedToRef<BE>;
}

View File

@@ -4,16 +4,16 @@ use poulpy_hal::{
api::{
ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace,
VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy,
VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNegateInplace, VecZnxNormalize,
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub,
VecZnxSubInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace,
VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace,
VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,
},
layouts::{Backend, DataMut, DataRef, Module, Scratch},
};
use crate::{
GLWEOperations, TakeGLWECt,
layouts::{GGLWELayoutInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared},
layouts::{GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared},
};
/// [GLWEPacker] enables only the fly GLWE packing
@@ -93,7 +93,7 @@ impl GLWEPacker {
pub fn scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
pack_core_scratch_space(module, out_infos, key_infos)
@@ -180,7 +180,7 @@ impl GLWEPacker {
fn pack_core_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
combine_scratch_space(module, out_infos, key_infos)
@@ -271,7 +271,7 @@ fn pack_core<D: DataRef, DataAK: DataRef, B: Backend>(
fn combine_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GLWECiphertext::alloc_bytes(out_infos)
@@ -390,3 +390,165 @@ fn combine<D: DataRef, DataAK: DataRef, B: Backend>(
acc.value = true;
}
}
/// Packs [x_0: GLWE(m_0), x_1: GLWE(m_1), ..., x_i: GLWE(m_i)]
/// to [0: GLWE(m_0 * X^x_0 + m_1 * X^x_1 + ... + m_i * X^x_i)]
pub fn glwe_packing<D: DataMut, ATK, B: Backend>(
module: &Module<B>,
cts: &mut HashMap<usize, &mut GLWECiphertext<D>>,
log_gap_out: usize,
auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<ATK, B>>,
scratch: &mut Scratch<B>,
) where
ATK: DataRef,
Module<B>: VecZnxRotateInplace<B>
+ VecZnxNormalizeInplace<B>
+ VecZnxNormalizeTmpBytes
+ VecZnxSwitchRing
+ VecZnxBigAutomorphismInplace<B>
+ VecZnxRshInplace<B>
+ VecZnxDftCopy<B>
+ VecZnxIdftApplyTmpA<B>
+ VecZnxSub
+ VecZnxAddInplace
+ VecZnxNegateInplace
+ VecZnxCopy
+ VecZnxSubInplace
+ VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxAutomorphismInplace<B>
+ VecZnxBigSubSmallNegateInplace<B>
+ VecZnxRotate
+ VecZnxNormalize<B>,
Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable,
{
#[cfg(debug_assertions)]
{
assert!(*cts.keys().max().unwrap() < module.n())
}
let log_n: usize = module.log_n();
(0..log_n - log_gap_out).for_each(|i| {
let t: usize = (1 << log_n).min(1 << (log_n - 1 - i));
let auto_key: &GGLWEAutomorphismKeyPrepared<ATK, B> = if i == 0 {
auto_keys.get(&-1).unwrap()
} else {
auto_keys.get(&module.galois_element(1 << (i - 1))).unwrap()
};
(0..t).for_each(|j| {
let mut a: Option<&mut GLWECiphertext<D>> = cts.remove(&j);
let mut b: Option<&mut GLWECiphertext<D>> = cts.remove(&(j + t));
pack_internal(module, &mut a, &mut b, i, auto_key, scratch);
if let Some(a) = a {
cts.insert(j, a);
} else if let Some(b) = b {
cts.insert(j, b);
}
});
});
}
#[allow(clippy::too_many_arguments)]
fn pack_internal<A: DataMut, D: DataMut, DataAK: DataRef, B: Backend>(
module: &Module<B>,
a: &mut Option<&mut GLWECiphertext<A>>,
b: &mut Option<&mut GLWECiphertext<D>>,
i: usize,
auto_key: &GGLWEAutomorphismKeyPrepared<DataAK, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: VecZnxRotateInplace<B>
+ VecZnxNormalizeInplace<B>
+ VecZnxNormalizeTmpBytes
+ VecZnxBigAutomorphismInplace<B>
+ VecZnxRshInplace<B>
+ VecZnxDftCopy<B>
+ VecZnxIdftApplyTmpA<B>
+ VecZnxSub
+ VecZnxAddInplace
+ VecZnxNegateInplace
+ VecZnxCopy
+ VecZnxSubInplace
+ VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes
+ VmpApplyDftToDft<B>
+ VmpApplyDftToDftAdd<B>
+ VecZnxDftApply<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>
+ VecZnxAutomorphismInplace<B>
+ VecZnxBigSubSmallNegateInplace<B>
+ VecZnxRotate
+ VecZnxNormalize<B>,
Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable,
{
// Goal is to evaluate: a = a + b*X^t + phi(a - b*X^t))
// We also use the identity: AUTO(a * X^t, g) = -X^t * AUTO(a, g)
// where t = 2^(log_n - i - 1) and g = 5^{2^(i - 1)}
// Different cases for wether a and/or b are zero.
//
// Implicite RSH without modulus switch, introduces extra I(X) * Q/2 on decryption.
// Necessary so that the scaling of the plaintext remains constant.
// It however is ok to do so here because coefficients are eventually
// either mapped to garbage or twice their value which vanishes I(X)
// since 2*(I(X) * Q/2) = I(X) * Q = 0 mod Q.
if let Some(a) = a.as_deref_mut() {
let t: i64 = 1 << (a.n().log2() - i - 1);
if let Some(b) = b.as_deref_mut() {
let (mut tmp_b, scratch_1) = scratch.take_glwe_ct(a);
// a = a * X^-t
a.rotate_inplace(module, -t, scratch_1);
// tmp_b = a * X^-t - b
tmp_b.sub(module, a, b);
tmp_b.rsh(module, 1, scratch_1);
// a = a * X^-t + b
a.add_inplace(module, b);
a.rsh(module, 1, scratch_1);
tmp_b.normalize_inplace(module, scratch_1);
// tmp_b = phi(a * X^-t - b)
tmp_b.automorphism_inplace(module, auto_key, scratch_1);
// a = a * X^-t + b - phi(a * X^-t - b)
a.sub_inplace_ab(module, &tmp_b);
a.normalize_inplace(module, scratch_1);
// a = a + b * X^t - phi(a * X^-t - b) * X^t
// = a + b * X^t - phi(a * X^-t - b) * - phi(X^t)
// = a + b * X^t + phi(a - b * X^t)
a.rotate_inplace(module, t, scratch_1);
} else {
a.rsh(module, 1, scratch);
// a = a + phi(a)
a.automorphism_add_inplace(module, auto_key, scratch);
}
} else if let Some(b) = b.as_deref_mut() {
let t: i64 = 1 << (b.n().log2() - i - 1);
let (mut tmp_b, scratch_1) = scratch.take_glwe_ct(b);
tmp_b.rotate(module, t, b);
tmp_b.rsh(module, 1, scratch_1);
// a = (b* X^t - phi(b* X^t))
b.automorphism_sub_negate(module, &tmp_b, auto_key, scratch_1);
}
}

View File

@@ -12,8 +12,7 @@ use poulpy_hal::{
use crate::{
TakeGLWECt,
layouts::{
Base2K, GGLWELayoutInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWEInfos,
prepared::GGLWEAutomorphismKeyPrepared,
Base2K, GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared,
},
operations::GLWEOperations,
};
@@ -40,7 +39,7 @@ impl GLWECiphertext<Vec<u8>> {
where
OUT: GLWEInfos,
IN: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
let trace: usize = Self::automorphism_inplace_scratch_space(module, out_infos, key_infos);
@@ -59,7 +58,7 @@ impl GLWECiphertext<Vec<u8>> {
pub fn trace_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
Self::trace_scratch_space(module, out_infos, out_infos, key_infos)

View File

@@ -8,7 +8,7 @@ use poulpy_hal::{
};
use crate::layouts::{
GGLWEAutomorphismKey, GGLWELayoutInfos, GGLWESwitchingKey, GLWECiphertext, GLWEInfos,
GGLWEAutomorphismKey, GGLWEInfos, GGLWESwitchingKey, GLWECiphertext, GLWEInfos,
prepared::{GGLWEAutomorphismKeyPrepared, GGLWESwitchingKeyPrepared},
};
@@ -20,9 +20,9 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
key_infos: &KEY,
) -> usize
where
OUT: GGLWELayoutInfos,
IN: GGLWELayoutInfos,
KEY: GGLWELayoutInfos,
OUT: GGLWEInfos,
IN: GGLWEInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GGLWESwitchingKey::keyswitch_scratch_space(module, out_infos, in_infos, key_infos)
@@ -30,8 +30,8 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
pub fn keyswitch_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize
where
OUT: GGLWELayoutInfos,
KEY: GGLWELayoutInfos,
OUT: GGLWEInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GGLWESwitchingKey::keyswitch_inplace_scratch_space(module, out_infos, key_infos)
@@ -93,9 +93,9 @@ impl GGLWESwitchingKey<Vec<u8>> {
key_apply: &KEY,
) -> usize
where
OUT: GGLWELayoutInfos,
IN: GGLWELayoutInfos,
KEY: GGLWELayoutInfos,
OUT: GGLWEInfos,
IN: GGLWEInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GLWECiphertext::keyswitch_scratch_space(module, out_infos, in_infos, key_apply)
@@ -103,8 +103,8 @@ impl GGLWESwitchingKey<Vec<u8>> {
pub fn keyswitch_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_apply: &KEY) -> usize
where
OUT: GGLWELayoutInfos + GLWEInfos,
KEY: GGLWELayoutInfos + GLWEInfos,
OUT: GGLWEInfos + GLWEInfos,
KEY: GGLWEInfos + GLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
GLWECiphertext::keyswitch_inplace_scratch_space(module, out_infos, key_apply)
@@ -156,28 +156,28 @@ impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> {
rhs.rank_out()
);
assert!(
self.rows() <= lhs.rows(),
"self.rows()={} > lhs.rows()={}",
self.rows(),
lhs.rows()
self.dnum() <= lhs.dnum(),
"self.dnum()={} > lhs.dnum()={}",
self.dnum(),
lhs.dnum()
);
assert_eq!(
self.digits(),
lhs.digits(),
"ksk_out digits: {} != ksk_in digits: {}",
self.digits(),
lhs.digits()
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.rows().into()).for_each(|row_j| {
(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.rows().min(lhs.rows()).into()..self.rows().into()).for_each(|row_i| {
(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();
});
@@ -215,7 +215,7 @@ impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> {
}
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.rows().into()).for_each(|row_j| {
(0..self.dnum().into()).for_each(|row_j| {
self.at_mut(row_j, col_i)
.keyswitch_inplace(module, rhs, scratch)
});

View File

@@ -10,7 +10,7 @@ use poulpy_hal::{
use crate::{
layouts::{
GGLWECiphertext, GGLWELayoutInfos, GGSWCiphertext, GGSWInfos, GLWECiphertext, GLWEInfos, LWEInfos,
GGLWECiphertext, GGLWEInfos, GGSWCiphertext, GGSWInfos, GLWECiphertext, GLWEInfos, LWEInfos,
prepared::{GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared},
},
operations::GLWEOperations,
@@ -20,14 +20,14 @@ impl GGSWCiphertext<Vec<u8>> {
pub(crate) fn expand_row_scratch_space<B: Backend, OUT, TSK>(module: &Module<B>, out_infos: &OUT, tsk_infos: &TSK) -> usize
where
OUT: GGSWInfos,
TSK: GGLWELayoutInfos,
TSK: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigAllocBytes + VecZnxNormalizeTmpBytes,
{
let tsk_size: usize = tsk_infos.k().div_ceil(tsk_infos.base2k()) as usize;
let size_in: usize = out_infos
.k()
.div_ceil(tsk_infos.base2k())
.div_ceil(tsk_infos.digits().into()) as usize;
.div_ceil(tsk_infos.dsize().into()) as usize;
let tmp_dft_i: usize = module.vec_znx_dft_alloc_bytes((tsk_infos.rank_out() + 1).into(), tsk_size);
let tmp_a: usize = module.vec_znx_dft_alloc_bytes(1, size_in);
@@ -56,8 +56,8 @@ impl GGSWCiphertext<Vec<u8>> {
where
OUT: GGSWInfos,
IN: GGSWInfos,
KEY: GGLWELayoutInfos,
TSK: GGLWELayoutInfos,
KEY: GGLWEInfos,
TSK: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigAllocBytes
@@ -101,8 +101,8 @@ impl GGSWCiphertext<Vec<u8>> {
) -> usize
where
OUT: GGSWInfos,
KEY: GGLWELayoutInfos,
TSK: GGLWELayoutInfos,
KEY: GGLWEInfos,
TSK: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigAllocBytes
@@ -143,12 +143,12 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
use crate::layouts::{GLWEInfos, LWEInfos};
assert_eq!(self.rank(), a.rank_out());
assert_eq!(self.rows(), a.rows());
assert_eq!(self.dnum(), a.dnum());
assert_eq!(self.n(), module.n() as u32);
assert_eq!(a.n(), module.n() as u32);
assert_eq!(tsk.n(), module.n() as u32);
}
(0..self.rows().into()).for_each(|row_i| {
(0..self.dnum().into()).for_each(|row_i| {
self.at_mut(row_i, 0).copy(module, &a.at(row_i, 0));
});
self.expand_row(module, tsk, scratch);
@@ -180,7 +180,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
+ VecZnxNormalize<B>,
Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx,
{
(0..lhs.rows().into()).for_each(|row_i| {
(0..lhs.dnum().into()).for_each(|row_i| {
// Key-switch column 0, i.e.
// col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0s0' + a1s1' + a2s2') + M[i], a0, a1, a2)
self.at_mut(row_i, 0)
@@ -214,7 +214,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
+ VecZnxNormalize<B>,
Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx,
{
(0..self.rows().into()).for_each(|row_i| {
(0..self.dnum().into()).for_each(|row_i| {
// Key-switch column 0, i.e.
// col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0s0' + a1s1' + a2s2') + M[i], a0, a1, a2)
self.at_mut(row_i, 0)
@@ -255,7 +255,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
let a_size: usize = (self.size() * basek_in).div_ceil(basek_tsk);
// Keyswitch the j-th row of the col 0
for row_i in 0..self.rows().into() {
for row_i in 0..self.dnum().into() {
let a = &self.at(row_i, 0).data;
// Pre-compute DFT of (a0, a1, a2)
@@ -277,7 +277,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
// Example for rank 3:
//
// Note: M is a vector (m, Bm, B^2m, B^3m, ...), so each column is
// actually composed of that many rows and we focus on a specific row here
// actually composed of that many dnum and we focus on a specific row here
// implicitely given ci_dft.
//
// # Input
@@ -294,10 +294,10 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
// col 2: (-(c0s0 + c1s1 + c2s2) , c0 , c1 + M[i], c2 )
// col 3: (-(d0s0 + d1s1 + d2s2) , d0 , d1 , d2 + M[i])
let digits: usize = tsk.digits().into();
let dsize: usize = tsk.dsize().into();
let (mut tmp_dft_i, scratch_2) = scratch_1.take_vec_znx_dft(n, cols, tsk.size());
let (mut tmp_a, scratch_3) = scratch_2.take_vec_znx_dft(n, 1, ci_dft.size().div_ceil(digits));
let (mut tmp_a, scratch_3) = scratch_2.take_vec_znx_dft(n, 1, ci_dft.size().div_ceil(dsize));
{
// Performs a key-switch for each combination of s[i]*s[j], i.e. for a0, a1, a2
@@ -315,19 +315,19 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
let pmat: &VmpPMat<DataTsk, B> = &tsk.at(col_i - 1, col_j - 1).key.data; // Selects Enc(s[i]s[j])
// Extracts a[i] and multipies with Enc(s[i]s[j])
for di in 0..digits {
tmp_a.set_size((ci_dft.size() + di) / digits);
for di in 0..dsize {
tmp_a.set_size((ci_dft.size() + di) / dsize);
// Small optimization for digits > 2
// Small optimization for dsize > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}.
// As such we can ignore the last digits-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last digits-1 limbs, but this introduce
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}.
// As such we can ignore the last dsize-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last dsize-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
tmp_dft_i.set_size(tsk.size() - ((digits - di) as isize - 2).max(0) as usize);
tmp_dft_i.set_size(tsk.size() - ((dsize - di) as isize - 2).max(0) as usize);
module.vec_znx_dft_copy(digits, digits - 1 - di, &mut tmp_a, 0, &ci_dft, col_i);
module.vec_znx_dft_copy(dsize, dsize - 1 - di, &mut tmp_a, 0, &ci_dft, col_i);
if di == 0 && col_i == 1 {
module.vmp_apply_dft_to_dft(&mut tmp_dft_i, &tmp_a, pmat, scratch_3);
} else {

View File

@@ -7,7 +7,7 @@ use poulpy_hal::{
layouts::{Backend, DataMut, DataRef, DataViewMut, Module, Scratch, VecZnx, VecZnxBig, VecZnxDft, VmpPMat, ZnxInfos},
};
use crate::layouts::{GGLWELayoutInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWESwitchingKeyPrepared};
use crate::layouts::{GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWESwitchingKeyPrepared};
impl GLWECiphertext<Vec<u8>> {
pub fn keyswitch_scratch_space<B: Backend, OUT, IN, KEY>(
@@ -19,13 +19,13 @@ impl GLWECiphertext<Vec<u8>> {
where
OUT: GLWEInfos,
IN: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
let in_size: usize = in_infos
.k()
.div_ceil(key_apply.base2k())
.div_ceil(key_apply.digits().into()) as usize;
.div_ceil(key_apply.dsize().into()) as usize;
let out_size: usize = out_infos.size();
let ksk_size: usize = key_apply.size();
let res_dft: usize = module.vec_znx_dft_alloc_bytes((key_apply.rank_out() + 1).into(), ksk_size); // TODO OPTIMIZE
@@ -41,12 +41,12 @@ impl GLWECiphertext<Vec<u8>> {
let normalize_big: usize = module.vec_znx_big_normalize_tmp_bytes();
if in_infos.base2k() == key_apply.base2k() {
res_dft + ((ai_dft + vmp) | normalize_big)
} else if key_apply.digits() == 1 {
} else if key_apply.dsize() == 1 {
// In this case, we only need one column, temporary, that we can drop once a_dft is computed.
let normalize_conv: usize = VecZnx::alloc_bytes(module.n(), 1, in_size) + module.vec_znx_normalize_tmp_bytes();
res_dft + (((ai_dft + normalize_conv) | vmp) | normalize_big)
} else {
// Since we stride over a to get a_dft when digits > 1, we need to store the full columns of a with in the base conversion.
// Since we stride over a to get a_dft when dsize > 1, we need to store the full columns of a with in the base conversion.
let normalize_conv: usize = VecZnx::alloc_bytes(module.n(), (key_apply.rank_in()).into(), in_size);
res_dft + ((ai_dft + normalize_conv + (module.vec_znx_normalize_tmp_bytes() | vmp)) | normalize_big)
}
@@ -55,7 +55,7 @@ impl GLWECiphertext<Vec<u8>> {
pub fn keyswitch_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_apply: &KEY) -> usize
where
OUT: GLWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes,
{
Self::keyswitch_scratch_space(module, out_infos, out_infos, key_apply)
@@ -105,7 +105,7 @@ impl<DataSelf: DataRef> GLWECiphertext<DataSelf> {
lhs.k(),
rhs.base2k(),
rhs.k(),
rhs.digits(),
rhs.dsize(),
rhs.rank_in(),
rhs.rank_out(),
)={scrach_needed}",
@@ -256,7 +256,7 @@ impl<D: DataRef> GLWECiphertext<D> {
+ VecZnxNormalize<B>,
Scratch<B>: TakeVecZnxDft<B> + TakeVecZnx,
{
if rhs.digits() == 1 {
if rhs.dsize() == 1 {
return keyswitch_vmp_one_digit(
module,
self.base2k().into(),
@@ -275,7 +275,7 @@ impl<D: DataRef> GLWECiphertext<D> {
res_dft,
&self.data,
&rhs.key.data,
rhs.digits().into(),
rhs.dsize().into(),
scratch,
)
}
@@ -333,7 +333,7 @@ fn keyswitch_vmp_multiple_digits<B: Backend, DataRes, DataIn, DataVmp>(
mut res_dft: VecZnxDft<DataRes, B>,
a: &VecZnx<DataIn>,
mat: &VmpPMat<DataVmp, B>,
digits: usize,
dsize: usize,
scratch: &mut Scratch<B>,
) -> VecZnxBig<DataRes, B>
where
@@ -351,24 +351,24 @@ where
{
let cols: usize = a.cols();
let a_size: usize = (a.size() * basek_in).div_ceil(basek_ksk);
let (mut ai_dft, scratch_1) = scratch.take_vec_znx_dft(a.n(), cols - 1, a_size.div_ceil(digits));
let (mut ai_dft, scratch_1) = scratch.take_vec_znx_dft(a.n(), cols - 1, a_size.div_ceil(dsize));
ai_dft.data_mut().fill(0);
if basek_in == basek_ksk {
for di in 0..digits {
ai_dft.set_size((a_size + di) / digits);
for di in 0..dsize {
ai_dft.set_size((a_size + di) / dsize);
// Small optimization for digits > 2
// Small optimization for dsize > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}.
// As such we can ignore the last digits-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last digits-1 limbs, but this introduce
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}.
// As such we can ignore the last dsize-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last dsize-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(mat.size() - ((digits - di) as isize - 2).max(0) as usize);
res_dft.set_size(mat.size() - ((dsize - di) as isize - 2).max(0) as usize);
for j in 0..cols - 1 {
module.vec_znx_dft_apply(digits, digits - di - 1, &mut ai_dft, j, a, j + 1);
module.vec_znx_dft_apply(dsize, dsize - di - 1, &mut ai_dft, j, a, j + 1);
}
if di == 0 {
@@ -383,20 +383,20 @@ where
module.vec_znx_normalize(basek_ksk, &mut a_conv, j, basek_in, a, j + 1, scratch_2);
}
for di in 0..digits {
ai_dft.set_size((a_size + di) / digits);
for di in 0..dsize {
ai_dft.set_size((a_size + di) / dsize);
// Small optimization for digits > 2
// Small optimization for dsize > 2
// VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(digits-1) * B}.
// As such we can ignore the last digits-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last digits-1 limbs, but this introduce
// we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}.
// As such we can ignore the last dsize-2 limbs safely of the sum of vmp products.
// It is possible to further ignore the last dsize-1 limbs, but this introduce
// ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same
// noise is kept with respect to the ideal functionality.
res_dft.set_size(mat.size() - ((digits - di) as isize - 2).max(0) as usize);
res_dft.set_size(mat.size() - ((dsize - di) as isize - 2).max(0) as usize);
for j in 0..cols - 1 {
module.vec_znx_dft_apply(digits, digits - di - 1, &mut ai_dft, j, &a_conv, j);
module.vec_znx_dft_apply(dsize, dsize - di - 1, &mut ai_dft, j, &a_conv, j);
}
if di == 0 {

View File

@@ -10,7 +10,7 @@ use poulpy_hal::{
use crate::{
TakeGLWECt,
layouts::{
GGLWELayoutInfos, GLWECiphertext, GLWECiphertextLayout, LWECiphertext, LWEInfos, Rank, TorusPrecision,
GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, LWECiphertext, LWEInfos, Rank, TorusPrecision,
prepared::LWESwitchingKeyPrepared,
},
};
@@ -25,7 +25,7 @@ impl LWECiphertext<Vec<u8>> {
where
OUT: LWEInfos,
IN: LWEInfos,
KEY: GGLWELayoutInfos,
KEY: GGLWEInfos,
Module<B>: VecZnxDftAllocBytes
+ VmpApplyDftToDftTmpBytes
+ VecZnxBigNormalizeTmpBytes

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWEAutomorphismKey, GGLWELayoutInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
compressed::{Decompress, GGLWESwitchingKeyCompressed},
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -40,7 +40,7 @@ impl<D: Data> GLWEInfos for GGLWEAutomorphismKeyCompressed<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWEAutomorphismKeyCompressed<D> {
impl<D: Data> GGLWEInfos for GGLWEAutomorphismKeyCompressed<D> {
fn rank_in(&self) -> Rank {
self.key.rank_in()
}
@@ -49,12 +49,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWEAutomorphismKeyCompressed<D> {
self.key.rank_out()
}
fn digits(&self) -> Digits {
self.key.digits()
fn dsize(&self) -> Dsize {
self.key.dsize()
}
fn rows(&self) -> Rows {
self.key.rows()
fn dnum(&self) -> Dnum {
self.key.dnum()
}
}
@@ -79,7 +79,7 @@ impl<D: DataRef> fmt::Display for GGLWEAutomorphismKeyCompressed<D> {
impl GGLWEAutomorphismKeyCompressed<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(infos.rank_in(), infos.rank_out());
Self {
@@ -88,23 +88,23 @@ impl GGLWEAutomorphismKeyCompressed<Vec<u8>> {
}
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
Self {
key: GGLWESwitchingKeyCompressed::alloc_with(n, base2k, k, rows, digits, rank, rank),
key: GGLWESwitchingKeyCompressed::alloc_with(n, base2k, k, rank, rank, dnum, dsize),
p: 0,
}
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(infos.rank_in(), infos.rank_out());
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rows, digits, rank, rank)
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rank, dnum, dsize)
}
}

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWECiphertext, GGLWELayoutInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
compressed::{Decompress, GLWECiphertextCompressed},
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -17,7 +17,7 @@ pub struct GGLWECiphertextCompressed<D: Data> {
pub(crate) base2k: Base2K,
pub(crate) k: TorusPrecision,
pub(crate) rank_out: Rank,
pub(crate) digits: Digits,
pub(crate) dsize: Dsize,
pub(crate) seed: Vec<[u8; 32]>,
}
@@ -44,7 +44,7 @@ impl<D: Data> GLWEInfos for GGLWECiphertextCompressed<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWECiphertextCompressed<D> {
impl<D: Data> GGLWEInfos for GGLWECiphertextCompressed<D> {
fn rank_in(&self) -> Rank {
Rank(self.data.cols_in() as u32)
}
@@ -53,12 +53,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWECiphertextCompressed<D> {
self.rank_out
}
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
Rows(self.data.rows() as u32)
fn dnum(&self) -> Dnum {
Dnum(self.data.rows() as u32)
}
}
@@ -78,8 +78,8 @@ impl<D: DataRef> fmt::Display for GGLWECiphertextCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GGLWECiphertextCompressed: base2k={} k={} digits={}) {}",
self.base2k.0, self.k.0, self.digits.0, self.data
"(GGLWECiphertextCompressed: base2k={} k={} dsize={}) {}",
self.base2k.0, self.k.0, self.dsize.0, self.data
)
}
}
@@ -87,16 +87,16 @@ impl<D: DataRef> fmt::Display for GGLWECiphertextCompressed<D> {
impl GGLWECiphertextCompressed<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
Self::alloc_with(
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_in(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
@@ -104,82 +104,73 @@ impl GGLWECiphertextCompressed<Vec<u8>> {
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> Self {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid gglwe: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid gglwe: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
Self {
data: MatZnx::alloc(
n.into(),
rows.into(),
dnum.into(),
rank_in.into(),
1,
k.0.div_ceil(base2k.0) as usize,
),
k,
base2k,
digits,
dsize,
rank_out,
seed: vec![[0u8; 32]; (rows.0 * rank_in.0) as usize],
seed: vec![[0u8; 32]; (dnum.0 * rank_in.0) as usize],
}
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
Self::alloc_bytes_with(
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_in(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_bytes_with(
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
_rank_out: Rank,
) -> usize {
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid gglwe: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid gglwe: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
MatZnx::alloc_bytes(
n.into(),
rows.into(),
dnum.into(),
rank_in.into(),
1,
k.0.div_ceil(base2k.0) as usize,
@@ -217,7 +208,7 @@ impl<D: DataMut> ReaderFrom for GGLWECiphertextCompressed<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
self.digits = Digits(reader.read_u32::<LittleEndian>()?);
self.dsize = Dsize(reader.read_u32::<LittleEndian>()?);
self.rank_out = Rank(reader.read_u32::<LittleEndian>()?);
let seed_len: u32 = reader.read_u32::<LittleEndian>()?;
self.seed = vec![[0u8; 32]; seed_len as usize];
@@ -232,7 +223,7 @@ impl<D: DataRef> WriterTo for GGLWECiphertextCompressed<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u32::<LittleEndian>(self.k.into())?;
writer.write_u32::<LittleEndian>(self.base2k.into())?;
writer.write_u32::<LittleEndian>(self.digits.into())?;
writer.write_u32::<LittleEndian>(self.dsize.into())?;
writer.write_u32::<LittleEndian>(self.rank_out.into())?;
writer.write_u32::<LittleEndian>(self.seed.len() as u32)?;
for s in &self.seed {
@@ -279,19 +270,19 @@ where
);
assert_eq!(
self.rows(),
other.rows(),
"invalid receiver: self.rows()={} != other.rows()={}",
self.rows(),
other.rows()
self.dnum(),
other.dnum(),
"invalid receiver: self.dnum()={} != other.dnum()={}",
self.dnum(),
other.dnum()
);
}
let rank_in: usize = self.rank_in().into();
let rows: usize = self.rows().into();
let dnum: usize = self.dnum().into();
(0..rank_in).for_each(|col_i| {
(0..rows).for_each(|row_i| {
(0..dnum).for_each(|row_i| {
self.at_mut(row_i, col_i)
.decompress(module, &other.at(row_i, col_i));
});

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
compressed::{Decompress, GGLWECiphertextCompressed},
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -41,7 +41,7 @@ impl<D: Data> GLWEInfos for GGLWESwitchingKeyCompressed<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWESwitchingKeyCompressed<D> {
impl<D: Data> GGLWEInfos for GGLWESwitchingKeyCompressed<D> {
fn rank_in(&self) -> Rank {
self.key.rank_in()
}
@@ -50,12 +50,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWESwitchingKeyCompressed<D> {
self.key.rank_out()
}
fn digits(&self) -> Digits {
self.key.digits()
fn dsize(&self) -> Dsize {
self.key.dsize()
}
fn rows(&self) -> Rows {
self.key.rows()
fn dnum(&self) -> Dnum {
self.key.dnum()
}
}
@@ -84,7 +84,7 @@ impl<D: DataRef> fmt::Display for GGLWESwitchingKeyCompressed<D> {
impl GGLWESwitchingKeyCompressed<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
GGLWESwitchingKeyCompressed {
key: GGLWECiphertextCompressed::alloc(infos),
@@ -97,13 +97,13 @@ impl GGLWESwitchingKeyCompressed<Vec<u8>> {
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> Self {
GGLWESwitchingKeyCompressed {
key: GGLWECiphertextCompressed::alloc_with(n, base2k, k, rows, digits, rank_in, rank_out),
key: GGLWECiphertextCompressed::alloc_with(n, base2k, k, rank_in, rank_out, dnum, dsize),
sk_in_n: 0,
sk_out_n: 0,
}
@@ -111,21 +111,13 @@ impl GGLWESwitchingKeyCompressed<Vec<u8>> {
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
GGLWECiphertextCompressed::alloc_bytes(infos)
}
pub fn alloc_bytes_with(
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
) -> usize {
GGLWECiphertextCompressed::alloc_bytes_with(n, base2k, k, rows, digits, rank_in, rank_out)
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize {
GGLWECiphertextCompressed::alloc_bytes_with(n, base2k, k, rank_in, dnum, dsize)
}
}

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
compressed::{Decompress, GGLWESwitchingKeyCompressed},
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -38,7 +38,7 @@ impl<D: Data> GLWEInfos for GGLWETensorKeyCompressed<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWETensorKeyCompressed<D> {
impl<D: Data> GGLWEInfos for GGLWETensorKeyCompressed<D> {
fn rank_in(&self) -> Rank {
self.rank_out()
}
@@ -47,12 +47,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWETensorKeyCompressed<D> {
self.keys[0].rank_out()
}
fn digits(&self) -> Digits {
self.keys[0].digits()
fn dsize(&self) -> Dsize {
self.keys[0].dsize()
}
fn rows(&self) -> Rows {
self.keys[0].rows()
fn dnum(&self) -> Dnum {
self.keys[0].dnum()
}
}
@@ -83,7 +83,7 @@ impl<D: DataRef> fmt::Display for GGLWETensorKeyCompressed<D> {
impl GGLWETensorKeyCompressed<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
@@ -94,13 +94,13 @@ impl GGLWETensorKeyCompressed<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
let mut keys: Vec<GGLWESwitchingKeyCompressed<Vec<u8>>> = Vec::new();
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
(0..pairs).for_each(|_| {
@@ -108,10 +108,10 @@ impl GGLWETensorKeyCompressed<Vec<u8>> {
n,
base2k,
k,
rows,
digits,
Rank(1),
rank,
dnum,
dsize,
));
});
Self { keys }
@@ -119,7 +119,7 @@ impl GGLWETensorKeyCompressed<Vec<u8>> {
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
@@ -133,16 +133,15 @@ impl GGLWETensorKeyCompressed<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
Rank(1),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> usize {
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
pairs * GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rows, digits, Rank(1), rank)
pairs * GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, dsize)
}
}

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
compressed::{Decompress, GLWECiphertextCompressed},
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -16,7 +16,7 @@ pub struct GGSWCiphertextCompressed<D: Data> {
pub(crate) data: MatZnx<D>,
pub(crate) k: TorusPrecision,
pub(crate) base2k: Base2K,
pub(crate) digits: Digits,
pub(crate) dsize: Dsize,
pub(crate) rank: Rank,
pub(crate) seed: Vec<[u8; 32]>,
}
@@ -44,12 +44,12 @@ impl<D: Data> GLWEInfos for GGSWCiphertextCompressed<D> {
}
impl<D: Data> GGSWInfos for GGSWCiphertextCompressed<D> {
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
Rows(self.data.rows() as u32)
fn dnum(&self) -> Dnum {
Dnum(self.data.rows() as u32)
}
}
@@ -63,8 +63,8 @@ impl<D: DataRef> fmt::Display for GGSWCiphertextCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GGSWCiphertextCompressed: base2k={} k={} digits={}) {}",
self.base2k, self.k, self.digits, self.data
"(GGSWCiphertextCompressed: base2k={} k={} dsize={}) {}",
self.base2k, self.k, self.dsize, self.data
)
}
}
@@ -84,38 +84,38 @@ impl GGSWCiphertextCompressed<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid ggsw: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
Self {
data: MatZnx::alloc(
n.into(),
rows.into(),
dnum.into(),
(rank + 1).into(),
1,
k.0.div_ceil(base2k.0) as usize,
),
k,
base2k,
digits,
dsize,
rank,
seed: Vec::new(),
}
@@ -129,30 +129,30 @@ impl GGSWCiphertextCompressed<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> usize {
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid ggsw: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
MatZnx::alloc_bytes(
n.into(),
rows.into(),
dnum.into(),
(rank + 1).into(),
1,
k.0.div_ceil(base2k.0) as usize,
@@ -190,7 +190,7 @@ impl<D: DataMut> ReaderFrom for GGSWCiphertextCompressed<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
self.digits = Digits(reader.read_u32::<LittleEndian>()?);
self.dsize = Dsize(reader.read_u32::<LittleEndian>()?);
self.rank = Rank(reader.read_u32::<LittleEndian>()?);
let seed_len: usize = reader.read_u32::<LittleEndian>()? as usize;
self.seed = vec![[0u8; 32]; seed_len];
@@ -205,7 +205,7 @@ impl<D: DataRef> WriterTo for GGSWCiphertextCompressed<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u32::<LittleEndian>(self.k.into())?;
writer.write_u32::<LittleEndian>(self.base2k.into())?;
writer.write_u32::<LittleEndian>(self.digits.into())?;
writer.write_u32::<LittleEndian>(self.dsize.into())?;
writer.write_u32::<LittleEndian>(self.rank.into())?;
writer.write_u32::<LittleEndian>(self.seed.len() as u32)?;
for s in &self.seed {
@@ -225,9 +225,9 @@ where
assert_eq!(self.rank(), other.rank())
}
let rows: usize = self.rows().into();
let dnum: usize = self.dnum().into();
let rank: usize = self.rank().into();
(0..rows).for_each(|row_i| {
(0..dnum).for_each(|row_i| {
(0..rank + 1).for_each(|col_j| {
self.at_mut(row_i, col_j)
.decompress(module, &other.at(row_i, col_j));

View File

@@ -6,8 +6,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
compressed::GGLWESwitchingKeyCompressed,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, compressed::GGLWESwitchingKeyCompressed,
};
#[derive(PartialEq, Eq, Clone)]
@@ -36,21 +35,21 @@ impl<D: Data> GLWEInfos for GLWEToLWESwitchingKeyCompressed<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GLWEToLWESwitchingKeyCompressed<D> {
impl<D: Data> GGLWEInfos for GLWEToLWESwitchingKeyCompressed<D> {
fn rank_in(&self) -> Rank {
self.0.rank_in()
}
fn digits(&self) -> Digits {
self.0.digits()
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_out(&self) -> Rank {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
@@ -87,7 +86,7 @@ impl<D: DataRef> WriterTo for GLWEToLWESwitchingKeyCompressed<D> {
impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.rank_out().0,
@@ -95,28 +94,28 @@ impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
"rank_out > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
"dsize > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
);
Self(GGLWESwitchingKeyCompressed::alloc(infos))
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_in: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self {
Self(GGLWESwitchingKeyCompressed::alloc_with(
n,
base2k,
k,
rows,
Digits(1),
rank_in,
Rank(1),
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.rank_out().0,
@@ -124,14 +123,14 @@ impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
"rank_out > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
"dsize > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
);
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_in: Rank) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rows, Digits(1), rank_in, Rank(1))
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_in: Rank) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rank_in, dnum, Dsize(1))
}
}

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, TorusPrecision,
compressed::{Decompress, GGLWESwitchingKeyCompressed},
};
use std::fmt;
@@ -35,9 +35,9 @@ impl<D: Data> GLWEInfos for LWESwitchingKeyCompressed<D> {
}
}
impl<D: Data> GGLWELayoutInfos for LWESwitchingKeyCompressed<D> {
fn digits(&self) -> Digits {
self.0.digits()
impl<D: Data> GGLWEInfos for LWESwitchingKeyCompressed<D> {
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_in(&self) -> Rank {
@@ -48,8 +48,8 @@ impl<D: Data> GGLWELayoutInfos for LWESwitchingKeyCompressed<D> {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
@@ -86,12 +86,12 @@ impl<D: DataRef> WriterTo for LWESwitchingKeyCompressed<D> {
impl LWESwitchingKeyCompressed<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWESwitchingKeyCompressed"
"dsize > 1 is not supported for LWESwitchingKeyCompressed"
);
debug_assert_eq!(
infos.rank_in().0,
@@ -106,26 +106,26 @@ impl LWESwitchingKeyCompressed<Vec<u8>> {
Self(GGLWESwitchingKeyCompressed::alloc(infos))
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self {
Self(GGLWESwitchingKeyCompressed::alloc_with(
n,
base2k,
k,
rows,
Digits(1),
Rank(1),
Rank(1),
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWESwitchingKey"
"dsize > 1 is not supported for LWESwitchingKey"
);
debug_assert_eq!(
infos.rank_in().0,
@@ -140,8 +140,8 @@ impl LWESwitchingKeyCompressed<Vec<u8>> {
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rows, Digits(1), Rank(1), Rank(1))
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, Dsize(1))
}
}

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, TorusPrecision,
compressed::{Decompress, GGLWESwitchingKeyCompressed},
};
use std::fmt;
@@ -35,9 +35,9 @@ impl<D: Data> GLWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
}
}
impl<D: Data> GGLWELayoutInfos for LWEToGLWESwitchingKeyCompressed<D> {
fn digits(&self) -> Digits {
self.0.digits()
impl<D: Data> GGLWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_in(&self) -> Rank {
@@ -48,8 +48,8 @@ impl<D: Data> GGLWELayoutInfos for LWEToGLWESwitchingKeyCompressed<D> {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
@@ -86,12 +86,12 @@ impl<D: DataRef> WriterTo for LWEToGLWESwitchingKeyCompressed<D> {
impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWEToGLWESwitchingKeyCompressed"
"dsize > 1 is not supported for LWEToGLWESwitchingKeyCompressed"
);
debug_assert_eq!(
infos.rank_in().0,
@@ -101,21 +101,21 @@ impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
Self(GGLWESwitchingKeyCompressed::alloc(infos))
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_out: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self {
Self(GGLWESwitchingKeyCompressed::alloc_with(
n,
base2k,
k,
rows,
Digits(1),
Rank(1),
rank_out,
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.rank_in().0,
@@ -123,15 +123,15 @@ impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWEToGLWESwitchingKey"
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
);
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_out: Rank) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rows, Digits(1), Rank(1), rank_out)
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, Dsize(1))
}
}

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWESwitchingKey, GLWECiphertext, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision,
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -15,9 +15,9 @@ pub struct GGLWEAutomorphismKeyLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub digits: Digits,
pub rank: Rank,
pub dnum: Dnum,
pub dsize: Dsize,
}
#[derive(PartialEq, Eq, Clone)]
@@ -56,7 +56,7 @@ impl<D: Data> GLWEInfos for GGLWEAutomorphismKey<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWEAutomorphismKey<D> {
impl<D: Data> GGLWEInfos for GGLWEAutomorphismKey<D> {
fn rank_in(&self) -> Rank {
self.key.rank_in()
}
@@ -65,12 +65,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWEAutomorphismKey<D> {
self.key.rank_out()
}
fn digits(&self) -> Digits {
self.key.digits()
fn dsize(&self) -> Dsize {
self.key.dsize()
}
fn rows(&self) -> Rows {
self.key.rows()
fn dnum(&self) -> Dnum {
self.key.dnum()
}
}
@@ -94,21 +94,21 @@ impl GLWEInfos for GGLWEAutomorphismKeyLayout {
}
}
impl GGLWELayoutInfos for GGLWEAutomorphismKeyLayout {
impl GGLWEInfos for GGLWEAutomorphismKeyLayout {
fn rank_in(&self) -> Rank {
self.rank
}
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rank_out(&self) -> Rank {
self.rank
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
@@ -133,7 +133,7 @@ impl<D: DataRef> fmt::Display for GGLWEAutomorphismKey<D> {
impl GGLWEAutomorphismKey<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
@@ -146,16 +146,16 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
}
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
GGLWEAutomorphismKey {
key: GGLWESwitchingKey::alloc_with(n, base2k, k, rows, digits, rank, rank),
key: GGLWESwitchingKey::alloc_with(n, base2k, k, rank, rank, dnum, dsize),
p: 0,
}
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
@@ -165,8 +165,8 @@ impl GGLWEAutomorphismKey<Vec<u8>> {
GGLWESwitchingKey::alloc_bytes(infos)
}
pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rows, digits, rank, rank)
pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rank, rank, dnum, dsize)
}
}

View File

@@ -3,17 +3,17 @@ use poulpy_hal::{
source::Source,
};
use crate::layouts::{Base2K, BuildError, Degree, Digits, GLWECiphertext, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision};
use crate::layouts::{Base2K, BuildError, Degree, Dnum, Dsize, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::fmt;
pub trait GGLWELayoutInfos
pub trait GGLWEInfos
where
Self: GLWEInfos,
{
fn rows(&self) -> Rows;
fn digits(&self) -> Digits;
fn dnum(&self) -> Dnum;
fn dsize(&self) -> Dsize;
fn rank_in(&self) -> Rank;
fn rank_out(&self) -> Rank;
fn layout(&self) -> GGLWECiphertextLayout {
@@ -23,8 +23,8 @@ where
k: self.k(),
rank_in: self.rank_in(),
rank_out: self.rank_out(),
digits: self.digits(),
rows: self.rows(),
dsize: self.dsize(),
dnum: self.dnum(),
}
}
}
@@ -34,10 +34,10 @@ pub struct GGLWECiphertextLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub digits: Digits,
pub rank_in: Rank,
pub rank_out: Rank,
pub dnum: Dnum,
pub dsize: Dsize,
}
impl LWEInfos for GGLWECiphertextLayout {
@@ -60,21 +60,21 @@ impl GLWEInfos for GGLWECiphertextLayout {
}
}
impl GGLWELayoutInfos for GGLWECiphertextLayout {
impl GGLWEInfos for GGLWECiphertextLayout {
fn rank_in(&self) -> Rank {
self.rank_in
}
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rank_out(&self) -> Rank {
self.rank_out
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
@@ -83,7 +83,7 @@ pub struct GGLWECiphertext<D: Data> {
pub(crate) data: MatZnx<D>,
pub(crate) k: TorusPrecision,
pub(crate) base2k: Base2K,
pub(crate) digits: Digits,
pub(crate) dsize: Dsize,
}
impl<D: Data> LWEInfos for GGLWECiphertext<D> {
@@ -110,7 +110,7 @@ impl<D: Data> GLWEInfos for GGLWECiphertext<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWECiphertext<D> {
impl<D: Data> GGLWEInfos for GGLWECiphertext<D> {
fn rank_in(&self) -> Rank {
Rank(self.data.cols_in() as u32)
}
@@ -119,12 +119,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWECiphertext<D> {
Rank(self.data.cols_out() as u32 - 1)
}
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
Rows(self.data.rows() as u32)
fn dnum(&self) -> Dnum {
Dnum(self.data.rows() as u32)
}
}
@@ -132,7 +132,7 @@ pub struct GGLWECiphertextBuilder<D: Data> {
data: Option<MatZnx<D>>,
base2k: Option<Base2K>,
k: Option<TorusPrecision>,
digits: Option<Digits>,
dsize: Option<Dsize>,
}
impl<D: Data> GGLWECiphertext<D> {
@@ -142,7 +142,7 @@ impl<D: Data> GGLWECiphertext<D> {
data: None,
base2k: None,
k: None,
digits: None,
dsize: None,
}
}
}
@@ -151,18 +151,18 @@ impl GGLWECiphertextBuilder<Vec<u8>> {
#[inline]
pub fn layout<A>(mut self, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
self.data = Some(MatZnx::alloc(
infos.n().into(),
infos.rows().into(),
infos.dnum().into(),
infos.rank_in().into(),
(infos.rank_out() + 1).into(),
infos.size(),
));
self.base2k = Some(infos.base2k());
self.k = Some(infos.k());
self.digits = Some(infos.digits());
self.dsize = Some(infos.dsize());
self
}
}
@@ -185,8 +185,8 @@ impl<D: Data> GGLWECiphertextBuilder<D> {
}
#[inline]
pub fn digits(mut self, digits: Digits) -> Self {
self.digits = Some(digits);
pub fn dsize(mut self, dsize: Dsize) -> Self {
self.dsize = Some(dsize);
self
}
@@ -194,13 +194,13 @@ impl<D: Data> GGLWECiphertextBuilder<D> {
let data: MatZnx<D> = self.data.ok_or(BuildError::MissingData)?;
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
let digits: Digits = self.digits.ok_or(BuildError::MissingDigits)?;
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
if base2k == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
if digits == 0_u32 {
if dsize == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
@@ -224,7 +224,7 @@ impl<D: Data> GGLWECiphertextBuilder<D> {
data,
base2k,
k,
digits,
dsize,
})
}
}
@@ -257,10 +257,10 @@ impl<D: DataRef> fmt::Display for GGLWECiphertext<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GGLWECiphertext: k={} base2k={} digits={}) {}",
"(GGLWECiphertext: k={} base2k={} dsize={}) {}",
self.k().0,
self.base2k().0,
self.digits().0,
self.dsize().0,
self.data
)
}
@@ -291,16 +291,16 @@ impl<D: DataMut> GGLWECiphertext<D> {
impl GGLWECiphertext<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
Self::alloc_with(
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_in(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
@@ -308,51 +308,51 @@ impl GGLWECiphertext<Vec<u8>> {
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> Self {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid gglwe: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid gglwe: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
Self {
data: MatZnx::alloc(
n.into(),
rows.into(),
dnum.into(),
rank_in.into(),
(rank_out + 1).into(),
k.0.div_ceil(base2k.0) as usize,
),
k,
base2k,
digits,
dsize,
}
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
Self::alloc_bytes_with(
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_in(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
@@ -360,28 +360,28 @@ impl GGLWECiphertext<Vec<u8>> {
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> usize {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid gglwe: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid gglwe: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
MatZnx::alloc_bytes(
n.into(),
rows.into(),
dnum.into(),
rank_in.into(),
(rank_out + 1).into(),
k.0.div_ceil(base2k.0) as usize,
@@ -393,7 +393,7 @@ impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
self.digits = Digits(reader.read_u32::<LittleEndian>()?);
self.dsize = Dsize(reader.read_u32::<LittleEndian>()?);
self.data.read_from(reader)
}
}
@@ -402,7 +402,7 @@ impl<D: DataRef> WriterTo for GGLWECiphertext<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u32::<LittleEndian>(self.k.0)?;
writer.write_u32::<LittleEndian>(self.base2k.0)?;
writer.write_u32::<LittleEndian>(self.digits.0)?;
writer.write_u32::<LittleEndian>(self.dsize.0)?;
self.data.write_to(writer)
}
}

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWECiphertext, GGLWELayoutInfos, GLWECiphertext, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision,
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
@@ -15,10 +15,10 @@ pub struct GGLWESwitchingKeyLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub digits: Digits,
pub rank_in: Rank,
pub rank_out: Rank,
pub dnum: Dnum,
pub dsize: Dsize,
}
impl LWEInfos for GGLWESwitchingKeyLayout {
@@ -41,7 +41,7 @@ impl GLWEInfos for GGLWESwitchingKeyLayout {
}
}
impl GGLWELayoutInfos for GGLWESwitchingKeyLayout {
impl GGLWEInfos for GGLWESwitchingKeyLayout {
fn rank_in(&self) -> Rank {
self.rank_in
}
@@ -50,12 +50,12 @@ impl GGLWELayoutInfos for GGLWESwitchingKeyLayout {
self.rank_out
}
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
@@ -90,7 +90,7 @@ impl<D: Data> GLWEInfos for GGLWESwitchingKey<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWESwitchingKey<D> {
impl<D: Data> GGLWEInfos for GGLWESwitchingKey<D> {
fn rank_in(&self) -> Rank {
self.key.rank_in()
}
@@ -99,12 +99,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWESwitchingKey<D> {
self.key.rank_out()
}
fn digits(&self) -> Digits {
self.key.digits()
fn dsize(&self) -> Dsize {
self.key.dsize()
}
fn rows(&self) -> Rows {
self.key.rows()
fn dnum(&self) -> Dnum {
self.key.dnum()
}
}
@@ -135,7 +135,7 @@ impl<D: DataMut> FillUniform for GGLWESwitchingKey<D> {
impl GGLWESwitchingKey<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
GGLWESwitchingKey {
key: GGLWECiphertext::alloc(infos),
@@ -148,13 +148,13 @@ impl GGLWESwitchingKey<Vec<u8>> {
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> Self {
GGLWESwitchingKey {
key: GGLWECiphertext::alloc_with(n, base2k, k, rows, digits, rank_in, rank_out),
key: GGLWECiphertext::alloc_with(n, base2k, k, rank_in, rank_out, dnum, dsize),
sk_in_n: 0,
sk_out_n: 0,
}
@@ -162,7 +162,7 @@ impl GGLWESwitchingKey<Vec<u8>> {
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
GGLWECiphertext::alloc_bytes(infos)
}
@@ -171,12 +171,12 @@ impl GGLWESwitchingKey<Vec<u8>> {
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> usize {
GGLWECiphertext::alloc_bytes_with(n, base2k, k, rows, digits, rank_in, rank_out)
GGLWECiphertext::alloc_bytes_with(n, base2k, k, rank_in, rank_out, dnum, dsize)
}
}

View File

@@ -3,9 +3,7 @@ use poulpy_hal::{
source::Source,
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
};
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::fmt;
@@ -15,9 +13,9 @@ pub struct GGLWETensorKeyLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub digits: Digits,
pub rank: Rank,
pub dnum: Dnum,
pub dsize: Dsize,
}
#[derive(PartialEq, Eq, Clone)]
@@ -49,7 +47,7 @@ impl<D: Data> GLWEInfos for GGLWETensorKey<D> {
}
}
impl<D: Data> GGLWELayoutInfos for GGLWETensorKey<D> {
impl<D: Data> GGLWEInfos for GGLWETensorKey<D> {
fn rank_in(&self) -> Rank {
self.rank_out()
}
@@ -58,12 +56,12 @@ impl<D: Data> GGLWELayoutInfos for GGLWETensorKey<D> {
self.keys[0].rank_out()
}
fn digits(&self) -> Digits {
self.keys[0].digits()
fn dsize(&self) -> Dsize {
self.keys[0].dsize()
}
fn rows(&self) -> Rows {
self.keys[0].rows()
fn dnum(&self) -> Dnum {
self.keys[0].dnum()
}
}
@@ -87,21 +85,21 @@ impl GLWEInfos for GGLWETensorKeyLayout {
}
}
impl GGLWELayoutInfos for GGLWETensorKeyLayout {
impl GGLWEInfos for GGLWETensorKeyLayout {
fn rank_in(&self) -> Rank {
self.rank
}
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rank_out(&self) -> Rank {
self.rank
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
@@ -132,7 +130,7 @@ impl<D: DataRef> fmt::Display for GGLWETensorKey<D> {
impl GGLWETensorKey<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
@@ -143,13 +141,13 @@ impl GGLWETensorKey<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
let mut keys: Vec<GGLWESwitchingKey<Vec<u8>>> = Vec::new();
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
(0..pairs).for_each(|_| {
@@ -157,10 +155,10 @@ impl GGLWETensorKey<Vec<u8>> {
n,
base2k,
k,
rows,
digits,
Rank(1),
rank,
dnum,
dsize,
));
});
Self { keys }
@@ -168,7 +166,7 @@ impl GGLWETensorKey<Vec<u8>> {
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
@@ -182,16 +180,16 @@ impl GGLWETensorKey<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
Rank(1),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> usize {
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
pairs * GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rows, digits, Rank(1), rank)
pairs * GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), rank, dnum, dsize)
}
}

View File

@@ -4,22 +4,22 @@ use poulpy_hal::{
};
use std::fmt;
use crate::layouts::{Base2K, BuildError, Degree, Digits, GLWECiphertext, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision};
use crate::layouts::{Base2K, BuildError, Degree, Dnum, Dsize, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision};
pub trait GGSWInfos
where
Self: GLWEInfos,
{
fn rows(&self) -> Rows;
fn digits(&self) -> Digits;
fn dnum(&self) -> Dnum;
fn dsize(&self) -> Dsize;
fn layout(&self) -> GGSWCiphertextLayout {
GGSWCiphertextLayout {
n: self.n(),
base2k: self.base2k(),
k: self.k(),
rank: self.rank(),
rows: self.rows(),
digits: self.digits(),
dnum: self.dnum(),
dsize: self.dsize(),
}
}
}
@@ -29,9 +29,9 @@ pub struct GGSWCiphertextLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub digits: Digits,
pub rank: Rank,
pub dnum: Dnum,
pub dsize: Dsize,
}
impl LWEInfos for GGSWCiphertextLayout {
@@ -54,12 +54,12 @@ impl GLWEInfos for GGSWCiphertextLayout {
}
impl GGSWInfos for GGSWCiphertextLayout {
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
@@ -68,7 +68,7 @@ pub struct GGSWCiphertext<D: Data> {
pub(crate) data: MatZnx<D>,
pub(crate) k: TorusPrecision,
pub(crate) base2k: Base2K,
pub(crate) digits: Digits,
pub(crate) dsize: Dsize,
}
impl<D: Data> LWEInfos for GGSWCiphertext<D> {
@@ -96,12 +96,12 @@ impl<D: Data> GLWEInfos for GGSWCiphertext<D> {
}
impl<D: Data> GGSWInfos for GGSWCiphertext<D> {
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
Rows(self.data.rows() as u32)
fn dnum(&self) -> Dnum {
Dnum(self.data.rows() as u32)
}
}
@@ -109,7 +109,7 @@ pub struct GGSWCiphertextBuilder<D: Data> {
data: Option<MatZnx<D>>,
base2k: Option<Base2K>,
k: Option<TorusPrecision>,
digits: Option<Digits>,
dsize: Option<Dsize>,
}
impl<D: Data> GGSWCiphertext<D> {
@@ -119,7 +119,7 @@ impl<D: Data> GGSWCiphertext<D> {
data: None,
base2k: None,
k: None,
digits: None,
dsize: None,
}
}
}
@@ -131,30 +131,30 @@ impl GGSWCiphertextBuilder<Vec<u8>> {
A: GGSWInfos,
{
debug_assert!(
infos.size() as u32 > infos.digits().0,
"invalid ggsw: ceil(k/base2k): {} <= digits: {}",
infos.size() as u32 > infos.dsize().0,
"invalid ggsw: ceil(k/base2k): {} <= dsize: {}",
infos.size(),
infos.digits()
infos.dsize()
);
assert!(
infos.rows().0 * infos.digits().0 <= infos.size() as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {}",
infos.rows(),
infos.digits(),
infos.dnum().0 * infos.dsize().0 <= infos.size() as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {}",
infos.dnum(),
infos.dsize(),
infos.size(),
);
self.data = Some(MatZnx::alloc(
infos.n().into(),
infos.rows().into(),
infos.dnum().into(),
(infos.rank() + 1).into(),
(infos.rank() + 1).into(),
infos.size(),
));
self.base2k = Some(infos.base2k());
self.k = Some(infos.k());
self.digits = Some(infos.digits());
self.dsize = Some(infos.dsize());
self
}
}
@@ -177,8 +177,8 @@ impl<D: Data> GGSWCiphertextBuilder<D> {
}
#[inline]
pub fn digits(mut self, digits: Digits) -> Self {
self.digits = Some(digits);
pub fn dsize(mut self, dsize: Dsize) -> Self {
self.dsize = Some(dsize);
self
}
@@ -186,13 +186,13 @@ impl<D: Data> GGSWCiphertextBuilder<D> {
let data: MatZnx<D> = self.data.ok_or(BuildError::MissingData)?;
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
let digits: Digits = self.digits.ok_or(BuildError::MissingDigits)?;
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
if base2k == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
if digits == 0_u32 {
if dsize == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
@@ -216,7 +216,7 @@ impl<D: Data> GGSWCiphertextBuilder<D> {
data,
base2k,
k,
digits,
dsize,
})
}
}
@@ -231,10 +231,10 @@ impl<D: DataRef> fmt::Display for GGSWCiphertext<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GGSWCiphertext: k: {} base2k: {} digits: {}) {}",
"(GGSWCiphertext: k: {} base2k: {} dsize: {}) {}",
self.k().0,
self.base2k().0,
self.digits().0,
self.dsize().0,
self.data
)
}
@@ -277,38 +277,38 @@ impl GGSWCiphertext<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid ggsw: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
Self {
data: MatZnx::alloc(
n.into(),
rows.into(),
dnum.into(),
(rank + 1).into(),
(rank + 1).into(),
k.0.div_ceil(base2k.0) as usize,
),
k,
base2k,
digits,
dsize,
}
}
@@ -320,30 +320,30 @@ impl GGSWCiphertext<Vec<u8>> {
infos.n(),
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> usize {
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid ggsw: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
MatZnx::alloc_bytes(
n.into(),
rows.into(),
dnum.into(),
(rank + 1).into(),
(rank + 1).into(),
k.0.div_ceil(base2k.0) as usize,
@@ -357,7 +357,7 @@ impl<D: DataMut> ReaderFrom for GGSWCiphertext<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
self.digits = Digits(reader.read_u32::<LittleEndian>()?);
self.dsize = Dsize(reader.read_u32::<LittleEndian>()?);
self.data.read_from(reader)
}
}
@@ -366,7 +366,7 @@ impl<D: DataRef> WriterTo for GGSWCiphertext<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u32::<LittleEndian>(self.k.into())?;
writer.write_u32::<LittleEndian>(self.base2k.into())?;
writer.write_u32::<LittleEndian>(self.digits.into())?;
writer.write_u32::<LittleEndian>(self.dsize.into())?;
self.data.write_to(writer)
}
}

View File

@@ -3,22 +3,20 @@ use poulpy_hal::{
source::Source,
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
};
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
use std::fmt;
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct GLWEToLWESwitchingKeyLayout {
pub struct GLWEToLWEKeyLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub rank_in: Rank,
pub dnum: Dnum,
}
impl LWEInfos for GLWEToLWESwitchingKeyLayout {
impl LWEInfos for GLWEToLWEKeyLayout {
fn n(&self) -> Degree {
self.n
}
@@ -32,35 +30,35 @@ impl LWEInfos for GLWEToLWESwitchingKeyLayout {
}
}
impl GLWEInfos for GLWEToLWESwitchingKeyLayout {
impl GLWEInfos for GLWEToLWEKeyLayout {
fn rank(&self) -> Rank {
self.rank_out()
}
}
impl GGLWELayoutInfos for GLWEToLWESwitchingKeyLayout {
impl GGLWEInfos for GLWEToLWEKeyLayout {
fn rank_in(&self) -> Rank {
self.rank_in
}
fn digits(&self) -> Digits {
Digits(1)
fn dsize(&self) -> Dsize {
Dsize(1)
}
fn rank_out(&self) -> Rank {
Rank(1)
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
/// A special [GLWESwitchingKey] required to for the conversion from [GLWECiphertext] to [LWECiphertext].
#[derive(PartialEq, Eq, Clone)]
pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>);
pub struct GLWEToLWEKey<D: Data>(pub(crate) GGLWESwitchingKey<D>);
impl<D: Data> LWEInfos for GLWEToLWESwitchingKey<D> {
impl<D: Data> LWEInfos for GLWEToLWEKey<D> {
fn base2k(&self) -> Base2K {
self.0.base2k()
}
@@ -78,63 +76,63 @@ impl<D: Data> LWEInfos for GLWEToLWESwitchingKey<D> {
}
}
impl<D: Data> GLWEInfos for GLWEToLWESwitchingKey<D> {
impl<D: Data> GLWEInfos for GLWEToLWEKey<D> {
fn rank(&self) -> Rank {
self.rank_out()
}
}
impl<D: Data> GGLWELayoutInfos for GLWEToLWESwitchingKey<D> {
impl<D: Data> GGLWEInfos for GLWEToLWEKey<D> {
fn rank_in(&self) -> Rank {
self.0.rank_in()
}
fn digits(&self) -> Digits {
self.0.digits()
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_out(&self) -> Rank {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKey<D> {
impl<D: DataRef> fmt::Debug for GLWEToLWEKey<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{self}")
}
}
impl<D: DataMut> FillUniform for GLWEToLWESwitchingKey<D> {
impl<D: DataMut> FillUniform for GLWEToLWEKey<D> {
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
self.0.fill_uniform(log_bound, source);
}
}
impl<D: DataRef> fmt::Display for GLWEToLWESwitchingKey<D> {
impl<D: DataRef> fmt::Display for GLWEToLWEKey<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "(GLWEToLWESwitchingKey) {}", self.0)
}
}
impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKey<D> {
impl<D: DataMut> ReaderFrom for GLWEToLWEKey<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.0.read_from(reader)
}
}
impl<D: DataRef> WriterTo for GLWEToLWESwitchingKey<D> {
impl<D: DataRef> WriterTo for GLWEToLWEKey<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
self.0.write_to(writer)
}
}
impl GLWEToLWESwitchingKey<Vec<u8>> {
impl GLWEToLWEKey<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.rank_out().0,
@@ -142,28 +140,28 @@ impl GLWEToLWESwitchingKey<Vec<u8>> {
"rank_out > 1 is not supported for GLWEToLWESwitchingKey"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for GLWEToLWESwitchingKey"
"dsize > 1 is not supported for GLWEToLWESwitchingKey"
);
Self(GGLWESwitchingKey::alloc(infos))
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_in: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self {
Self(GGLWESwitchingKey::alloc_with(
n,
base2k,
k,
rows,
Digits(1),
rank_in,
Rank(1),
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.rank_out().0,
@@ -171,14 +169,14 @@ impl GLWEToLWESwitchingKey<Vec<u8>> {
"rank_out > 1 is not supported for GLWEToLWESwitchingKey"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for GLWEToLWESwitchingKey"
"dsize > 1 is not supported for GLWEToLWESwitchingKey"
);
GGLWESwitchingKey::alloc_bytes(infos)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_in: Rank) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rows, Digits(1), rank_in, Rank(1))
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rank_in, Rank(1), dnum, Dsize(1))
}
}

View File

@@ -5,16 +5,14 @@ use poulpy_hal::{
source::Source,
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
};
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct LWESwitchingKeyLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub dnum: Dnum,
}
impl LWEInfos for LWESwitchingKeyLayout {
@@ -37,21 +35,21 @@ impl GLWEInfos for LWESwitchingKeyLayout {
}
}
impl GGLWELayoutInfos for LWESwitchingKeyLayout {
impl GGLWEInfos for LWESwitchingKeyLayout {
fn rank_in(&self) -> Rank {
Rank(1)
}
fn digits(&self) -> Digits {
Digits(1)
fn dsize(&self) -> Dsize {
Dsize(1)
}
fn rank_out(&self) -> Rank {
Rank(1)
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
@@ -82,9 +80,9 @@ impl<D: Data> GLWEInfos for LWESwitchingKey<D> {
}
}
impl<D: Data> GGLWELayoutInfos for LWESwitchingKey<D> {
fn digits(&self) -> Digits {
self.0.digits()
impl<D: Data> GGLWEInfos for LWESwitchingKey<D> {
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_in(&self) -> Rank {
@@ -95,20 +93,20 @@ impl<D: Data> GGLWELayoutInfos for LWESwitchingKey<D> {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
impl LWESwitchingKey<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWESwitchingKey"
"dsize > 1 is not supported for LWESwitchingKey"
);
debug_assert_eq!(
infos.rank_in().0,
@@ -123,26 +121,26 @@ impl LWESwitchingKey<Vec<u8>> {
Self(GGLWESwitchingKey::alloc(infos))
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self {
Self(GGLWESwitchingKey::alloc_with(
n,
base2k,
k,
rows,
Digits(1),
Rank(1),
Rank(1),
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWESwitchingKey"
"dsize > 1 is not supported for LWESwitchingKey"
);
debug_assert_eq!(
infos.rank_in().0,
@@ -157,8 +155,8 @@ impl LWESwitchingKey<Vec<u8>> {
GGLWESwitchingKey::alloc_bytes(infos)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rows, Digits(1), Rank(1), Rank(1))
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), Rank(1), dnum, Dsize(1))
}
}

View File

@@ -5,17 +5,15 @@ use poulpy_hal::{
source::Source,
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
};
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct LWEToGLWESwitchingKeyLayout {
pub n: Degree,
pub base2k: Base2K,
pub k: TorusPrecision,
pub rows: Rows,
pub rank_out: Rank,
pub dnum: Dnum,
}
impl LWEInfos for LWEToGLWESwitchingKeyLayout {
@@ -38,21 +36,21 @@ impl GLWEInfos for LWEToGLWESwitchingKeyLayout {
}
}
impl GGLWELayoutInfos for LWEToGLWESwitchingKeyLayout {
impl GGLWEInfos for LWEToGLWESwitchingKeyLayout {
fn rank_in(&self) -> Rank {
Rank(1)
}
fn digits(&self) -> Digits {
Digits(1)
fn dsize(&self) -> Dsize {
Dsize(1)
}
fn rank_out(&self) -> Rank {
self.rank_out
}
fn rows(&self) -> Rows {
self.rows
fn dnum(&self) -> Dnum {
self.dnum
}
}
@@ -82,9 +80,9 @@ impl<D: Data> GLWEInfos for LWEToGLWESwitchingKey<D> {
self.rank_out()
}
}
impl<D: Data> GGLWELayoutInfos for LWEToGLWESwitchingKey<D> {
fn digits(&self) -> Digits {
self.0.digits()
impl<D: Data> GGLWEInfos for LWEToGLWESwitchingKey<D> {
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_in(&self) -> Rank {
@@ -95,8 +93,8 @@ impl<D: Data> GGLWELayoutInfos for LWEToGLWESwitchingKey<D> {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
@@ -133,7 +131,7 @@ impl<D: DataRef> WriterTo for LWEToGLWESwitchingKey<D> {
impl LWEToGLWESwitchingKey<Vec<u8>> {
pub fn alloc<A>(infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.rank_in().0,
@@ -141,28 +139,28 @@ impl LWEToGLWESwitchingKey<Vec<u8>> {
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWEToGLWESwitchingKey"
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
);
Self(GGLWESwitchingKey::alloc(infos))
}
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_out: Rank) -> Self {
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self {
Self(GGLWESwitchingKey::alloc_with(
n,
base2k,
k,
rows,
Digits(1),
Rank(1),
rank_out,
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
debug_assert_eq!(
infos.rank_in().0,
@@ -170,14 +168,14 @@ impl LWEToGLWESwitchingKey<Vec<u8>> {
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWEToGLWESwitchingKey"
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
);
GGLWESwitchingKey::alloc_bytes(infos)
}
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_out: Rank) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rows, Digits(1), Rank(1), rank_out)
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize {
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), rank_out, dnum, Dsize(1))
}
}

View File

@@ -209,9 +209,9 @@ macro_rules! newtype_u32 {
newtype_u32!(Degree);
newtype_u32!(TorusPrecision);
newtype_u32!(Base2K);
newtype_u32!(Rows);
newtype_u32!(Dnum);
newtype_u32!(Rank);
newtype_u32!(Digits);
newtype_u32!(Dsize);
impl Degree {
pub fn log2(&self) -> usize {

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWEAutomorphismKey, GGLWELayoutInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
@@ -44,7 +44,7 @@ impl<D: Data, B: Backend> GLWEInfos for GGLWEAutomorphismKeyPrepared<D, B> {
}
}
impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWEAutomorphismKeyPrepared<D, B> {
impl<D: Data, B: Backend> GGLWEInfos for GGLWEAutomorphismKeyPrepared<D, B> {
fn rank_in(&self) -> Rank {
self.key.rank_in()
}
@@ -53,19 +53,19 @@ impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWEAutomorphismKeyPrepared<D, B
self.key.rank_out()
}
fn digits(&self) -> Digits {
self.key.digits()
fn dsize(&self) -> Dsize {
self.key.dsize()
}
fn rows(&self) -> Rows {
self.key.rows()
fn dnum(&self) -> Dnum {
self.key.dnum()
}
}
impl<B: Backend> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAlloc<B>,
{
assert_eq!(
@@ -79,19 +79,19 @@ impl<B: Backend> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> {
}
}
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
GGLWEAutomorphismKeyPrepared {
key: GGLWESwitchingKeyPrepared::alloc_with(module, base2k, k, rows, digits, rank, rank),
key: GGLWESwitchingKeyPrepared::alloc_with(module, base2k, k, rank, rank, dnum, dsize),
p: 0,
}
}
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAllocBytes,
{
assert_eq!(
@@ -102,18 +102,11 @@ impl<B: Backend> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> {
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
}
pub fn alloc_bytes_with(
module: &Module<B>,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank: Rank,
) -> usize
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rows, digits, rank, rank)
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rank, rank, dnum, dsize)
}
}

View File

@@ -5,7 +5,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, BuildError, Degree, Digits, GGLWECiphertext, GGLWELayoutInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, BuildError, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
prepared::{Prepare, PrepareAlloc},
};
@@ -14,7 +14,7 @@ pub struct GGLWECiphertextPrepared<D: Data, B: Backend> {
pub(crate) data: VmpPMat<D, B>,
pub(crate) k: TorusPrecision,
pub(crate) base2k: Base2K,
pub(crate) digits: Digits,
pub(crate) dsize: Dsize,
}
impl<D: Data, B: Backend> LWEInfos for GGLWECiphertextPrepared<D, B> {
@@ -41,7 +41,7 @@ impl<D: Data, B: Backend> GLWEInfos for GGLWECiphertextPrepared<D, B> {
}
}
impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWECiphertextPrepared<D, B> {
impl<D: Data, B: Backend> GGLWEInfos for GGLWECiphertextPrepared<D, B> {
fn rank_in(&self) -> Rank {
Rank(self.data.cols_in() as u32)
}
@@ -50,12 +50,12 @@ impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWECiphertextPrepared<D, B> {
Rank(self.data.cols_out() as u32 - 1)
}
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
Rows(self.data.rows() as u32)
fn dnum(&self) -> Dnum {
Dnum(self.data.rows() as u32)
}
}
@@ -63,7 +63,7 @@ pub struct GGLWECiphertextPreparedBuilder<D: Data, B: Backend> {
data: Option<VmpPMat<D, B>>,
base2k: Option<Base2K>,
k: Option<TorusPrecision>,
digits: Option<Digits>,
dsize: Option<Dsize>,
}
impl<D: Data, B: Backend> GGLWECiphertextPrepared<D, B> {
@@ -73,7 +73,7 @@ impl<D: Data, B: Backend> GGLWECiphertextPrepared<D, B> {
data: None,
base2k: None,
k: None,
digits: None,
dsize: None,
}
}
}
@@ -82,19 +82,19 @@ impl<B: Backend> GGLWECiphertextPreparedBuilder<Vec<u8>, B> {
#[inline]
pub fn layout<A>(mut self, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
B: VmpPMatAllocBytesImpl<B>,
{
self.data = Some(VmpPMat::alloc(
infos.n().into(),
infos.rows().into(),
infos.dnum().into(),
infos.rank_in().into(),
(infos.rank_out() + 1).into(),
infos.size(),
));
self.base2k = Some(infos.base2k());
self.k = Some(infos.k());
self.digits = Some(infos.digits());
self.dsize = Some(infos.dsize());
self
}
}
@@ -117,8 +117,8 @@ impl<D: Data, B: Backend> GGLWECiphertextPreparedBuilder<D, B> {
}
#[inline]
pub fn digits(mut self, digits: Digits) -> Self {
self.digits = Some(digits);
pub fn dsize(mut self, dsize: Dsize) -> Self {
self.dsize = Some(dsize);
self
}
@@ -126,13 +126,13 @@ impl<D: Data, B: Backend> GGLWECiphertextPreparedBuilder<D, B> {
let data: VmpPMat<D, B> = self.data.ok_or(BuildError::MissingData)?;
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
let digits: Digits = self.digits.ok_or(BuildError::MissingDigits)?;
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
if base2k == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
if digits == 0_u32 {
if dsize == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
@@ -156,7 +156,7 @@ impl<D: Data, B: Backend> GGLWECiphertextPreparedBuilder<D, B> {
data,
base2k,
k,
digits,
dsize,
})
}
}
@@ -164,7 +164,7 @@ impl<D: Data, B: Backend> GGLWECiphertextPreparedBuilder<D, B> {
impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAlloc<B>,
{
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
@@ -172,10 +172,10 @@ impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
module,
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_in(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
@@ -183,39 +183,39 @@ impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
module: &Module<B>,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid gglwe: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid gglwe: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
Self {
data: module.vmp_pmat_alloc(rows.into(), rank_in.into(), (rank_out + 1).into(), size),
data: module.vmp_pmat_alloc(dnum.into(), rank_in.into(), (rank_out + 1).into(), size),
k,
base2k,
digits,
dsize,
}
}
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAllocBytes,
{
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
@@ -223,10 +223,10 @@ impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
module,
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.rank_in(),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
@@ -234,29 +234,29 @@ impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
module: &Module<B>,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid gglwe: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid gglwe: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
module.vmp_pmat_alloc_bytes(rows.into(), rank_in.into(), (rank_out + 1).into(), size)
module.vmp_pmat_alloc_bytes(dnum.into(), rank_in.into(), (rank_out + 1).into(), size)
}
}
@@ -268,7 +268,7 @@ where
module.vmp_prepare(&mut self.data, &other.data, scratch);
self.k = other.k;
self.base2k = other.base2k;
self.digits = other.digits;
self.dsize = other.dsize;
}
}

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
prepared::{GGLWECiphertextPrepared, Prepare, PrepareAlloc},
};
@@ -39,7 +39,7 @@ impl<D: Data, B: Backend> GLWEInfos for GGLWESwitchingKeyPrepared<D, B> {
}
}
impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWESwitchingKeyPrepared<D, B> {
impl<D: Data, B: Backend> GGLWEInfos for GGLWESwitchingKeyPrepared<D, B> {
fn rank_in(&self) -> Rank {
self.key.rank_in()
}
@@ -48,19 +48,19 @@ impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWESwitchingKeyPrepared<D, B> {
self.key.rank_out()
}
fn digits(&self) -> Digits {
self.key.digits()
fn dsize(&self) -> Dsize {
self.key.dsize()
}
fn rows(&self) -> Rows {
self.key.rows()
fn dnum(&self) -> Dnum {
self.key.dnum()
}
}
impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAlloc<B>,
{
debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()");
@@ -75,16 +75,16 @@ impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
module: &Module<B>,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
GGLWESwitchingKeyPrepared::<Vec<u8>, B> {
key: GGLWECiphertextPrepared::alloc_with(module, base2k, k, rows, digits, rank_in, rank_out),
key: GGLWECiphertextPrepared::alloc_with(module, base2k, k, rank_in, rank_out, dnum, dsize),
sk_in_n: 0,
sk_out_n: 0,
}
@@ -92,7 +92,7 @@ impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAllocBytes,
{
debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()");
@@ -103,15 +103,15 @@ impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
module: &Module<B>,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
GGLWECiphertextPrepared::alloc_bytes_with(module, base2k, k, rows, digits, rank_in, rank_out)
GGLWECiphertextPrepared::alloc_bytes_with(module, base2k, k, rank_in, rank_out, dnum, dsize)
}
}

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
@@ -37,7 +37,7 @@ impl<D: Data, B: Backend> GLWEInfos for GGLWETensorKeyPrepared<D, B> {
}
}
impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWETensorKeyPrepared<D, B> {
impl<D: Data, B: Backend> GGLWEInfos for GGLWETensorKeyPrepared<D, B> {
fn rank_in(&self) -> Rank {
self.rank_out()
}
@@ -46,19 +46,19 @@ impl<D: Data, B: Backend> GGLWELayoutInfos for GGLWETensorKeyPrepared<D, B> {
self.keys[0].rank_out()
}
fn digits(&self) -> Digits {
self.keys[0].digits()
fn dsize(&self) -> Dsize {
self.keys[0].dsize()
}
fn rows(&self) -> Rows {
self.keys[0].rows()
fn dnum(&self) -> Dnum {
self.keys[0].dnum()
}
}
impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAlloc<B>,
{
assert_eq!(
@@ -70,13 +70,13 @@ impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
module,
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.dnum(),
infos.dsize(),
infos.rank_out(),
)
}
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
@@ -87,10 +87,10 @@ impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
module,
base2k,
k,
rows,
digits,
Rank(1),
rank,
dnum,
dsize,
));
});
Self { keys }
@@ -98,7 +98,7 @@ impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAllocBytes,
{
assert_eq!(
@@ -113,26 +113,19 @@ impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
module,
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
Rank(1),
infos.rank_out(),
infos.dnum(),
infos.dsize(),
)
}
pub fn alloc_bytes_with(
module: &Module<B>,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank: Rank,
) -> usize
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
pairs * GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rows, digits, Rank(1), rank)
pairs * GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank, dnum, dsize)
}
}

View File

@@ -1,11 +1,11 @@
use poulpy_hal::{
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, ZnxInfos},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToRef, ZnxInfos},
oep::VmpPMatAllocBytesImpl,
};
use crate::layouts::{
Base2K, BuildError, Degree, Digits, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, BuildError, Degree, Dnum, Dsize, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
prepared::{Prepare, PrepareAlloc},
};
@@ -14,7 +14,7 @@ pub struct GGSWCiphertextPrepared<D: Data, B: Backend> {
pub(crate) data: VmpPMat<D, B>,
pub(crate) k: TorusPrecision,
pub(crate) base2k: Base2K,
pub(crate) digits: Digits,
pub(crate) dsize: Dsize,
}
impl<D: Data, B: Backend> LWEInfos for GGSWCiphertextPrepared<D, B> {
@@ -42,12 +42,12 @@ impl<D: Data, B: Backend> GLWEInfos for GGSWCiphertextPrepared<D, B> {
}
impl<D: Data, B: Backend> GGSWInfos for GGSWCiphertextPrepared<D, B> {
fn digits(&self) -> Digits {
self.digits
fn dsize(&self) -> Dsize {
self.dsize
}
fn rows(&self) -> Rows {
Rows(self.data.rows() as u32)
fn dnum(&self) -> Dnum {
Dnum(self.data.rows() as u32)
}
}
@@ -55,7 +55,7 @@ pub struct GGSWCiphertextPreparedBuilder<D: Data, B: Backend> {
data: Option<VmpPMat<D, B>>,
base2k: Option<Base2K>,
k: Option<TorusPrecision>,
digits: Option<Digits>,
dsize: Option<Dsize>,
}
impl<D: Data, B: Backend> GGSWCiphertextPrepared<D, B> {
@@ -65,7 +65,7 @@ impl<D: Data, B: Backend> GGSWCiphertextPrepared<D, B> {
data: None,
base2k: None,
k: None,
digits: None,
dsize: None,
}
}
}
@@ -78,30 +78,30 @@ impl<B: Backend> GGSWCiphertextPreparedBuilder<Vec<u8>, B> {
B: VmpPMatAllocBytesImpl<B>,
{
debug_assert!(
infos.size() as u32 > infos.digits().0,
"invalid ggsw: ceil(k/base2k): {} <= digits: {}",
infos.size() as u32 > infos.dsize().0,
"invalid ggsw: ceil(k/base2k): {} <= dsize: {}",
infos.size(),
infos.digits()
infos.dsize()
);
assert!(
infos.rows().0 * infos.digits().0 <= infos.size() as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {}",
infos.rows(),
infos.digits(),
infos.dnum().0 * infos.dsize().0 <= infos.size() as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {}",
infos.dnum(),
infos.dsize(),
infos.size(),
);
self.data = Some(VmpPMat::alloc(
infos.n().into(),
infos.rows().into(),
infos.dnum().into(),
(infos.rank() + 1).into(),
(infos.rank() + 1).into(),
infos.size(),
));
self.base2k = Some(infos.base2k());
self.k = Some(infos.k());
self.digits = Some(infos.digits());
self.dsize = Some(infos.dsize());
self
}
}
@@ -124,8 +124,8 @@ impl<D: Data, B: Backend> GGSWCiphertextPreparedBuilder<D, B> {
}
#[inline]
pub fn digits(mut self, digits: Digits) -> Self {
self.digits = Some(digits);
pub fn dsize(mut self, dsize: Dsize) -> Self {
self.dsize = Some(dsize);
self
}
@@ -133,13 +133,13 @@ impl<D: Data, B: Backend> GGSWCiphertextPreparedBuilder<D, B> {
let data: VmpPMat<D, B> = self.data.ok_or(BuildError::MissingData)?;
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
let digits: Digits = self.digits.ok_or(BuildError::MissingDigits)?;
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
if base2k == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
if digits == 0_u32 {
if dsize == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
@@ -163,7 +163,7 @@ impl<D: Data, B: Backend> GGSWCiphertextPreparedBuilder<D, B> {
data,
base2k,
k,
digits,
dsize,
})
}
}
@@ -178,40 +178,40 @@ impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
module,
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.dnum(),
infos.dsize(),
infos.rank(),
)
}
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows, digits: Digits, rank: Rank) -> Self
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid ggsw: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
Self {
data: module.vmp_pmat_alloc(
rows.into(),
dnum.into(),
(rank + 1).into(),
(rank + 1).into(),
k.0.div_ceil(base2k.0) as usize,
),
k,
base2k,
digits,
dsize,
}
}
@@ -224,38 +224,31 @@ impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
module,
infos.base2k(),
infos.k(),
infos.rows(),
infos.digits(),
infos.dnum(),
infos.dsize(),
infos.rank(),
)
}
pub fn alloc_bytes_with(
module: &Module<B>,
base2k: Base2K,
k: TorusPrecision,
rows: Rows,
digits: Digits,
rank: Rank,
) -> usize
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
let size: usize = k.0.div_ceil(base2k.0) as usize;
debug_assert!(
size as u32 > digits.0,
"invalid ggsw: ceil(k/base2k): {size} <= digits: {}",
digits.0
size as u32 > dsize.0,
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
dsize.0
);
assert!(
rows.0 * digits.0 <= size as u32,
"invalid ggsw: rows: {} * digits:{} > ceil(k/base2k): {size}",
rows.0,
digits.0,
dnum.0 * dsize.0 <= size as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
dnum.0,
dsize.0,
);
module.vmp_pmat_alloc_bytes(rows.into(), (rank + 1).into(), (rank + 1).into(), size)
module.vmp_pmat_alloc_bytes(dnum.into(), (rank + 1).into(), (rank + 1).into(), size)
}
}
@@ -273,7 +266,7 @@ where
module.vmp_prepare(&mut self.data, &other.data, scratch);
self.k = other.k;
self.base2k = other.base2k;
self.digits = other.digits;
self.dsize = other.dsize;
}
}
@@ -287,3 +280,19 @@ where
ggsw_prepared
}
}
pub trait GGSWCiphertextPreparedToRef<B: Backend> {
fn to_ref(&self) -> GGSWCiphertextPrepared<&[u8], B>;
}
impl<D: DataRef, B: Backend> GGSWCiphertextPreparedToRef<B> for GGSWCiphertextPrepared<D, B> {
fn to_ref(&self) -> GGSWCiphertextPrepared<&[u8], B> {
GGSWCiphertextPrepared::builder()
.base2k(self.base2k())
.dsize(self.dsize())
.k(self.k())
.data(self.data.to_ref())
.build()
.unwrap()
}
}

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GLWEInfos, GLWEToLWESwitchingKey, LWEInfos, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWEToLWEKey, LWEInfos, Rank, TorusPrecision,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
@@ -35,28 +35,28 @@ impl<D: Data, B: Backend> GLWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
}
}
impl<D: Data, B: Backend> GGLWELayoutInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
impl<D: Data, B: Backend> GGLWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
fn rank_in(&self) -> Rank {
self.0.rank_in()
}
fn digits(&self) -> Digits {
self.0.digits()
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_out(&self) -> Rank {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAlloc<B>,
{
debug_assert_eq!(
@@ -65,14 +65,14 @@ impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
"rank_out > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
);
Self(GGLWESwitchingKeyPrepared::alloc(module, infos))
}
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_in: Rank) -> Self
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
@@ -80,16 +80,16 @@ impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
module,
base2k,
k,
rows,
Digits(1),
rank_in,
Rank(1),
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAllocBytes,
{
debug_assert_eq!(
@@ -98,22 +98,22 @@ impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
"rank_out > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
);
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
}
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_in: Rank) -> usize
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rows, Digits(1), rank_in, Rank(1))
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rank_in, Rank(1), dnum, Dsize(1))
}
}
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>> for GLWEToLWESwitchingKey<D>
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>> for GLWEToLWEKey<D>
where
Module<B>: VmpPrepare<B> + VmpPMatAlloc<B>,
{
@@ -124,11 +124,11 @@ where
}
}
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEToLWESwitchingKey<DR>> for GLWEToLWESwitchingKeyPrepared<DM, B>
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEToLWEKey<DR>> for GLWEToLWESwitchingKeyPrepared<DM, B>
where
Module<B>: VmpPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GLWEToLWESwitchingKey<DR>, scratch: &mut Scratch<B>) {
fn prepare(&mut self, module: &Module<B>, other: &GLWEToLWEKey<DR>, scratch: &mut Scratch<B>) {
self.0.prepare(module, &other.0, scratch);
}
}

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, TorusPrecision,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
@@ -34,9 +34,9 @@ impl<D: Data, B: Backend> GLWEInfos for LWESwitchingKeyPrepared<D, B> {
}
}
impl<D: Data, B: Backend> GGLWELayoutInfos for LWESwitchingKeyPrepared<D, B> {
fn digits(&self) -> Digits {
self.0.digits()
impl<D: Data, B: Backend> GGLWEInfos for LWESwitchingKeyPrepared<D, B> {
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_in(&self) -> Rank {
@@ -47,21 +47,21 @@ impl<D: Data, B: Backend> GGLWELayoutInfos for LWESwitchingKeyPrepared<D, B> {
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAlloc<B>,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWESwitchingKey"
"dsize > 1 is not supported for LWESwitchingKey"
);
debug_assert_eq!(
infos.rank_in().0,
@@ -76,7 +76,7 @@ impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> {
Self(GGLWESwitchingKeyPrepared::alloc(module, infos))
}
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows) -> Self
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
@@ -84,22 +84,22 @@ impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> {
module,
base2k,
k,
rows,
Digits(1),
Rank(1),
Rank(1),
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAllocBytes,
{
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWESwitchingKey"
"dsize > 1 is not supported for LWESwitchingKey"
);
debug_assert_eq!(
infos.rank_in().0,
@@ -114,11 +114,11 @@ impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> {
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
}
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows) -> usize
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rows, Digits(1), Rank(1), Rank(1))
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), Rank(1), dnum, Dsize(1))
}
}

View File

@@ -4,7 +4,7 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, Digits, GGLWELayoutInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, TorusPrecision,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
@@ -36,9 +36,9 @@ impl<D: Data, B: Backend> GLWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
}
}
impl<D: Data, B: Backend> GGLWELayoutInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
fn digits(&self) -> Digits {
self.0.digits()
impl<D: Data, B: Backend> GGLWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
fn dsize(&self) -> Dsize {
self.0.dsize()
}
fn rank_in(&self) -> Rank {
@@ -49,15 +49,15 @@ impl<D: Data, B: Backend> GGLWELayoutInfos for LWEToGLWESwitchingKeyPrepared<D,
self.0.rank_out()
}
fn rows(&self) -> Rows {
self.0.rows()
fn dnum(&self) -> Dnum {
self.0.dnum()
}
}
impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAlloc<B>,
{
debug_assert_eq!(
@@ -66,14 +66,14 @@ impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWEToGLWESwitchingKey"
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
);
Self(GGLWESwitchingKeyPrepared::alloc(module, infos))
}
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_out: Rank) -> Self
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
@@ -81,16 +81,16 @@ impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
module,
base2k,
k,
rows,
Digits(1),
Rank(1),
rank_out,
dnum,
Dsize(1),
))
}
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
Module<B>: VmpPMatAllocBytes,
{
debug_assert_eq!(
@@ -99,18 +99,18 @@ impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
);
debug_assert_eq!(
infos.digits().0,
infos.dsize().0,
1,
"digits > 1 is not supported for LWEToGLWESwitchingKey"
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
);
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
}
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rows: Rows, rank_out: Rank) -> usize
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rows, Digits(1), Rank(1), rank_out)
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank_out, dnum, Dsize(1))
}
}

View File

@@ -15,6 +15,7 @@ mod utils;
pub use operations::*;
pub mod layouts;
pub use dist::*;
pub use external_product::*;
pub use glwe_packing::*;
pub use encryption::SIGMA;

View File

@@ -8,7 +8,7 @@ use poulpy_hal::{
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl},
};
use crate::layouts::{GGLWECiphertext, GGLWELayoutInfos, GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared};
use crate::layouts::{GGLWECiphertext, GGLWEInfos, GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared};
impl<D: DataRef> GGLWECiphertext<D> {
pub fn assert_noise<B, DataSk, DataWant>(
@@ -32,24 +32,18 @@ impl<D: DataRef> GGLWECiphertext<D> {
+ VecZnxSubScalarInplace,
B: Backend + TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>,
{
let digits: usize = self.digits().into();
let dsize: usize = self.dsize().into();
let base2k: usize = self.base2k().into();
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self));
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self);
(0..self.rank_in().into()).for_each(|col_i| {
(0..self.rows().into()).for_each(|row_i| {
(0..self.dnum().into()).for_each(|row_i| {
self.at(row_i, col_i)
.decrypt(module, &mut pt, sk, scratch.borrow());
module.vec_znx_sub_scalar_inplace(
&mut pt.data,
0,
(digits - 1) + row_i * digits,
pt_want,
col_i,
);
module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, col_i);
let noise_have: f64 = pt.data.std(base2k, 0).log2();

View File

@@ -42,7 +42,7 @@ impl<D: DataRef> GGSWCiphertext<D> {
F: Fn(usize) -> f64,
{
let base2k: usize = self.base2k().into();
let digits: usize = self.digits().into();
let dsize: usize = self.dsize().into();
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self);
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self);
@@ -53,8 +53,8 @@ impl<D: DataRef> GGSWCiphertext<D> {
ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self) | module.vec_znx_normalize_tmp_bytes());
(0..(self.rank() + 1).into()).for_each(|col_j| {
(0..self.rows().into()).for_each(|row_i| {
module.vec_znx_add_scalar_inplace(&mut pt.data, 0, (digits - 1) + row_i * digits, pt_want, 0);
(0..self.dnum().into()).for_each(|row_i| {
module.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0);
// mul with sk[col_j-1]
if col_j > 0 {
@@ -114,7 +114,7 @@ impl<D: DataRef> GGSWCiphertext<D> {
B: Backend + TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>,
{
let base2k: usize = self.base2k().into();
let digits: usize = self.digits().into();
let dsize: usize = self.dsize().into();
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self);
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self);
@@ -125,8 +125,8 @@ impl<D: DataRef> GGSWCiphertext<D> {
ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self) | module.vec_znx_normalize_tmp_bytes());
(0..(self.rank() + 1).into()).for_each(|col_j| {
(0..self.rows().into()).for_each(|row_i| {
module.vec_znx_add_scalar_inplace(&mut pt.data, 0, (digits - 1) + row_i * digits, pt_want, 0);
(0..self.dnum().into()).for_each(|row_i| {
module.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0);
// mul with sk[col_j-1]
if col_j > 0 {
@@ -146,12 +146,12 @@ impl<D: DataRef> GGSWCiphertext<D> {
self.at(row_i, col_j)
.decrypt(module, &mut pt_have, sk_prepared, scratch.borrow());
module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt.data, 0);
let std_pt: f64 = pt_have.data.std(base2k, 0).log2();
println!("col: {col_j} row: {row_i}: {std_pt}");
pt.data.zero();
// println!(">>>>>>>>>>>>>>>>");
});
});
}

View File

@@ -1,16 +1,44 @@
use poulpy_hal::{
api::{
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume,
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSubInplace,
ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace,
VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply,
VecZnxIdftApplyConsume, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSubInplace,
},
layouts::{Backend, DataRef, Module, ScratchOwned},
layouts::{Backend, DataRef, Module, Scratch, ScratchOwned},
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl},
};
use crate::layouts::{GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared};
impl<D: DataRef> GLWECiphertext<D> {
pub fn noise<B, DataSk, DataPt>(
&self,
module: &Module<B>,
sk_prepared: &GLWESecretPrepared<DataSk, B>,
pt_want: &GLWEPlaintext<DataPt>,
scratch: &mut Scratch<B>,
) -> f64
where
DataSk: DataRef,
DataPt: DataRef,
B: Backend,
Module<B>: VecZnxDftApply<B>
+ VecZnxSubInplace
+ VecZnxNormalizeInplace<B>
+ SvpApplyDftToDftInplace<B>
+ VecZnxIdftApplyConsume<B>
+ VecZnxBigAddInplace<B>
+ VecZnxBigAddSmallInplace<B>
+ VecZnxBigNormalize<B>,
Scratch<B>: TakeVecZnxDft<B> + TakeVecZnxBig<B>,
{
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self);
self.decrypt(module, &mut pt_have, sk_prepared, scratch);
module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0);
module.vec_znx_normalize_inplace(self.base2k().into(), &mut pt_have.data, 0, scratch);
pt_have.data.std(self.base2k().into(), 0).log2()
}
pub fn assert_noise<B, DataSk, DataPt>(
&self,
module: &Module<B>,
@@ -33,16 +61,8 @@ impl<D: DataRef> GLWECiphertext<D> {
+ VecZnxNormalizeInplace<B>,
B: Backend + TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>,
{
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self));
self.decrypt(module, &mut pt_have, sk_prepared, scratch.borrow());
module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0);
module.vec_znx_normalize_inplace(self.base2k().into(), &mut pt_have.data, 0, scratch.borrow());
let noise_have: f64 = pt_have.data.std(self.base2k().into(), 0).log2();
let noise_have: f64 = self.noise(module, sk_prepared, pt_want, scratch.borrow());
assert!(noise_have <= max_noise, "{noise_have} {max_noise}");
}
}

View File

@@ -6,8 +6,8 @@ use poulpy_hal::{
use crate::{
dist::Distribution,
layouts::{
Degree, GGLWEAutomorphismKey, GGLWECiphertext, GGLWELayoutInfos, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext,
GGSWInfos, GLWECiphertext, GLWEInfos, GLWEPlaintext, GLWEPublicKey, GLWESecret, Rank,
Degree, GGLWEAutomorphismKey, GGLWECiphertext, GGLWEInfos, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GGSWInfos,
GLWECiphertext, GLWEInfos, GLWEPlaintext, GLWEPublicKey, GLWESecret, Rank,
prepared::{
GGLWEAutomorphismKeyPrepared, GGLWECiphertextPrepared, GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared,
GGSWCiphertextPrepared, GLWEPublicKeyPrepared, GLWESecretPrepared,
@@ -36,13 +36,13 @@ pub trait TakeGLWEPt<B: Backend> {
pub trait TakeGGLWE {
fn take_gglwe<A>(&mut self, infos: &A) -> (GGLWECiphertext<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
pub trait TakeGGLWEPrepared<B: Backend> {
fn take_gglwe_prepared<A>(&mut self, infos: &A) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
pub trait TakeGGSW {
@@ -80,37 +80,37 @@ pub trait TakeGLWEPkPrepared<B: Backend> {
pub trait TakeGLWESwitchingKey {
fn take_glwe_switching_key<A>(&mut self, infos: &A) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
pub trait TakeGGLWESwitchingKeyPrepared<B: Backend> {
fn take_gglwe_switching_key_prepared<A>(&mut self, infos: &A) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
pub trait TakeTensorKey {
fn take_tensor_key<A>(&mut self, infos: &A) -> (GGLWETensorKey<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
pub trait TakeGGLWETensorKeyPrepared<B: Backend> {
fn take_gglwe_tensor_key_prepared<A>(&mut self, infos: &A) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
pub trait TakeGGLWEAutomorphismKey {
fn take_gglwe_automorphism_key<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
pub trait TakeGGLWEAutomorphismKeyPrepared<B: Backend> {
fn take_gglwe_automorphism_key_prepared<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos;
A: GGLWEInfos;
}
impl<B: Backend> TakeGLWECt for Scratch<B>
@@ -180,11 +180,11 @@ where
{
fn take_gglwe<A>(&mut self, infos: &A) -> (GGLWECiphertext<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
let (data, scratch) = self.take_mat_znx(
infos.n().into(),
infos.rows().0.div_ceil(infos.digits().0) as usize,
infos.dnum().0.div_ceil(infos.dsize().0) as usize,
infos.rank_in().into(),
(infos.rank_out() + 1).into(),
infos.size(),
@@ -193,7 +193,7 @@ where
GGLWECiphertext::builder()
.base2k(infos.base2k())
.k(infos.k())
.digits(infos.digits())
.dsize(infos.dsize())
.data(data)
.build()
.unwrap(),
@@ -208,11 +208,11 @@ where
{
fn take_gglwe_prepared<A>(&mut self, infos: &A) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
let (data, scratch) = self.take_vmp_pmat(
infos.n().into(),
infos.rows().into(),
infos.dnum().into(),
infos.rank_in().into(),
(infos.rank_out() + 1).into(),
infos.size(),
@@ -220,7 +220,7 @@ where
(
GGLWECiphertextPrepared::builder()
.base2k(infos.base2k())
.digits(infos.digits())
.dsize(infos.dsize())
.k(infos.k())
.data(data)
.build()
@@ -240,7 +240,7 @@ where
{
let (data, scratch) = self.take_mat_znx(
infos.n().into(),
infos.rows().into(),
infos.dnum().into(),
(infos.rank() + 1).into(),
(infos.rank() + 1).into(),
infos.size(),
@@ -248,7 +248,7 @@ where
(
GGSWCiphertext::builder()
.base2k(infos.base2k())
.digits(infos.digits())
.dsize(infos.dsize())
.k(infos.k())
.data(data)
.build()
@@ -268,7 +268,7 @@ where
{
let (data, scratch) = self.take_vmp_pmat(
infos.n().into(),
infos.rows().into(),
infos.dnum().into(),
(infos.rank() + 1).into(),
(infos.rank() + 1).into(),
infos.size(),
@@ -276,7 +276,7 @@ where
(
GGSWCiphertextPrepared::builder()
.base2k(infos.base2k())
.digits(infos.digits())
.dsize(infos.dsize())
.k(infos.k())
.data(data)
.build()
@@ -367,7 +367,7 @@ where
{
fn take_glwe_switching_key<A>(&mut self, infos: &A) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
let (data, scratch) = self.take_gglwe(infos);
(
@@ -387,7 +387,7 @@ where
{
fn take_gglwe_switching_key_prepared<A>(&mut self, infos: &A) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
let (data, scratch) = self.take_gglwe_prepared(infos);
(
@@ -407,7 +407,7 @@ where
{
fn take_gglwe_automorphism_key<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
let (data, scratch) = self.take_glwe_switching_key(infos);
(GGLWEAutomorphismKey { key: data, p: 0 }, scratch)
@@ -420,7 +420,7 @@ where
{
fn take_gglwe_automorphism_key_prepared<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
let (data, scratch) = self.take_gglwe_switching_key_prepared(infos);
(GGLWEAutomorphismKeyPrepared { key: data, p: 0 }, scratch)
@@ -433,7 +433,7 @@ where
{
fn take_tensor_key<A>(&mut self, infos: &A) -> (GGLWETensorKey<&mut [u8]>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
@@ -468,7 +468,7 @@ where
{
fn take_gglwe_tensor_key_prepared<A>(&mut self, infos: &A) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWELayoutInfos,
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),

View File

@@ -1,8 +1,8 @@
use poulpy_hal::test_suite::serialization::test_reader_writer_interface;
use crate::layouts::{
Base2K, Degree, Digits, GGLWEAutomorphismKey, GGLWECiphertext, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext,
GLWECiphertext, GLWEToLWESwitchingKey, LWECiphertext, LWESwitchingKey, LWEToGLWESwitchingKey, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWECiphertext, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext,
GLWECiphertext, GLWEToLWEKey, LWECiphertext, LWESwitchingKey, LWEToGLWESwitchingKey, Rank, TorusPrecision,
compressed::{
GGLWEAutomorphismKeyCompressed, GGLWECiphertextCompressed, GGLWESwitchingKeyCompressed, GGLWETensorKeyCompressed,
GGSWCiphertextCompressed, GLWECiphertextCompressed, GLWEToLWESwitchingKeyCompressed, LWECiphertextCompressed,
@@ -14,9 +14,9 @@ const N_GLWE: Degree = Degree(64);
const N_LWE: Degree = Degree(32);
const BASE2K: Base2K = Base2K(12);
const K: TorusPrecision = TorusPrecision(33);
const ROWS: Rows = Rows(3);
const DNUM: Dnum = Dnum(3);
const RANK: Rank = Rank(2);
const DIGITS: Digits = Digits(1);
const DSIZE: Dsize = Dsize(1);
#[test]
fn glwe_serialization() {
@@ -44,101 +44,101 @@ fn lwe_compressed_serialization() {
#[test]
fn test_gglwe_serialization() {
let original: GGLWECiphertext<Vec<u8>> = GGLWECiphertext::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK, RANK);
let original: GGLWECiphertext<Vec<u8>> = GGLWECiphertext::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn test_gglwe_compressed_serialization() {
let original: GGLWECiphertextCompressed<Vec<u8>> =
GGLWECiphertextCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK, RANK);
GGLWECiphertextCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn test_glwe_switching_key_serialization() {
let original: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK, RANK);
let original: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn test_glwe_switching_key_compressed_serialization() {
let original: GGLWESwitchingKeyCompressed<Vec<u8>> =
GGLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK, RANK);
GGLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn test_automorphism_key_serialization() {
let original: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK);
let original: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn test_automorphism_key_compressed_serialization() {
let original: GGLWEAutomorphismKeyCompressed<Vec<u8>> =
GGLWEAutomorphismKeyCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK);
GGLWEAutomorphismKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn test_tensor_key_serialization() {
let original: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK);
let original: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn test_tensor_key_compressed_serialization() {
let original: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK);
let original: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn glwe_to_lwe_switching_key_serialization() {
let original: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, ROWS, RANK);
let original: GLWEToLWEKey<Vec<u8>> = GLWEToLWEKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM);
test_reader_writer_interface(original);
}
#[test]
fn glwe_to_lwe_switching_key_compressed_serialization() {
let original: GLWEToLWESwitchingKeyCompressed<Vec<u8>> =
GLWEToLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS, RANK);
GLWEToLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM);
test_reader_writer_interface(original);
}
#[test]
fn lwe_to_glwe_switching_key_serialization() {
let original: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, ROWS, RANK);
let original: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM);
test_reader_writer_interface(original);
}
#[test]
fn lwe_to_glwe_switching_key_compressed_serialization() {
let original: LWEToGLWESwitchingKeyCompressed<Vec<u8>> =
LWEToGLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS, RANK);
LWEToGLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM);
test_reader_writer_interface(original);
}
#[test]
fn lwe_switching_key_serialization() {
let original: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, ROWS);
let original: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, DNUM);
test_reader_writer_interface(original);
}
#[test]
fn lwe_switching_key_compressed_serialization() {
let original: LWESwitchingKeyCompressed<Vec<u8>> = LWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS);
let original: LWESwitchingKeyCompressed<Vec<u8>> = LWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, DNUM);
test_reader_writer_interface(original);
}
#[test]
fn ggsw_serialization() {
let original: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK);
let original: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}
#[test]
fn ggsw_compressed_serialization() {
let original: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc_with(N_GLWE, BASE2K, K, ROWS, DIGITS, RANK);
let original: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE);
test_reader_writer_interface(original);
}

View File

@@ -18,7 +18,7 @@ use poulpy_hal::{
use crate::{
encryption::SIGMA,
layouts::{
GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWELayoutInfos, GLWEPlaintext, GLWESecret,
GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWEInfos, GLWEPlaintext, GLWESecret,
prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc},
},
noise::log2_std_noise_gglwe_product,
@@ -70,26 +70,26 @@ where
let base2k: usize = 12;
let k_in: usize = 60;
let k_out: usize = 40;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
let p0: i64 = -1;
let p1: i64 = -5;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
let k_apply: usize = (digits + di) * base2k;
for di in 1..dsize + 1 {
let k_apply: usize = (dsize + di) * base2k;
let n: usize = module.n();
let digits_in: usize = 1;
let dsize_in: usize = 1;
let rows_in: usize = k_in / (base2k * di);
let rows_out: usize = k_out / (base2k * di);
let rows_apply: usize = k_in.div_ceil(base2k * di);
let dnum_in: usize = k_in / (base2k * di);
let dnum_out: usize = k_out / (base2k * di);
let dnum_apply: usize = k_in.div_ceil(base2k * di);
let auto_key_in_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_in.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -97,8 +97,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows_out.into(),
digits: digits_in.into(),
dnum: dnum_out.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -106,8 +106,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_apply.into(),
rows: rows_apply.into(),
digits: di.into(),
dnum: dnum_apply.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -183,7 +183,7 @@ where
let sk_auto_dft: GLWESecretPrepared<Vec<u8>, B> = sk_auto.prepare_alloc(module, scratch.borrow());
(0..auto_key_out.rank_in().into()).for_each(|col_i| {
(0..auto_key_out.rows().into()).for_each(|row_i| {
(0..auto_key_out.dnum().into()).for_each(|row_i| {
auto_key_out
.at(row_i, col_i)
.decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow());
@@ -191,7 +191,7 @@ where
module.vec_znx_sub_scalar_inplace(
&mut pt.data,
0,
(digits_in - 1) + row_i * digits_in,
(dsize_in - 1) + row_i * dsize_in,
&sk.data,
col_i,
);
@@ -280,25 +280,25 @@ where
{
let base2k: usize = 12;
let k_in: usize = 60;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
let p0: i64 = -1;
let p1: i64 = -5;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
let k_apply: usize = (digits + di) * base2k;
for di in 1..dsize + 1 {
let k_apply: usize = (dsize + di) * base2k;
let n: usize = module.n();
let digits_in: usize = 1;
let dsize_in: usize = 1;
let rows_in: usize = k_in / (base2k * di);
let rows_apply: usize = k_in.div_ceil(base2k * di);
let dnum_in: usize = k_in / (base2k * di);
let dnum_apply: usize = k_in.div_ceil(base2k * di);
let auto_key_layout: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_in.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -306,8 +306,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_apply.into(),
rows: rows_apply.into(),
digits: di.into(),
dnum: dnum_apply.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -373,14 +373,14 @@ where
let sk_auto_dft: GLWESecretPrepared<Vec<u8>, B> = sk_auto.prepare_alloc(module, scratch.borrow());
(0..auto_key.rank_in().into()).for_each(|col_i| {
(0..auto_key.rows().into()).for_each(|row_i| {
(0..auto_key.dnum().into()).for_each(|row_i| {
auto_key
.at(row_i, col_i)
.decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow());
module.vec_znx_sub_scalar_inplace(
&mut pt.data,
0,
(digits_in - 1) + row_i * digits_in,
(dsize_in - 1) + row_i * dsize_in,
&sk.data,
col_i,
);

View File

@@ -77,27 +77,27 @@ where
{
let base2k: usize = 12;
let k_in: usize = 54;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
let p: i64 = -5;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ksk: usize = k_in + base2k * di;
let k_tsk: usize = k_ksk;
let k_out: usize = k_ksk; // Better capture noise.
let n: usize = module.n();
let rows: usize = k_in.div_ceil(base2k * di);
let rows_in: usize = k_in.div_euclid(base2k * di);
let dnum: usize = k_in.div_ceil(base2k * di);
let dnum_in: usize = k_in.div_euclid(base2k * di);
let digits_in: usize = 1;
let dsize_in: usize = 1;
let ggsw_in_layout: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_in.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -105,8 +105,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -114,8 +114,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_tsk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -123,8 +123,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -270,24 +270,24 @@ where
{
let base2k: usize = 12;
let k_out: usize = 54;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
let p: i64 = -1;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ksk: usize = k_out + base2k * di;
let k_tsk: usize = k_ksk;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(di * base2k);
let rows_in: usize = k_out.div_euclid(base2k * di);
let digits_in: usize = 1;
let dnum: usize = k_out.div_ceil(di * base2k);
let dnum_in: usize = k_out.div_euclid(base2k * di);
let dsize_in: usize = 1;
let ggsw_out_layout: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -295,8 +295,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_tsk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -304,8 +304,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};

View File

@@ -67,15 +67,15 @@ where
{
let base2k: usize = 12;
let k_in: usize = 60;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
let p: i64 = -5;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ksk: usize = k_in + base2k * di;
let k_out: usize = k_ksk; // Better capture noise.
let n: usize = module.n();
let rows: usize = k_in.div_ceil(base2k * digits);
let dnum: usize = k_in.div_ceil(base2k * dsize);
let ct_in_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -96,8 +96,8 @@ where
base2k: base2k.into(),
k: k_out.into(),
rank: rank.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
};
let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&autokey_infos);
@@ -148,7 +148,7 @@ where
let max_noise: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
base2k * digits,
base2k * dsize,
0.5,
0.5,
0f64,
@@ -210,14 +210,14 @@ where
{
let base2k: usize = 12;
let k_out: usize = 60;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
let p = -5;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ksk: usize = k_out + base2k * di;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(base2k * digits);
let dnum: usize = k_out.div_ceil(base2k * dsize);
let ct_out_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -231,8 +231,8 @@ where
base2k: base2k.into(),
k: k_ksk.into(),
rank: rank.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
};
let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&autokey_infos);
@@ -282,7 +282,7 @@ where
let max_noise: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
base2k * digits,
base2k * dsize,
0.5,
0.5,
0f64,

View File

@@ -16,9 +16,9 @@ use poulpy_hal::{
};
use crate::layouts::{
Base2K, Degree, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, GLWEToLWESwitchingKey,
GLWEToLWESwitchingKeyLayout, LWECiphertext, LWECiphertextLayout, LWEPlaintext, LWESecret, LWEToGLWESwitchingKey,
LWEToGLWESwitchingKeyLayout, Rank, Rows, TorusPrecision,
Base2K, Degree, Dnum, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, GLWEToLWEKey, GLWEToLWEKeyLayout,
LWECiphertext, LWECiphertextLayout, LWEPlaintext, LWESecret, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyLayout, Rank,
TorusPrecision,
prepared::{GLWESecretPrepared, GLWEToLWESwitchingKeyPrepared, LWEToGLWESwitchingKeyPrepared, PrepareAlloc},
};
@@ -79,7 +79,7 @@ where
n: n_glwe,
base2k: Base2K(17),
k: TorusPrecision(51),
rows: Rows(2),
dnum: Dnum(2),
rank_out: rank,
};
@@ -188,11 +188,11 @@ where
let rank: Rank = Rank(2);
let k_lwe_pt: TorusPrecision = TorusPrecision(8);
let glwe_to_lwe_infos: GLWEToLWESwitchingKeyLayout = GLWEToLWESwitchingKeyLayout {
let glwe_to_lwe_infos: GLWEToLWEKeyLayout = GLWEToLWEKeyLayout {
n: n_glwe,
base2k: Base2K(17),
k: TorusPrecision(51),
rows: Rows(2),
dnum: Dnum(2),
rank_in: rank,
};
@@ -214,7 +214,7 @@ where
let mut source_xe: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
GLWEToLWESwitchingKey::encrypt_sk_scratch_space(module, &glwe_to_lwe_infos)
GLWEToLWEKey::encrypt_sk_scratch_space(module, &glwe_to_lwe_infos)
| LWECiphertext::from_glwe_scratch_space(module, &lwe_infos, &glwe_infos, &glwe_to_lwe_infos)
| GLWECiphertext::decrypt_scratch_space(module, &glwe_infos),
);
@@ -241,7 +241,7 @@ where
scratch.borrow(),
);
let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(&glwe_to_lwe_infos);
let mut ksk: GLWEToLWEKey<Vec<u8>> = GLWEToLWEKey::alloc(&glwe_to_lwe_infos);
ksk.encrypt_sk(
module,

View File

@@ -69,18 +69,18 @@ where
{
let base2k: usize = 12;
let k_ksk: usize = 60;
let digits: usize = k_ksk.div_ceil(base2k) - 1;
let dsize: usize = k_ksk.div_ceil(base2k) - 1;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let n: usize = module.n();
let rows: usize = (k_ksk - di * base2k) / (di * base2k);
let dnum: usize = (k_ksk - di * base2k) / (di * base2k);
let atk_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -172,18 +172,18 @@ where
{
let base2k: usize = 12;
let k_ksk: usize = 60;
let digits: usize = k_ksk.div_ceil(base2k) - 1;
let dsize: usize = k_ksk.div_ceil(base2k) - 1;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let n: usize = module.n();
let rows: usize = (k_ksk - di * base2k) / (di * base2k);
let dnum: usize = (k_ksk - di * base2k) / (di * base2k);
let atk_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};

View File

@@ -64,19 +64,19 @@ where
{
let base2k: usize = 12;
let k_ksk: usize = 54;
let digits: usize = k_ksk / base2k;
let dsize: usize = k_ksk / base2k;
for rank_in in 1_usize..3 {
for rank_out in 1_usize..3 {
for di in 1_usize..digits + 1 {
for di in 1_usize..dsize + 1 {
let n: usize = module.n();
let rows: usize = (k_ksk - di * base2k) / (di * base2k);
let dnum: usize = (k_ksk - di * base2k) / (di * base2k);
let gglwe_infos: GGLWECiphertextLayout = GGLWECiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank_in: rank_in.into(),
rank_out: rank_out.into(),
};
@@ -156,19 +156,19 @@ where
{
let base2k: usize = 12;
let k_ksk: usize = 54;
let digits: usize = k_ksk / base2k;
let dsize: usize = k_ksk / base2k;
for rank_in in 1_usize..3 {
for rank_out in 1_usize..3 {
for di in 1_usize..digits + 1 {
for di in 1_usize..dsize + 1 {
let n: usize = module.n();
let rows: usize = (k_ksk - di * base2k) / (di * base2k);
let dnum: usize = (k_ksk - di * base2k) / (di * base2k);
let gglwe_infos: GGLWECiphertextLayout = GGLWECiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank_in: rank_in.into(),
rank_out: rank_out.into(),
};

View File

@@ -67,18 +67,18 @@ where
{
let base2k: usize = 12;
let k: usize = 54;
let digits: usize = k / base2k;
let dsize: usize = k / base2k;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let n: usize = module.n();
let rows: usize = (k - di * base2k) / (di * base2k);
let dnum: usize = (k - di * base2k) / (di * base2k);
let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -160,18 +160,18 @@ where
{
let base2k: usize = 12;
let k: usize = 54;
let digits: usize = k / base2k;
let dsize: usize = k / base2k;
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let n: usize = module.n();
let rows: usize = (k - di * base2k) / (di * base2k);
let dnum: usize = (k - di * base2k) / (di * base2k);
let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};

View File

@@ -17,7 +17,7 @@ use poulpy_hal::{
use crate::{
encryption::SIGMA,
layouts::{
Digits, GGLWETensorKey, GGLWETensorKeyLayout, GLWEPlaintext, GLWESecret,
Dsize, GGLWETensorKey, GGLWETensorKeyLayout, GLWEPlaintext, GLWESecret,
compressed::{Decompress, GGLWETensorKeyCompressed},
prepared::{GLWESecretPrepared, PrepareAlloc},
},
@@ -69,14 +69,14 @@ where
for rank in 1_usize..3 {
let n: usize = module.n();
let rows: usize = k / base2k;
let dnum: usize = k / base2k;
let tensor_key_infos = GGLWETensorKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k.into(),
rows: rows.into(),
digits: Digits(1),
dnum: dnum.into(),
dsize: Dsize(1),
rank: rank.into(),
};
@@ -127,7 +127,7 @@ where
0,
scratch.borrow(),
);
for row_i in 0..rows {
for row_i in 0..dnum {
tensor_key
.at(i, j)
.at(row_i, 0)
@@ -188,14 +188,14 @@ where
let k = 54;
for rank in 1_usize..3 {
let n: usize = module.n();
let rows: usize = k / base2k;
let dnum: usize = k / base2k;
let tensor_key_infos: GGLWETensorKeyLayout = GGLWETensorKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k.into(),
rows: rows.into(),
digits: Digits(1),
dnum: dnum.into(),
dsize: Dsize(1),
rank: rank.into(),
};
@@ -244,7 +244,7 @@ where
0,
scratch.borrow(),
);
for row_i in 0..rows {
for row_i in 0..dnum {
tensor_key
.at(i, j)
.at(row_i, 0)

View File

@@ -70,23 +70,23 @@ where
{
let base2k: usize = 12;
let k_in: usize = 60;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
for rank_in in 1_usize..3 {
for rank_out in 1_usize..3 {
for di in 1_usize..digits + 1 {
for di in 1_usize..dsize + 1 {
let k_ggsw: usize = k_in + base2k * di;
let k_out: usize = k_in; // Better capture noise.
let n: usize = module.n();
let rows: usize = k_in.div_ceil(base2k * di);
let digits_in: usize = 1;
let dnum: usize = k_in.div_ceil(base2k * di);
let dsize_in: usize = 1;
let gglwe_in_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_in.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank_in: rank_in.into(),
rank_out: rank_out.into(),
};
@@ -95,8 +95,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank_in: rank_in.into(),
rank_out: rank_out.into(),
};
@@ -105,8 +105,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ggsw.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank_out.into(),
};
@@ -252,23 +252,23 @@ where
{
let base2k: usize = 12;
let k_out: usize = 60;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
for rank_in in 1_usize..3 {
for rank_out in 1_usize..3 {
for di in 1_usize..digits + 1 {
for di in 1_usize..dsize + 1 {
let k_ggsw: usize = k_out + base2k * di;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(base2k * di);
let dnum: usize = k_out.div_ceil(base2k * di);
let digits_in: usize = 1;
let dsize_in: usize = 1;
let gglwe_out_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank_in: rank_in.into(),
rank_out: rank_out.into(),
};
@@ -277,8 +277,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ggsw.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank_out.into(),
};

View File

@@ -72,24 +72,24 @@ where
{
let base2k: usize = 12;
let k_in: usize = 60;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_apply: usize = k_in + base2k * di;
let k_out: usize = k_in; // Better capture noise.
let n: usize = module.n();
let rows: usize = k_in.div_ceil(base2k * di);
let rows_in: usize = k_in.div_euclid(base2k * di);
let digits_in: usize = 1;
let dnum: usize = k_in.div_ceil(base2k * di);
let dnum_in: usize = k_in.div_euclid(base2k * di);
let dsize_in: usize = 1;
let ggsw_in_infos: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_in.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -97,8 +97,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -106,8 +106,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_apply.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -237,22 +237,22 @@ where
{
let base2k: usize = 12;
let k_out: usize = 60;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_apply: usize = k_out + base2k * di;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(di * base2k);
let rows_in: usize = k_out.div_euclid(base2k * di);
let digits_in: usize = 1;
let dnum: usize = k_out.div_ceil(di * base2k);
let dnum_in: usize = k_out.div_euclid(base2k * di);
let dsize_in: usize = 1;
let ggsw_out_infos: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows_in.into(),
digits: digits_in.into(),
dnum: dnum_in.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -260,8 +260,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_apply.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};

View File

@@ -64,14 +64,14 @@ where
{
let base2k: usize = 12;
let k_in: usize = 45;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ggsw: usize = k_in + base2k * di;
let k_out: usize = k_ggsw; // Better capture noise
let n: usize = module.n();
let rows: usize = k_in.div_ceil(base2k * digits);
let dnum: usize = k_in.div_ceil(base2k * dsize);
let glwe_in_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -91,8 +91,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ggsw.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -158,7 +158,7 @@ where
let max_noise: f64 = noise_ggsw_product(
n as f64,
base2k * digits,
base2k * dsize,
0.5,
var_msg,
var_a0_err,
@@ -216,13 +216,13 @@ where
{
let base2k: usize = 12;
let k_out: usize = 60;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ggsw: usize = k_out + base2k * di;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(base2k * digits);
let dnum: usize = k_out.div_ceil(base2k * dsize);
let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -235,8 +235,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ggsw.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -301,7 +301,7 @@ where
let max_noise: f64 = noise_ggsw_product(
n as f64,
base2k * digits,
base2k * dsize,
0.5,
var_msg,
var_a0_err,

View File

@@ -66,26 +66,26 @@ where
{
let base2k: usize = 12;
let k_in: usize = 60;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
for rank_in_s0s1 in 1_usize..3 {
for rank_out_s0s1 in 1_usize..3 {
for rank_out_s1s2 in 1_usize..3 {
for di in 1_usize..digits + 1 {
for di in 1_usize..dsize + 1 {
let k_ksk: usize = k_in + base2k * di;
let k_out: usize = k_ksk; // Better capture noise.
let n: usize = module.n();
let rows: usize = k_in / base2k;
let rows_apply: usize = k_in.div_ceil(base2k * di);
let digits_in: usize = 1;
let dnum: usize = k_in / base2k;
let dnum_apply: usize = k_in.div_ceil(base2k * di);
let dsize_in: usize = 1;
let gglwe_s0s1_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_in.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank_in: rank_in_s0s1.into(),
rank_out: rank_out_s0s1.into(),
};
@@ -94,8 +94,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows_apply.into(),
digits: di.into(),
dnum: dnum_apply.into(),
dsize: di.into(),
rank_in: rank_out_s0s1.into(),
rank_out: rank_out_s1s2.into(),
};
@@ -104,8 +104,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows_apply.into(),
digits: digits_in.into(),
dnum: dnum_apply.into(),
dsize: dsize_in.into(),
rank_in: rank_in_s0s1.into(),
rank_out: rank_out_s1s2.into(),
};
@@ -236,22 +236,22 @@ where
{
let base2k: usize = 12;
let k_out: usize = 60;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
for rank_in in 1_usize..3 {
for rank_out in 1_usize..3 {
for di in 1_usize..digits + 1 {
for di in 1_usize..dsize + 1 {
let k_ksk: usize = k_out + base2k * di;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(base2k * di);
let digits_in: usize = 1;
let dnum: usize = k_out.div_ceil(base2k * di);
let dsize_in: usize = 1;
let gglwe_s0s1_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout {
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank_in: rank_in.into(),
rank_out: rank_out.into(),
};
@@ -260,8 +260,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank_in: rank_out.into(),
rank_out: rank_out.into(),
};

View File

@@ -73,24 +73,24 @@ where
{
let base2k: usize = 12;
let k_in: usize = 54;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ksk: usize = k_in + base2k * di;
let k_tsk: usize = k_ksk;
let k_out: usize = k_ksk; // Better capture noise.
let n: usize = module.n();
let rows: usize = k_in.div_ceil(di * base2k);
let dnum: usize = k_in.div_ceil(di * base2k);
let digits_in: usize = 1;
let dsize_in: usize = 1;
let ggsw_in_infos: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_in.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -98,8 +98,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -107,8 +107,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_tsk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -116,8 +116,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank_in: rank.into(),
rank_out: rank.into(),
};
@@ -262,23 +262,23 @@ where
{
let base2k: usize = 12;
let k_out: usize = 54;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ksk: usize = k_out + base2k * di;
let k_tsk: usize = k_ksk;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(di * base2k);
let dnum: usize = k_out.div_ceil(di * base2k);
let digits_in: usize = 1;
let dsize_in: usize = 1;
let ggsw_out_infos: GGSWCiphertextLayout = GGSWCiphertextLayout {
n: n.into(),
base2k: base2k.into(),
k: k_out.into(),
rows: rows.into(),
digits: digits_in.into(),
dnum: dnum.into(),
dsize: dsize_in.into(),
rank: rank.into(),
};
@@ -286,8 +286,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_tsk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank: rank.into(),
};
@@ -295,8 +295,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank_in: rank.into(),
rank_out: rank.into(),
};

View File

@@ -66,16 +66,16 @@ where
{
let base2k: usize = 12;
let k_in: usize = 45;
let digits: usize = k_in.div_ceil(base2k);
let dsize: usize = k_in.div_ceil(base2k);
for rank_in in 1_usize..3 {
for rank_out in 1_usize..3 {
for di in 1_usize..digits + 1 {
for di in 1_usize..dsize + 1 {
let k_ksk: usize = k_in + base2k * di;
let k_out: usize = k_ksk; // better capture noise
let n: usize = module.n();
let rows: usize = k_in.div_ceil(base2k * digits);
let dnum: usize = k_in.div_ceil(base2k * dsize);
let glwe_in_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -95,8 +95,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank_in: rank_in.into(),
rank_out: rank_out.into(),
};
@@ -150,7 +150,7 @@ where
let max_noise: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
base2k * digits,
base2k * dsize,
0.5,
0.5,
0f64,
@@ -208,14 +208,14 @@ where
{
let base2k: usize = 12;
let k_out: usize = 45;
let digits: usize = k_out.div_ceil(base2k);
let dsize: usize = k_out.div_ceil(base2k);
for rank in 1_usize..3 {
for di in 1..digits + 1 {
for di in 1..dsize + 1 {
let k_ksk: usize = k_out + base2k * di;
let n: usize = module.n();
let rows: usize = k_out.div_ceil(base2k * digits);
let dnum: usize = k_out.div_ceil(base2k * dsize);
let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -228,8 +228,8 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
digits: di.into(),
dnum: dnum.into(),
dsize: di.into(),
rank_in: rank.into(),
rank_out: rank.into(),
};
@@ -282,7 +282,7 @@ where
let max_noise: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
base2k * digits,
base2k * dsize,
0.5,
0.5,
0f64,

View File

@@ -73,7 +73,7 @@ where
let k_lwe_pt: usize = 8;
let k_ksk: usize = k_lwe_ct + base2k;
let rows: usize = k_lwe_ct.div_ceil(base2k);
let dnum: usize = k_lwe_ct.div_ceil(base2k);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]);
@@ -83,7 +83,7 @@ where
n: n.into(),
base2k: base2k.into(),
k: k_ksk.into(),
rows: rows.into(),
dnum: dnum.into(),
};
let lwe_in_infos: LWECiphertextLayout = LWECiphertextLayout {

View File

@@ -83,10 +83,10 @@ where
let k_ct: usize = 36;
let pt_k: usize = 18;
let rank: usize = 3;
let digits: usize = 1;
let k_ksk: usize = k_ct + base2k * digits;
let dsize: usize = 1;
let k_ksk: usize = k_ct + base2k * dsize;
let rows: usize = k_ct.div_ceil(base2k * digits);
let dnum: usize = k_ct.div_ceil(base2k * dsize);
let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -100,8 +100,8 @@ where
base2k: base2k.into(),
k: k_ksk.into(),
rank: rank.into(),
digits: digits.into(),
rows: rows.into(),
dsize: dsize.into(),
dnum: dnum.into(),
};
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(

View File

@@ -80,8 +80,8 @@ where
let n: usize = module.n();
let k_autokey: usize = k + base2k;
let digits: usize = 1;
let rows: usize = k.div_ceil(base2k * digits);
let dsize: usize = 1;
let dnum: usize = k.div_ceil(base2k * dsize);
let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout {
n: n.into(),
@@ -95,8 +95,8 @@ where
base2k: base2k.into(),
k: k_autokey.into(),
rank: rank.into(),
digits: digits.into(),
rows: rows.into(),
dsize: dsize.into(),
dnum: dnum.into(),
};
let mut glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos);