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

17
Cargo.lock generated
View File

@@ -408,6 +408,7 @@ dependencies = [
"poulpy-backend",
"poulpy-core",
"poulpy-hal",
"rand",
]
[[package]]
@@ -421,18 +422,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
@@ -445,9 +446,9 @@ checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
name = "rand"
version = "0.9.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha",
"rand_core",
@@ -598,9 +599,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "2.0.96"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -1124,6 +1124,7 @@ mod tests {
}
}
#[allow(dead_code)]
#[target_feature(enable = "avx2")]
fn znx_extract_digit_addmul_internal() {
let mut y0: [i64; 4] = [
@@ -1168,6 +1169,7 @@ mod tests {
}
}
#[allow(dead_code)]
#[target_feature(enable = "avx2")]
fn znx_normalize_digit_internal() {
let mut y0: [i64; 4] = [

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);

View File

@@ -2,8 +2,8 @@ use crate::reference::znx::{
ZnxAdd, ZnxAddInplace, ZnxAutomorphism, ZnxCopy, ZnxExtractDigitAddMul, ZnxMulAddPowerOfTwo, ZnxMulPowerOfTwo,
ZnxMulPowerOfTwoInplace, ZnxNegate, ZnxNegateInplace, ZnxNormalizeDigit, ZnxNormalizeFinalStep, ZnxNormalizeFinalStepInplace,
ZnxNormalizeFirstStep, ZnxNormalizeFirstStepCarryOnly, ZnxNormalizeFirstStepInplace, ZnxNormalizeMiddleStep,
ZnxNormalizeMiddleStepCarryOnly, ZnxNormalizeMiddleStepInplace, ZnxSub, ZnxSubInplace, ZnxSubNegateInplace, ZnxSwitchRing,
ZnxZero,
ZnxNormalizeMiddleStepCarryOnly, ZnxNormalizeMiddleStepInplace, ZnxRotate, ZnxSub, ZnxSubInplace, ZnxSubNegateInplace,
ZnxSwitchRing, ZnxZero,
add::{znx_add_inplace_ref, znx_add_ref},
automorphism::znx_automorphism_ref,
copy::znx_copy_ref,
@@ -17,7 +17,7 @@ use crate::reference::znx::{
switch_ring::znx_switch_ring_ref,
zero::znx_zero_ref,
znx_extract_digit_addmul_ref, znx_mul_add_power_of_two_ref, znx_mul_power_of_two_inplace_ref, znx_mul_power_of_two_ref,
znx_normalize_digit_ref,
znx_normalize_digit_ref, znx_rotate,
};
pub struct ZnxRef {}
@@ -29,6 +29,13 @@ impl ZnxAdd for ZnxRef {
}
}
impl ZnxRotate for ZnxRef {
#[inline(always)]
fn znx_rotate(p: i64, res: &mut [i64], src: &[i64]) {
znx_rotate::<Self>(p, res, src);
}
}
impl ZnxAddInplace for ZnxRef {
#[inline(always)]
fn znx_add_inplace(res: &mut [i64], a: &[i64]) {

View File

@@ -16,6 +16,8 @@ poulpy-core = {path="../poulpy-core"}
criterion = {workspace = true}
itertools = "0.14.0"
byteorder = "1.5.0"
rand = "0.9.2"
[[bench]]
name = "circuit_bootstrapping"

View File

@@ -3,7 +3,7 @@ use std::hint::black_box;
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use poulpy_backend::{FFT64Avx, FFT64Ref, FFT64Spqlios};
use poulpy_core::layouts::{
Digits, GGLWEAutomorphismKeyLayout, GGLWETensorKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, LWECiphertext,
Dsize, GGLWEAutomorphismKeyLayout, GGLWETensorKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, LWECiphertext,
LWECiphertextLayout, LWESecret, prepared::PrepareAlloc,
};
use poulpy_hal::{
@@ -20,8 +20,8 @@ use poulpy_hal::{
},
layouts::{Backend, Module, ScratchOwned},
oep::{
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeMatZnxImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl,
ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeMatZnxImpl, TakeScalarZnxImpl, TakeSliceImpl,
TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl,
},
source::Source,
};
@@ -98,7 +98,8 @@ where
+ TakeVecZnxBigImpl<B>
+ TakeVecZnxDftSliceImpl<B>
+ TakeMatZnxImpl<B>
+ TakeVecZnxSliceImpl<B>,
+ TakeVecZnxSliceImpl<B>
+ TakeSliceImpl<B>,
BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>,
BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlincRotationExecute<B>,
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>,
@@ -178,7 +179,8 @@ where
+ TakeVecZnxBigImpl<B>
+ TakeVecZnxDftSliceImpl<B>
+ TakeMatZnxImpl<B>
+ TakeVecZnxSliceImpl<B>,
+ TakeVecZnxSliceImpl<B>
+ TakeSliceImpl<B>,
BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>,
BlindRotationKeyPrepared<Vec<u8>, BRA, B>: BlincRotationExecute<B>,
BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>,
@@ -246,8 +248,8 @@ where
n: 1024_u32.into(),
base2k: 13_u32.into(),
k: 26_u32.into(),
rows: 2_u32.into(),
digits: 1_u32.into(),
dnum: 2_u32.into(),
dsize: 1_u32.into(),
rank: 2_u32.into(),
},
cbt_infos: CircuitBootstrappingKeyLayout {
@@ -256,23 +258,23 @@ where
n_lwe: 574_u32.into(),
base2k: 13_u32.into(),
k: 52_u32.into(),
rows: 3_u32.into(),
dnum: 3_u32.into(),
rank: 2_u32.into(),
},
layout_atk: GGLWEAutomorphismKeyLayout {
n: 1024_u32.into(),
base2k: 13_u32.into(),
k: 52_u32.into(),
rows: 3_u32.into(),
digits: Digits(1),
dnum: 3_u32.into(),
dsize: Dsize(1),
rank: 2_u32.into(),
},
layout_tsk: GGLWETensorKeyLayout {
n: 1024_u32.into(),
base2k: 13_u32.into(),
k: 52_u32.into(),
rows: 3_u32.into(),
digits: Digits(1),
dnum: 3_u32.into(),
dsize: Dsize(1),
rank: 2_u32.into(),
},
},

View File

@@ -56,25 +56,25 @@ fn main() {
// LWE block binary key block size
let block_size: usize = 7;
// GGSW output number of rows
// GGSW output number of dnum
let rows_ggsw_res: usize = 2;
// GGSW output modulus
let k_ggsw_res: usize = (rows_ggsw_res + 1) * base2k;
// Blind rotation key GGSW number of rows
// Blind rotation key GGSW number of dnum
let rows_brk: usize = rows_ggsw_res + 1;
// Blind rotation key GGSW modulus
let k_brk: usize = (rows_brk + 1) * base2k;
// GGLWE automorphism keys number of rows
// GGLWE automorphism keys number of dnum
let rows_trace: usize = rows_ggsw_res + 1;
// GGLWE automorphism keys modulus
let k_trace: usize = (rows_trace + 1) * base2k;
// GGLWE tensor key number of rows
// GGLWE tensor key number of dnum
let rows_tsk: usize = rows_ggsw_res + 1;
// GGLWE tensor key modulus
@@ -86,23 +86,23 @@ fn main() {
n_lwe: n_lwe.into(),
base2k: base2k.into(),
k: k_brk.into(),
rows: rows_brk.into(),
dnum: rows_brk.into(),
rank: rank.into(),
},
layout_atk: GGLWEAutomorphismKeyLayout {
n: n_glwe.into(),
base2k: base2k.into(),
k: k_trace.into(),
rows: rows_trace.into(),
digits: 1_u32.into(),
dnum: rows_trace.into(),
dsize: 1_u32.into(),
rank: rank.into(),
},
layout_tsk: GGLWETensorKeyLayout {
n: n_glwe.into(),
base2k: base2k.into(),
k: k_tsk.into(),
rows: rows_tsk.into(),
digits: 1_u32.into(),
dnum: rows_tsk.into(),
dsize: 1_u32.into(),
rank: rank.into(),
},
};
@@ -111,8 +111,8 @@ fn main() {
n: n_glwe.into(),
base2k: base2k.into(),
k: k_ggsw_res.into(),
rows: rows_ggsw_res.into(),
digits: 1_u32.into(),
dnum: rows_ggsw_res.into(),
dsize: 1_u32.into(),
rank: rank.into(),
};

View File

@@ -0,0 +1,220 @@
use itertools::Itertools;
use poulpy_core::layouts::prepared::GGSWCiphertextPreparedToRef;
use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch};
use crate::tfhe::bdd_arithmetic::{
BitCircuitInfo, Circuit, CircuitExecute, FheUintBlocks, FheUintBlocksPrep, UnsignedInteger, circuits,
};
/// Operations Z x Z -> Z
pub(crate) struct Circuits2WTo1W<C: BitCircuitInfo + 'static, const WORD_SIZE: usize>(pub &'static Circuit<C, WORD_SIZE>);
pub trait EvalBDD2WTo1W<BE: Backend, T: UnsignedInteger> {
fn eval_bdd_2w_to_1w<R, A, B>(
&self,
module: &Module<BE>,
out: &mut FheUintBlocks<R, T>,
a: &FheUintBlocksPrep<A, BE, T>,
b: &FheUintBlocksPrep<B, BE, T>,
scratch: &mut Scratch<BE>,
) where
R: DataMut,
A: DataRef,
B: DataRef;
}
impl<C: BitCircuitInfo + 'static, const WORD_SIZE: usize, BE: Backend, T: UnsignedInteger> EvalBDD2WTo1W<BE, T>
for Circuits2WTo1W<C, WORD_SIZE>
where
Circuit<C, WORD_SIZE>: CircuitExecute<BE, T>,
{
fn eval_bdd_2w_to_1w<R, A, B>(
&self,
module: &Module<BE>,
out: &mut FheUintBlocks<R, T>,
a: &FheUintBlocksPrep<A, BE, T>,
b: &FheUintBlocksPrep<B, BE, T>,
scratch: &mut Scratch<BE>,
) where
R: DataMut,
A: DataRef,
B: DataRef,
{
eval_bdd_2w_to_1w(module, self.0, out, a, b, scratch);
}
}
pub fn eval_bdd_2w_to_1w<R: DataMut, A: DataRef, B: DataRef, T: UnsignedInteger, C: CircuitExecute<BE, T>, BE: Backend>(
module: &Module<BE>,
circuit: &C,
out: &mut FheUintBlocks<R, T>,
a: &FheUintBlocksPrep<A, BE, T>,
b: &FheUintBlocksPrep<B, BE, T>,
scratch: &mut Scratch<BE>,
) {
#[cfg(debug_assertions)]
{
assert_eq!(out.blocks.len(), T::WORD_SIZE);
assert_eq!(b.blocks.len(), T::WORD_SIZE);
assert_eq!(b.blocks.len(), T::WORD_SIZE);
}
// Collects inputs into a single array
let inputs: Vec<&dyn GGSWCiphertextPreparedToRef<BE>> = a
.blocks
.iter()
.map(|x| x as &dyn GGSWCiphertextPreparedToRef<BE>)
.chain(
b.blocks
.iter()
.map(|x| x as &dyn GGSWCiphertextPreparedToRef<BE>),
)
.collect_vec();
// Evaluates out[i] = circuit[i](a, b)
circuit.execute(module, &mut out.blocks, &inputs, scratch);
}
#[macro_export]
macro_rules! define_bdd_2w_to_1w_trait {
($(#[$meta:meta])* $vis:vis $trait_name:ident, $method_name:ident) => {
$(#[$meta])*
$vis trait $trait_name<T: UnsignedInteger, BE: Backend> {
fn $method_name<A, B>(
&mut self,
module: &Module<BE>,
a: &FheUintBlocksPrep<A, BE, T>,
b: &FheUintBlocksPrep<B, BE, T>,
scratch: &mut Scratch<BE>,
) where
A: DataRef,
B: DataRef;
}
};
}
#[macro_export]
macro_rules! impl_bdd_2w_to_1w_trait {
($trait_name:ident, $method_name:ident, $ty:ty, $n:literal, $circuit_ty:ty, $output_circuits:path) => {
impl<D: DataMut, BE: Backend> $trait_name<$ty, BE> for FheUintBlocks<D, $ty>
where
Circuits2WTo1W<$circuit_ty, $n>: EvalBDD2WTo1W<BE, $ty>,
{
fn $method_name<A, B>(
&mut self,
module: &Module<BE>,
a: &FheUintBlocksPrep<A, BE, $ty>,
b: &FheUintBlocksPrep<B, BE, $ty>,
scratch: &mut Scratch<BE>,
) where
A: DataRef,
B: DataRef,
{
const OP: Circuits2WTo1W<$circuit_ty, $n> = Circuits2WTo1W::<$circuit_ty, $n>(&$output_circuits);
OP.eval_bdd_2w_to_1w(module, self, a, b, scratch);
}
}
};
}
define_bdd_2w_to_1w_trait!(pub Add, add);
define_bdd_2w_to_1w_trait!(pub Sub, sub);
define_bdd_2w_to_1w_trait!(pub Sll, sll);
define_bdd_2w_to_1w_trait!(pub Sra, sra);
define_bdd_2w_to_1w_trait!(pub Srl, srl);
define_bdd_2w_to_1w_trait!(pub Slt, slt);
define_bdd_2w_to_1w_trait!(pub Sltu, sltu);
define_bdd_2w_to_1w_trait!(pub Or, or);
define_bdd_2w_to_1w_trait!(pub And, and);
define_bdd_2w_to_1w_trait!(pub Xor, xor);
impl_bdd_2w_to_1w_trait!(
Add,
add,
u32,
32,
circuits::u32::add_codegen::AnyBitCircuit,
circuits::u32::add_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Sub,
sub,
u32,
32,
circuits::u32::sub_codegen::AnyBitCircuit,
circuits::u32::sub_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Sll,
sll,
u32,
32,
circuits::u32::sll_codegen::AnyBitCircuit,
circuits::u32::sll_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Sra,
sra,
u32,
32,
circuits::u32::sra_codegen::AnyBitCircuit,
circuits::u32::sra_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Srl,
srl,
u32,
32,
circuits::u32::srl_codegen::AnyBitCircuit,
circuits::u32::srl_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Slt,
slt,
u32,
1,
circuits::u32::slt_codegen::AnyBitCircuit,
circuits::u32::slt_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Sltu,
sltu,
u32,
1,
circuits::u32::sltu_codegen::AnyBitCircuit,
circuits::u32::sltu_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
And,
and,
u32,
32,
circuits::u32::and_codegen::AnyBitCircuit,
circuits::u32::and_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Or,
or,
u32,
1,
circuits::u32::or_codegen::AnyBitCircuit,
circuits::u32::or_codegen::OUTPUT_CIRCUITS
);
impl_bdd_2w_to_1w_trait!(
Xor,
xor,
u32,
1,
circuits::u32::xor_codegen::AnyBitCircuit,
circuits::u32::xor_codegen::OUTPUT_CIRCUITS
);

View File

@@ -0,0 +1,215 @@
use std::marker::PhantomData;
use poulpy_core::layouts::{Base2K, GLWECiphertext, GLWEInfos, GLWEPlaintextLayout, LWEInfos, Rank, TorusPrecision};
use poulpy_core::{TakeGLWEPt, layouts::prepared::GLWESecretPrepared};
use poulpy_hal::api::VecZnxBigAllocBytes;
#[cfg(test)]
use poulpy_hal::api::{
ScratchAvailable, TakeVecZnx, VecZnxAddInplace, VecZnxAddNormal, VecZnxFillUniform, VecZnxNormalize, VecZnxSub,
};
#[cfg(test)]
use poulpy_hal::source::Source;
use poulpy_hal::{
api::{
TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftAllocBytes,
VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes,
},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
};
use poulpy_hal::api::{SvpApplyDftToDftInplace, VecZnxNormalizeInplace, VecZnxSubInplace};
use crate::tfhe::bdd_arithmetic::{FromBits, ToBits, UnsignedInteger};
/// An FHE ciphertext encrypting the bits of an [UnsignedInteger].
pub struct FheUintBlocks<D: Data, T: UnsignedInteger> {
pub(crate) blocks: Vec<GLWECiphertext<D>>,
pub(crate) _base: u8,
pub(crate) _phantom: PhantomData<T>,
}
impl<D: DataRef, T: UnsignedInteger> LWEInfos for FheUintBlocks<D, T> {
fn base2k(&self) -> poulpy_core::layouts::Base2K {
self.blocks[0].base2k()
}
fn k(&self) -> poulpy_core::layouts::TorusPrecision {
self.blocks[0].k()
}
fn n(&self) -> poulpy_core::layouts::Degree {
self.blocks[0].n()
}
}
impl<D: DataRef, T: UnsignedInteger> GLWEInfos for FheUintBlocks<D, T> {
fn rank(&self) -> poulpy_core::layouts::Rank {
self.blocks[0].rank()
}
}
impl<T: UnsignedInteger> FheUintBlocks<Vec<u8>, T> {
#[allow(dead_code)]
pub(crate) fn alloc<A, BE: Backend>(module: &Module<BE>, infos: &A) -> Self
where
A: GLWEInfos,
{
Self::alloc_with(module, infos.base2k(), infos.k(), infos.rank())
}
#[allow(dead_code)]
pub(crate) fn alloc_with<BE: Backend>(module: &Module<BE>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
Self {
blocks: (0..T::WORD_SIZE)
.map(|_| GLWECiphertext::alloc_with(module.n().into(), base2k, k, rank))
.collect(),
_base: 1,
_phantom: PhantomData,
}
}
}
impl<D: DataMut, T: UnsignedInteger + ToBits> FheUintBlocks<D, T> {
#[allow(dead_code)]
#[cfg(test)]
pub(crate) fn encrypt_sk<S, BE: Backend>(
&mut self,
module: &Module<BE>,
value: T,
sk: &GLWESecretPrepared<S, BE>,
source_xa: &mut Source,
source_xe: &mut Source,
scratch: &mut Scratch<BE>,
) where
S: DataRef,
Module<BE>: VecZnxDftAllocBytes
+ VecZnxBigNormalize<BE>
+ VecZnxDftApply<BE>
+ SvpApplyDftToDftInplace<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxNormalizeTmpBytes
+ VecZnxFillUniform
+ VecZnxSubInplace
+ VecZnxAddInplace
+ VecZnxNormalizeInplace<BE>
+ VecZnxAddNormal
+ VecZnxNormalize<BE>
+ VecZnxSub,
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPt<BE>,
{
use poulpy_core::layouts::GLWEPlaintextLayout;
#[cfg(debug_assertions)]
{
assert!(module.n().is_multiple_of(T::WORD_SIZE));
assert_eq!(self.n(), module.n() as u32);
assert_eq!(sk.n(), module.n() as u32);
}
let pt_infos = GLWEPlaintextLayout {
n: self.n(),
base2k: self.base2k(),
k: 1_usize.into(),
};
let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos);
for i in 0..T::WORD_SIZE {
pt.encode_coeff_i64(value.bit(i) as i64, TorusPrecision(1), 0);
self.blocks[i].encrypt_sk(&module, &pt, sk, source_xa, source_xe, scratch_1);
}
}
}
impl<D: DataRef, T: UnsignedInteger + FromBits + ToBits> FheUintBlocks<D, T> {
pub fn decrypt<S: DataRef, BE: Backend>(
&self,
module: &Module<BE>,
sk: &GLWESecretPrepared<S, BE>,
scratch: &mut Scratch<BE>,
) -> T
where
Module<BE>: VecZnxDftApply<BE>
+ SvpApplyDftToDftInplace<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxBigAddInplace<BE>
+ VecZnxBigAddSmallInplace<BE>
+ VecZnxBigNormalize<BE>,
Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPt<BE>,
{
#[cfg(debug_assertions)]
{
assert!(module.n().is_multiple_of(T::WORD_SIZE));
assert_eq!(self.n(), module.n() as u32);
assert_eq!(sk.n(), module.n() as u32);
}
let pt_infos = GLWEPlaintextLayout {
n: self.n(),
base2k: self.base2k(),
k: self.k(),
};
let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos);
let mut bits: Vec<u8> = vec![0u8; T::WORD_SIZE];
let base2k: usize = self.base2k().into();
let scale: f64 = 4.0 / ((1 << base2k) as f64);
for (i, bit) in bits.iter_mut().enumerate().take(T::WORD_SIZE) {
self.blocks[i].decrypt(module, &mut pt, sk, scratch_1);
let value: i64 = pt.decode_coeff_i64(base2k.into(), 0);
*bit = ((value as f64) * scale).round() as u8;
}
T::from_bits(&bits)
}
pub fn noise<S: DataRef, BE: Backend>(
&self,
module: &Module<BE>,
sk: &GLWESecretPrepared<S, BE>,
want: T,
scratch: &mut Scratch<BE>,
) -> Vec<f64>
where
Module<BE>: VecZnxDftAllocBytes
+ VecZnxBigAllocBytes
+ VecZnxDftApply<BE>
+ SvpApplyDftToDftInplace<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxBigAddInplace<BE>
+ VecZnxBigAddSmallInplace<BE>
+ VecZnxBigNormalize<BE>
+ VecZnxNormalizeTmpBytes
+ VecZnxSubInplace
+ VecZnxNormalizeInplace<BE>,
Scratch<BE>: TakeGLWEPt<BE> + TakeVecZnxDft<BE> + TakeVecZnxBig<BE>,
{
#[cfg(debug_assertions)]
{
assert!(module.n().is_multiple_of(T::WORD_SIZE));
assert_eq!(self.n(), module.n() as u32);
assert_eq!(sk.n(), module.n() as u32);
}
let pt_infos = GLWEPlaintextLayout {
n: self.n(),
base2k: self.base2k(),
k: 1_usize.into(),
};
let (mut pt_want, scratch_1) = scratch.take_glwe_pt(&pt_infos);
let mut noise: Vec<f64> = vec![0f64; T::WORD_SIZE];
for (i, noise_i) in noise.iter_mut().enumerate().take(T::WORD_SIZE) {
pt_want.encode_coeff_i64(want.bit(i) as i64, TorusPrecision(2), 0);
*noise_i = self.blocks[i].noise(module, sk, &pt_want, scratch_1);
}
noise
}
}

