mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
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:
committed by
GitHub
parent
37e13b965c
commit
6357a05509
17
Cargo.lock
generated
17
Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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] = [
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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,
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
});
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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!(">>>>>>>>>>>>>>>>");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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(),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
220
poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs
Normal file
220
poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs
Normal 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
|
||||
);
|
||||
215
poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block.rs
Normal file
215
poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block.rs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mod block;
|
||||
mod block_prepared;
|
||||
mod word;
|
||||
|
||||
pub use block::*;
|
||||
pub use block_prepared::*;
|
||||
pub use word::*;
|
||||
198
poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/word.rs
Normal file
198
poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/word.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
1
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/mod.rs
Normal file
1
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod u32;
|
||||
3020
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/add_codegen.rs
Normal file
3020
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/add_codegen.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
)),
|
||||
]);
|
||||
10
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/mod.rs
Normal file
10
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/mod.rs
Normal 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;
|
||||
@@ -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,
|
||||
))]);
|
||||
1830
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/sll_codegen.rs
Normal file
1830
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/sll_codegen.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
))]);
|
||||
@@ -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,
|
||||
))]);
|
||||
1762
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/sra_codegen.rs
Normal file
1762
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/sra_codegen.rs
Normal file
File diff suppressed because it is too large
Load Diff
1830
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/srl_codegen.rs
Normal file
1830
poulpy-schemes/src/tfhe/bdd_arithmetic/circuits/u32/srl_codegen.rs
Normal file
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
Reference in New Issue
Block a user