View File

@@ -0,0 +1,282 @@
use std::marker::PhantomData;
use poulpy_core::layouts::{
Base2K, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWCiphertextPrepared,
};
#[cfg(test)]
use poulpy_core::{
TakeGGSW,
layouts::{GGSWCiphertext, prepared::GLWESecretPrepared},
};
use poulpy_hal::{
api::VmpPMatAlloc,
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
};
#[cfg(test)]
use poulpy_hal::{
api::{
ScratchAvailable, SvpApplyDftToDftInplace, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal,
VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes,
VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform,
VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub,
VecZnxSubInplace, VmpPrepare,
},
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl},
source::Source,
};
use crate::tfhe::bdd_arithmetic::{FheUintBlocks, FheUintPrepare, ToBits, UnsignedInteger};
#[cfg(test)]
pub(crate) struct FheUintBlocksPrepDebug<D: Data, T: UnsignedInteger> {
pub(crate) blocks: Vec<GGSWCiphertext<D>>,
pub(crate) _base: u8,
pub(crate) _phantom: PhantomData<T>,
}
#[cfg(test)]
impl<T: UnsignedInteger> FheUintBlocksPrepDebug<Vec<u8>, T> {
#[allow(dead_code)]
pub(crate) fn alloc<A, BE: Backend>(module: &Module<BE>, infos: &A) -> Self
where
A: GGSWInfos,
{
Self::alloc_with(
module,
infos.base2k(),
infos.k(),
infos.dnum(),
infos.dsize(),
infos.rank(),
)
}
#[allow(dead_code)]
pub(crate) fn alloc_with<BE: Backend>(
module: &Module<BE>,
base2k: Base2K,
k: TorusPrecision,
dnum: Dnum,
dsize: Dsize,
rank: Rank,
) -> Self {
Self {
blocks: (0..T::WORD_SIZE)
.map(|_| GGSWCiphertext::alloc_with(module.n().into(), base2k, k, rank, dnum, dsize))
.collect(),
_base: 1,
_phantom: PhantomData,
}
}
}
/// A prepared FHE ciphertext encrypting the bits of an [UnsignedInteger].
pub struct FheUintBlocksPrep<D: Data, B: Backend, T: UnsignedInteger> {
pub(crate) blocks: Vec<GGSWCiphertextPrepared<D, B>>,
pub(crate) _base: u8,
pub(crate) _phantom: PhantomData<T>,
}
impl<T: UnsignedInteger, BE: Backend> FheUintBlocksPrep<Vec<u8>, BE, T>
where
Module<BE>: VmpPMatAlloc<BE>,
{
#[allow(dead_code)]
pub(crate) fn alloc<A>(module: &Module<BE>, infos: &A) -> Self
where
A: GGSWInfos,
{
Self::alloc_with(
module,
infos.base2k(),
infos.k(),
infos.dnum(),
infos.dsize(),
infos.rank(),
)
}
#[allow(dead_code)]
pub(crate) fn alloc_with(module: &Module<BE>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
where
Module<BE>: VmpPMatAlloc<BE>,
{
Self {
blocks: (0..T::WORD_SIZE)
.map(|_| GGSWCiphertextPrepared::alloc_with(module, base2k, k, dnum, dsize, rank))
.collect(),
_base: 1,
_phantom: PhantomData,
}
}
}
impl<D: DataMut, T: UnsignedInteger + ToBits, BE: Backend> FheUintBlocksPrep<D, BE, T> {
#[allow(dead_code)]
#[cfg(test)]
pub(crate) fn encrypt_sk<S>(
&mut self,
module: &Module<BE>,
value: T,
sk: &GLWESecretPrepared<S, BE>,
source_xa: &mut Source,
source_xe: &mut Source,
scratch: &mut Scratch<BE>,
) where
S: DataRef,
Module<BE>: VecZnxAddScalarInplace
+ VecZnxDftAllocBytes
+ VecZnxBigNormalize<BE>
+ VecZnxDftApply<BE>
+ SvpApplyDftToDftInplace<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxNormalizeTmpBytes
+ VecZnxFillUniform
+ VecZnxSubInplace
+ VecZnxAddInplace
+ VecZnxNormalizeInplace<BE>
+ VecZnxAddNormal
+ VecZnxNormalize<BE>
+ VecZnxSub
+ VmpPrepare<BE>,
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGGSW + TakeScalarZnx,
{
#[cfg(debug_assertions)]
{
assert!(module.n().is_multiple_of(T::WORD_SIZE));
assert_eq!(self.n(), module.n() as u32);
assert_eq!(sk.n(), module.n() as u32);
}
let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(self);
let (mut pt, scratch_2) = scratch_1.take_scalar_znx(module.n(), 1);
for i in 0..T::WORD_SIZE {
use poulpy_core::layouts::prepared::Prepare;
use poulpy_hal::layouts::ZnxViewMut;
pt.at_mut(0, 0)[0] = value.bit(i) as i64;
tmp_ggsw.encrypt_sk(&module, &pt, sk, source_xa, source_xe, scratch_2);
self.blocks[i].prepare(module, &tmp_ggsw, scratch_2);
}
}
/// Prepares [FheUintBits] to [FheUintBitsPrep].
pub fn prepare<BIT, KEY>(&mut self, module: &Module<BE>, bits: &FheUintBlocks<BIT, T>, key: &KEY, scratch: &mut Scratch<BE>)
where
BIT: DataRef,
KEY: FheUintPrepare<BE, FheUintBlocksPrep<D, BE, T>, FheUintBlocks<BIT, T>>,
{
key.prepare(module, self, bits, scratch);
}
}
#[cfg(test)]
impl<D: DataMut, T: UnsignedInteger + ToBits> FheUintBlocksPrepDebug<D, T> {
pub(crate) fn prepare<BIT, KEY, BE: Backend>(
&mut self,
module: &Module<BE>,
bits: &FheUintBlocks<BIT, T>,
key: &KEY,
scratch: &mut Scratch<BE>,
) where
BIT: DataRef,
KEY: FheUintPrepare<BE, FheUintBlocksPrepDebug<D, T>, FheUintBlocks<BIT, T>>,
{
key.prepare(module, self, bits, scratch);
}
}
#[cfg(test)]
impl<D: DataRef, T: UnsignedInteger + ToBits> FheUintBlocksPrepDebug<D, T> {
#[allow(dead_code)]
pub(crate) fn noise<S: DataRef, BE: Backend>(&self, module: &Module<BE>, sk: &GLWESecretPrepared<S, BE>, want: T)
where
Module<BE>: VecZnxDftAllocBytes
+ VecZnxBigAllocBytes
+ VecZnxDftApply<BE>
+ SvpApplyDftToDftInplace<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxBigAddInplace<BE>
+ VecZnxBigAddSmallInplace<BE>
+ VecZnxBigNormalize<BE>
+ VecZnxNormalizeTmpBytes
+ VecZnxBigAlloc<BE>
+ VecZnxDftAlloc<BE>
+ VecZnxBigNormalizeTmpBytes
+ VecZnxIdftApplyTmpA<BE>
+ VecZnxAddScalarInplace
+ VecZnxSubInplace,
BE: Backend + TakeVecZnxDftImpl<BE> + TakeVecZnxBigImpl<BE> + ScratchOwnedAllocImpl<BE> + ScratchOwnedBorrowImpl<BE>,
{
for (i, ggsw) in self.blocks.iter().enumerate() {
use poulpy_hal::layouts::{ScalarZnx, ZnxViewMut};
let mut pt_want = ScalarZnx::alloc(self.n().into(), 1);
pt_want.at_mut(0, 0)[0] = want.bit(i) as i64;
ggsw.print_noise(module, sk, &pt_want);
}
}
}
impl<D: DataRef, T: UnsignedInteger, B: Backend> LWEInfos for FheUintBlocksPrep<D, B, T> {
fn base2k(&self) -> poulpy_core::layouts::Base2K {
self.blocks[0].base2k()
}
fn k(&self) -> poulpy_core::layouts::TorusPrecision {
self.blocks[0].k()
}
fn n(&self) -> poulpy_core::layouts::Degree {
self.blocks[0].n()
}
}
impl<D: DataRef, T: UnsignedInteger, B: Backend> GLWEInfos for FheUintBlocksPrep<D, B, T> {
fn rank(&self) -> poulpy_core::layouts::Rank {
self.blocks[0].rank()
}
}
impl<D: DataRef, T: UnsignedInteger, B: Backend> GGSWInfos for FheUintBlocksPrep<D, B, T> {
fn dsize(&self) -> poulpy_core::layouts::Dsize {
self.blocks[0].dsize()
}
fn dnum(&self) -> poulpy_core::layouts::Dnum {
self.blocks[0].dnum()
}
}
#[cfg(test)]
impl<D: DataRef, T: UnsignedInteger> LWEInfos for FheUintBlocksPrepDebug<D, T> {
fn base2k(&self) -> poulpy_core::layouts::Base2K {
self.blocks[0].base2k()
}
fn k(&self) -> poulpy_core::layouts::TorusPrecision {
self.blocks[0].k()
}
fn n(&self) -> poulpy_core::layouts::Degree {
self.blocks[0].n()
}
}
#[cfg(test)]
impl<D: DataRef, T: UnsignedInteger> GLWEInfos for FheUintBlocksPrepDebug<D, T> {
fn rank(&self) -> poulpy_core::layouts::Rank {
self.blocks[0].rank()
}
}
#[cfg(test)]
impl<D: DataRef, T: UnsignedInteger> GGSWInfos for FheUintBlocksPrepDebug<D, T> {
fn dsize(&self) -> poulpy_core::layouts::Dsize {
self.blocks[0].dsize()
}
fn dnum(&self) -> poulpy_core::layouts::Dnum {
self.blocks[0].dnum()
}
}

View File

@@ -0,0 +1,7 @@
mod block;
mod block_prepared;
mod word;
pub use block::*;
pub use block_prepared::*;
pub use word::*;

View File

@@ -0,0 +1,198 @@
use itertools::Itertools;
use poulpy_core::{
GLWEOperations, TakeGLWECtSlice, TakeGLWEPt, glwe_packing,
layouts::{
GLWECiphertext, GLWEInfos, GLWEPlaintextLayout, LWEInfos, TorusPrecision,
prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared},
},
};
use poulpy_hal::{
api::{
ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal,
VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace,
VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy,
VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA,
VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace,
VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd,
VmpApplyDftToDftTmpBytes,
},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
source::Source,
};
use std::{collections::HashMap, marker::PhantomData};
use crate::tfhe::bdd_arithmetic::{FromBits, ToBits, UnsignedInteger};
/// A FHE ciphertext encrypting a [UnsignedInteger].
pub struct FheUintWord<D: Data, T: UnsignedInteger>(pub(crate) GLWECiphertext<D>, pub(crate) PhantomData<T>);
impl<D: DataMut, T: UnsignedInteger> FheUintWord<D, T> {
#[allow(dead_code)]
fn post_process<ATK, BE: Backend>(
&mut self,
module: &Module<BE>,
mut tmp_res: Vec<GLWECiphertext<&mut [u8]>>,
auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<ATK, BE>>,
scratch: &mut Scratch<BE>,
) where
ATK: DataRef,
Module<BE>: VecZnxSub
+ VecZnxCopy
+ VecZnxNegateInplace
+ VecZnxDftAllocBytes
+ VecZnxAddInplace
+ VmpApplyDftToDftTmpBytes
+ VecZnxNormalizeTmpBytes
+ VecZnxDftApply<BE>
+ VmpApplyDftToDft<BE>
+ VmpApplyDftToDftAdd<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxBigNormalize<BE>
+ VecZnxNormalize<BE>
+ VecZnxRotateInplace<BE>
+ VecZnxNormalizeInplace<BE>
+ VecZnxSwitchRing
+ VecZnxBigAutomorphismInplace<BE>
+ VecZnxRshInplace<BE>
+ VecZnxDftCopy<BE>
+ VecZnxIdftApplyTmpA<BE>
+ VecZnxSubInplace
+ VecZnxBigNormalizeTmpBytes
+ VecZnxBigAddSmallInplace<BE>
+ VecZnxAutomorphismInplace<BE>
+ VecZnxBigSubSmallNegateInplace<BE>
+ VecZnxRotate,
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWECtSlice,
{
// Repacks the GLWE ciphertexts bits
let gap: usize = module.n() / T::WORD_SIZE;
let log_gap: usize = (usize::BITS - (gap - 1).leading_zeros()) as usize;
let mut cts: HashMap<usize, &mut GLWECiphertext<&mut [u8]>> = HashMap::new();
for (i, ct) in tmp_res.iter_mut().enumerate().take(T::WORD_SIZE) {
cts.insert(i * gap, ct);
}
glwe_packing(module, &mut cts, log_gap, auto_keys, scratch);
// And copies the repacked ciphertext on the receiver.
self.0.copy(module, cts.remove(&0).unwrap())
}
}
impl<D: DataRef, T: UnsignedInteger> LWEInfos for FheUintWord<D, T> {
fn base2k(&self) -> poulpy_core::layouts::Base2K {
self.0.base2k()
}
fn k(&self) -> poulpy_core::layouts::TorusPrecision {
self.0.k()
}
fn n(&self) -> poulpy_core::layouts::Degree {
self.0.n()
}
}
impl<D: DataRef, T: UnsignedInteger> GLWEInfos for FheUintWord<D, T> {
fn rank(&self) -> poulpy_core::layouts::Rank {
self.0.rank()
}
}
impl<D: DataMut, T: UnsignedInteger + ToBits> FheUintWord<D, T> {
pub fn encrypt_sk<S: DataRef, BE: Backend>(
&mut self,
module: &Module<BE>,
data: T,
sk: &GLWESecretPrepared<S, BE>,
source_xa: &mut Source,
source_xe: &mut Source,
scratch: &mut Scratch<BE>,
) where
Module<BE>: VecZnxAddScalarInplace
+ VecZnxDftAllocBytes
+ VecZnxBigNormalize<BE>
+ VecZnxDftApply<BE>
+ SvpApplyDftToDftInplace<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxNormalizeTmpBytes
+ VecZnxFillUniform
+ VecZnxSubInplace
+ VecZnxAddInplace
+ VecZnxNormalizeInplace<BE>
+ VecZnxAddNormal
+ VecZnxNormalize<BE>
+ VecZnxSub,
Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPt<BE>,
{
#[cfg(debug_assertions)]
{
assert!(module.n().is_multiple_of(T::WORD_SIZE));
assert_eq!(self.n(), module.n() as u32);
assert_eq!(sk.n(), module.n() as u32);
}
let gap: usize = module.n() / T::WORD_SIZE;
let mut data_bits: Vec<i64> = vec![0i64; module.n()];
for i in 0..T::WORD_SIZE {
data_bits[i * gap] = data.bit(i) as i64
}
let pt_infos = GLWEPlaintextLayout {
n: self.n(),
base2k: self.base2k(),
k: 1_usize.into(),
};
let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos);
pt.encode_vec_i64(&data_bits, TorusPrecision(1));
self.0
.encrypt_sk(module, &pt, sk, source_xa, source_xe, scratch_1);
}
}
impl<D: DataRef, T: UnsignedInteger + FromBits> FheUintWord<D, T> {
pub fn decrypt<S: DataRef, BE: Backend>(
&self,
module: &Module<BE>,
sk: &GLWESecretPrepared<S, BE>,
scratch: &mut Scratch<BE>,
) -> T
where
Module<BE>: VecZnxDftApply<BE>
+ SvpApplyDftToDftInplace<BE>
+ VecZnxIdftApplyConsume<BE>
+ VecZnxBigAddInplace<BE>
+ VecZnxBigAddSmallInplace<BE>
+ VecZnxBigNormalize<BE>,
Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPt<BE>,
{
#[cfg(debug_assertions)]
{
assert!(module.n().is_multiple_of(T::WORD_SIZE));
assert_eq!(self.n(), module.n() as u32);
assert_eq!(sk.n(), module.n() as u32);
}
let gap: usize = module.n() / T::WORD_SIZE;
let pt_infos = GLWEPlaintextLayout {
n: self.n(),
base2k: self.base2k(),
k: 1_usize.into(),
};
let (mut pt, scratch_1) = scratch.take_glwe_pt(&pt_infos);
self.0.decrypt(module, &mut pt, sk, scratch_1);
let mut data: Vec<i64> = vec![0i64; module.n()];
pt.decode_vec_i64(&mut data, TorusPrecision(1));
let bits: Vec<u8> = data.iter().step_by(gap).map(|c| *c as u8).collect_vec();
T::from_bits(&bits)
}
}

View File

@@ -0,0 +1 @@
pub mod u32;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,465 @@
use crate::tfhe::bdd_arithmetic::{BitCircuit, BitCircuitInfo, Circuit, GetBitCircuitInfo, Node};
pub(crate) enum AnyBitCircuit {
B0(BitCircuit<3, 2>),
B1(BitCircuit<3, 2>),
B2(BitCircuit<3, 2>),
B3(BitCircuit<3, 2>),
B4(BitCircuit<3, 2>),
B5(BitCircuit<3, 2>),
B6(BitCircuit<3, 2>),
B7(BitCircuit<3, 2>),
B8(BitCircuit<3, 2>),
B9(BitCircuit<3, 2>),
B10(BitCircuit<3, 2>),
B11(BitCircuit<3, 2>),
B12(BitCircuit<3, 2>),
B13(BitCircuit<3, 2>),
B14(BitCircuit<3, 2>),
B15(BitCircuit<3, 2>),
B16(BitCircuit<3, 2>),
B17(BitCircuit<3, 2>),
B18(BitCircuit<3, 2>),
B19(BitCircuit<3, 2>),
B20(BitCircuit<3, 2>),
B21(BitCircuit<3, 2>),
B22(BitCircuit<3, 2>),
B23(BitCircuit<3, 2>),
B24(BitCircuit<3, 2>),
B25(BitCircuit<3, 2>),
B26(BitCircuit<3, 2>),
B27(BitCircuit<3, 2>),
B28(BitCircuit<3, 2>),
B29(BitCircuit<3, 2>),
B30(BitCircuit<3, 2>),
B31(BitCircuit<3, 2>),
}
impl BitCircuitInfo for AnyBitCircuit {
fn info(&self) -> (&[Node], &[usize], usize) {
match self {
AnyBitCircuit::B0(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B1(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B2(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B3(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B4(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B5(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B6(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B7(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B8(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B9(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B10(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B11(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B12(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B13(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B14(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B15(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B16(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B17(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B18(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B19(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B20(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B21(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B22(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B23(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B24(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B25(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B26(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B27(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B28(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B29(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B30(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
AnyBitCircuit::B31(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
}
}
}
impl GetBitCircuitInfo<u32> for Circuit<AnyBitCircuit, 32usize> {
fn input_size(&self) -> usize {
2 * u32::BITS as usize
}
fn output_size(&self) -> usize {
u32::BITS as usize
}
fn get_circuit(&self, bit: usize) -> (&[Node], &[usize], usize) {
self.0[bit].info()
}
}
pub(crate) static OUTPUT_CIRCUITS: Circuit<AnyBitCircuit, 32usize> = Circuit([
AnyBitCircuit::B0(BitCircuit::new(
[Node::new(0, 0, 0), Node::new(32, 1, 0), Node::new(0, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B1(BitCircuit::new(
[Node::new(1, 0, 0), Node::new(33, 1, 0), Node::new(1, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B2(BitCircuit::new(
[Node::new(2, 0, 0), Node::new(34, 1, 0), Node::new(2, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B3(BitCircuit::new(
[Node::new(3, 0, 0), Node::new(35, 1, 0), Node::new(3, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B4(BitCircuit::new(
[Node::new(4, 0, 0), Node::new(36, 1, 0), Node::new(4, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B5(BitCircuit::new(
[Node::new(5, 0, 0), Node::new(37, 1, 0), Node::new(5, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B6(BitCircuit::new(
[Node::new(6, 0, 0), Node::new(38, 1, 0), Node::new(6, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B7(BitCircuit::new(
[Node::new(7, 0, 0), Node::new(39, 1, 0), Node::new(7, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B8(BitCircuit::new(
[Node::new(8, 0, 0), Node::new(40, 1, 0), Node::new(8, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B9(BitCircuit::new(
[Node::new(9, 0, 0), Node::new(41, 1, 0), Node::new(9, 1, 0)],
[0, 2],
2,
)),
AnyBitCircuit::B10(BitCircuit::new(
[
Node::new(10, 0, 0),
Node::new(42, 1, 0),
Node::new(10, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B11(BitCircuit::new(
[
Node::new(11, 0, 0),
Node::new(43, 1, 0),
Node::new(11, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B12(BitCircuit::new(
[
Node::new(12, 0, 0),
Node::new(44, 1, 0),
Node::new(12, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B13(BitCircuit::new(
[
Node::new(13, 0, 0),
Node::new(45, 1, 0),
Node::new(13, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B14(BitCircuit::new(
[
Node::new(14, 0, 0),
Node::new(46, 1, 0),
Node::new(14, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B15(BitCircuit::new(
[
Node::new(15, 0, 0),
Node::new(47, 1, 0),
Node::new(15, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B16(BitCircuit::new(
[
Node::new(16, 0, 0),
Node::new(48, 1, 0),
Node::new(16, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B17(BitCircuit::new(
[
Node::new(17, 0, 0),
Node::new(49, 1, 0),
Node::new(17, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B18(BitCircuit::new(
[
Node::new(18, 0, 0),
Node::new(50, 1, 0),
Node::new(18, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B19(BitCircuit::new(
[
Node::new(19, 0, 0),
Node::new(51, 1, 0),
Node::new(19, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B20(BitCircuit::new(
[
Node::new(20, 0, 0),
Node::new(52, 1, 0),
Node::new(20, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B21(BitCircuit::new(
[
Node::new(21, 0, 0),
Node::new(53, 1, 0),
Node::new(21, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B22(BitCircuit::new(
[
Node::new(22, 0, 0),
Node::new(54, 1, 0),
Node::new(22, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B23(BitCircuit::new(
[
Node::new(23, 0, 0),
Node::new(55, 1, 0),
Node::new(23, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B24(BitCircuit::new(
[
Node::new(24, 0, 0),
Node::new(56, 1, 0),
Node::new(24, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B25(BitCircuit::new(
[
Node::new(25, 0, 0),
Node::new(57, 1, 0),
Node::new(25, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B26(BitCircuit::new(
[
Node::new(26, 0, 0),
Node::new(58, 1, 0),
Node::new(26, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B27(BitCircuit::new(
[
Node::new(27, 0, 0),
Node::new(59, 1, 0),
Node::new(27, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B28(BitCircuit::new(
[
Node::new(28, 0, 0),
Node::new(60, 1, 0),
Node::new(28, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B29(BitCircuit::new(
[
Node::new(29, 0, 0),
Node::new(61, 1, 0),
Node::new(29, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B30(BitCircuit::new(
[
Node::new(30, 0, 0),
Node::new(62, 1, 0),
Node::new(30, 1, 0),
],
[0, 2],
2,
)),
AnyBitCircuit::B31(BitCircuit::new(
[
Node::new(31, 0, 0),
Node::new(63, 1, 0),
Node::new(31, 1, 0),
],
[0, 2],
2,
)),
]);

View File

@@ -0,0 +1,10 @@
pub(crate) mod add_codegen;
pub(crate) mod and_codegen;
pub(crate) mod or_codegen;
pub(crate) mod sll_codegen;
pub(crate) mod slt_codegen;
pub(crate) mod sltu_codegen;
pub(crate) mod sra_codegen;
pub(crate) mod srl_codegen;
pub(crate) mod sub_codegen;
pub(crate) mod xor_codegen;

View File

@@ -0,0 +1,34 @@
use crate::tfhe::bdd_arithmetic::{BitCircuit, BitCircuitInfo, Circuit, GetBitCircuitInfo, Node};
pub(crate) enum AnyBitCircuit {
B0(BitCircuit<3, 2>),
}
impl BitCircuitInfo for AnyBitCircuit {
fn info(&self) -> (&[Node], &[usize], usize) {
match self {
AnyBitCircuit::B0(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
}
}
}
impl GetBitCircuitInfo<u32> for Circuit<AnyBitCircuit, 1usize> {
fn input_size(&self) -> usize {
2 * u32::BITS as usize
}
fn output_size(&self) -> usize {
u32::BITS as usize
}
fn get_circuit(&self, _bit: usize) -> (&[Node], &[usize], usize) {
self.0[0].info()
}
}
pub(crate) static OUTPUT_CIRCUITS: Circuit<AnyBitCircuit, 1usize> = Circuit([AnyBitCircuit::B0(BitCircuit::new(
[Node::new(0, 0, 0), Node::new(1, 1, 0), Node::new(0, 1, 1)],
[0, 2],
2,
))]);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,257 @@
use crate::tfhe::bdd_arithmetic::{BitCircuit, BitCircuitInfo, Circuit, GetBitCircuitInfo, Node};
pub(crate) enum AnyBitCircuit {
B0(BitCircuit<219, 64>),
}
impl BitCircuitInfo for AnyBitCircuit {
fn info(&self) -> (&[Node], &[usize], usize) {
match self {
AnyBitCircuit::B0(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
}
}
}
impl GetBitCircuitInfo<u32> for Circuit<AnyBitCircuit, 1usize> {
fn input_size(&self) -> usize {
2 * u32::BITS as usize
}
fn output_size(&self) -> usize {
1
}
fn get_circuit(&self, bit: usize) -> (&[Node], &[usize], usize) {
self.0[bit].info()
}
}
pub(crate) static OUTPUT_CIRCUITS: Circuit<AnyBitCircuit, 1usize> = Circuit([AnyBitCircuit::B0(BitCircuit::new(
[
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(32, 1, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(0, 0, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(33, 1, 2),
Node::new(33, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(1, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(34, 1, 2),
Node::new(34, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(2, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(35, 2, 0),
Node::new(35, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(3, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(36, 1, 2),
Node::new(36, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(4, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(37, 1, 2),
Node::new(37, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(5, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(38, 2, 0),
Node::new(38, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(6, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(39, 2, 0),
Node::new(39, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(7, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(40, 1, 2),
Node::new(40, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(8, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(41, 1, 2),
Node::new(41, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(9, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(42, 2, 0),
Node::new(42, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(10, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(43, 2, 0),
Node::new(43, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(11, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(44, 1, 2),
Node::new(44, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(12, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(45, 1, 2),
Node::new(45, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(13, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(46, 2, 0),
Node::new(46, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(14, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(47, 1, 2),
Node::new(47, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(15, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(48, 2, 0),
Node::new(48, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(16, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(49, 1, 2),
Node::new(49, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(17, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(50, 2, 0),
Node::new(50, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(18, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(51, 2, 0),
Node::new(51, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(19, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(52, 1, 2),
Node::new(52, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(20, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(53, 2, 0),
Node::new(53, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(21, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(54, 1, 2),
Node::new(54, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(22, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(55, 1, 2),
Node::new(55, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(23, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(56, 2, 0),
Node::new(56, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(24, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(57, 1, 2),
Node::new(57, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(25, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(58, 2, 0),
Node::new(58, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(26, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(59, 2, 0),
Node::new(59, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(27, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(60, 2, 0),
Node::new(60, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(28, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(61, 1, 2),
Node::new(61, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(29, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(62, 1, 2),
Node::new(62, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(30, 3, 2),
Node::new(63, 2, 1),
Node::new(63, 0, 2),
Node::new(31, 0, 1),
],
[
0, 3, 6, 10, 13, 17, 20, 24, 27, 31, 34, 38, 41, 45, 48, 52, 55, 59, 62, 66, 69, 73, 76, 80, 83, 87, 90, 94, 97, 101,
104, 108, 111, 115, 118, 122, 125, 129, 132, 136, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 178, 181, 185,
188, 192, 195, 199, 202, 206, 209, 213, 216, 218,
],
4,
))]);

View File

@@ -0,0 +1,257 @@
use crate::tfhe::bdd_arithmetic::{BitCircuit, BitCircuitInfo, Circuit, GetBitCircuitInfo, Node};
pub(crate) enum AnyBitCircuit {
B0(BitCircuit<219, 64>),
}
impl BitCircuitInfo for AnyBitCircuit {
fn info(&self) -> (&[Node], &[usize], usize) {
match self {
AnyBitCircuit::B0(bit_circuit) => (
bit_circuit.nodes.as_ref(),
bit_circuit.levels.as_ref(),
bit_circuit.max_inter_state,
),
}
}
}
impl GetBitCircuitInfo<u32> for Circuit<AnyBitCircuit, 1usize> {
fn input_size(&self) -> usize {
2 * u32::BITS as usize
}
fn output_size(&self) -> usize {
1
}
fn get_circuit(&self, bit: usize) -> (&[Node], &[usize], usize) {
self.0[bit].info()
}
}
pub(crate) static OUTPUT_CIRCUITS: Circuit<AnyBitCircuit, 1usize> = Circuit([AnyBitCircuit::B0(BitCircuit::new(
[
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(32, 1, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(0, 0, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(33, 2, 0),
Node::new(33, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(1, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(34, 2, 0),
Node::new(34, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(2, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(35, 1, 2),
Node::new(35, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(3, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(36, 2, 0),
Node::new(36, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(4, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(37, 2, 0),
Node::new(37, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(5, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(38, 1, 2),
Node::new(38, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(6, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(39, 2, 0),
Node::new(39, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(7, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(40, 1, 2),
Node::new(40, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(8, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(41, 1, 2),
Node::new(41, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(9, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(42, 1, 2),
Node::new(42, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(10, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(43, 2, 0),
Node::new(43, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(11, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(44, 1, 2),
Node::new(44, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(12, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(45, 2, 0),
Node::new(45, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(13, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(46, 1, 2),
Node::new(46, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(14, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(47, 2, 0),
Node::new(47, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(15, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(48, 2, 0),
Node::new(48, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(16, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(49, 1, 2),
Node::new(49, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(17, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(50, 1, 2),
Node::new(50, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(18, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(51, 1, 2),
Node::new(51, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(19, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(52, 2, 0),
Node::new(52, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(20, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(53, 2, 0),
Node::new(53, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(21, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(54, 2, 0),
Node::new(54, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(22, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(55, 1, 2),
Node::new(55, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(23, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(56, 2, 0),
Node::new(56, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(24, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(57, 1, 2),
Node::new(57, 2, 0),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(25, 3, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(58, 2, 0),
Node::new(58, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(26, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(59, 2, 0),
Node::new(59, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(27, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(60, 2, 0),
Node::new(60, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(28, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(61, 2, 0),
Node::new(61, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(29, 2, 3),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(62, 2, 0),
Node::new(62, 1, 2),
Node::new(0, 0, 0),
Node::new(0, 1, 1),
Node::new(30, 2, 3),
Node::new(63, 2, 0),
Node::new(63, 1, 2),
Node::new(31, 0, 1),
],
[
0, 3, 6, 10, 13, 17, 20, 24, 27, 31, 34, 38, 41, 45, 48, 52, 55, 59, 62, 66, 69, 73, 76, 80, 83, 87, 90, 94, 97, 101,
104, 108, 111, 115, 118, 122, 125, 129, 132, 136, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 178, 181, 185,
188, 192, 195, 199, 202, 206, 209, 213, 216, 218,
],
4,
))]);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More