Added more serialization tests + generalize methods to any n

This commit is contained in:
Pro7ech
2025-08-13 15:28:52 +02:00
parent 068470783e
commit 940742ce6c
117 changed files with 3658 additions and 2577 deletions

View File

@@ -8,6 +8,7 @@ use crate::{AutomorphismKey, AutomorphismKeyExec, GLWECiphertext, GLWEKeyswitchF
impl AutomorphismKey<Vec<u8>> {
pub fn automorphism_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_in: usize,
@@ -18,11 +19,12 @@ impl AutomorphismKey<Vec<u8>> {
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWECiphertext::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank, rank)
GLWECiphertext::keyswitch_scratch_space(module, n, basek, k_out, k_in, k_ksk, digits, rank, rank)
}
pub fn automorphism_inplace_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_ksk: usize,
@@ -32,7 +34,7 @@ impl AutomorphismKey<Vec<u8>> {
where
Module<B>: GLWEKeyswitchFamily<B>,
{
AutomorphismKey::automorphism_scratch_space(module, basek, k_out, k_out, k_ksk, digits, rank)
AutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_out, k_ksk, digits, rank)
}
}

View File

@@ -1,8 +1,8 @@
use backend::hal::{
api::{
ScalarZnxAllocBytes, ScratchAvailable, SvpApply, TakeScalarZnx, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft,
VecZnxAddScalarInplace, VecZnxAllocBytes, VecZnxAutomorphism, VecZnxBigAllocBytes, VecZnxDftToVecZnxBigTmpA,
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSwithcDegree, ZnxZero,
ScratchAvailable, SvpApply, TakeScalarZnx, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddScalarInplace,
VecZnxAutomorphism, VecZnxBigAllocBytes, VecZnxDftToVecZnxBigTmpA, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
VecZnxSwithcDegree, ZnxZero,
},
layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch},
};
@@ -18,15 +18,15 @@ use crate::{
pub trait GGLWEEncryptSkFamily<B: Backend> = GLWEEncryptSkFamily<B> + GLWESecretFamily<B>;
impl GGLWECiphertext<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize) -> usize
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize
where
Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAllocBytes,
Module<B>: GGLWEEncryptSkFamily<B>,
{
GLWECiphertext::encrypt_sk_scratch_space(module, basek, k)
+ (GLWEPlaintext::byte_of(module, basek, k) | module.vec_znx_normalize_tmp_bytes(module.n()))
GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k)
+ (GLWEPlaintext::byte_of(n, basek, k) | module.vec_znx_normalize_tmp_bytes(n))
}
pub fn encrypt_pk_scratch_space<B: Backend>(_module: &Module<B>, _basek: usize, _k: usize, _rank: usize) -> usize {
pub fn encrypt_pk_scratch_space<B: Backend>(_module: &Module<B>, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize {
unimplemented!()
}
}
@@ -42,8 +42,8 @@ impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAllocBytes + VecZnxAddScalarInplace,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx<B>,
Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAddScalarInplace,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
@@ -63,16 +63,15 @@ impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> {
self.rank_out(),
sk.rank()
);
assert_eq!(self.n(), module.n());
assert_eq!(sk.n(), module.n());
assert_eq!(pt.n(), module.n());
assert_eq!(self.n(), sk.n());
assert_eq!(pt.n(), sk.n());
assert!(
scratch.available() >= GGLWECiphertext::encrypt_sk_scratch_space(module, self.basek(), self.k()),
scratch.available() >= GGLWECiphertext::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()),
"scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}",
scratch.available(),
self.rank(),
self.size(),
GGLWECiphertext::encrypt_sk_scratch_space(module, self.basek(), self.k())
GGLWECiphertext::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k())
);
assert!(
self.rows() * self.digits() * self.basek() <= self.k(),
@@ -91,7 +90,7 @@ impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> {
let k: usize = self.k();
let rank_in: usize = self.rank_in();
let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(module, basek, k);
let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(sk.n(), basek, k);
// For each input column (i.e. rank) produces a GGLWE ciphertext of rank_out+1 columns
//
// Example for ksk rank 2 to rank 3:
@@ -125,11 +124,11 @@ impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> {
}
impl GGLWECiphertextCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize) -> usize
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize
where
Module<B>: GLWESwitchingKeyEncryptSkFamily<B> + VecZnxAllocBytes,
Module<B>: GLWESwitchingKeyEncryptSkFamily<B>,
{
GGLWECiphertext::encrypt_sk_scratch_space(module, basek, k)
GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k)
}
}
@@ -144,8 +143,8 @@ impl<D: DataMut> GGLWECiphertextCompressed<D> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAllocBytes + VecZnxAddScalarInplace,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx<B>,
Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAddScalarInplace,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
@@ -165,16 +164,16 @@ impl<D: DataMut> GGLWECiphertextCompressed<D> {
self.rank_out(),
sk.rank()
);
assert_eq!(self.n(), module.n());
assert_eq!(sk.n(), module.n());
assert_eq!(pt.n(), module.n());
assert_eq!(self.n(), sk.n());
assert_eq!(pt.n(), sk.n());
assert!(
scratch.available() >= GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, self.basek(), self.k()),
scratch.available()
>= GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()),
"scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}",
scratch.available(),
self.rank(),
self.size(),
GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, self.basek(), self.k())
GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k())
);
assert!(
self.rows() * self.digits() * self.basek() <= self.k(),
@@ -196,7 +195,7 @@ impl<D: DataMut> GGLWECiphertextCompressed<D> {
let mut source_xa = Source::new(seed);
let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(module, basek, k);
let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(sk.n(), basek, k);
(0..rank_in).for_each(|col_i| {
(0..rows).for_each(|row_i| {
// Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
@@ -237,27 +236,29 @@ pub trait GLWESwitchingKeyEncryptSkFamily<B: Backend> = GGLWEEncryptSkFamily<B>;
impl GLWESwitchingKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k: usize,
rank_in: usize,
rank_out: usize,
) -> usize
where
Module<B>: GLWESwitchingKeyEncryptSkFamily<B> + ScalarZnxAllocBytes + VecZnxAllocBytes,
Module<B>: GLWESwitchingKeyEncryptSkFamily<B>,
{
(GGLWECiphertext::encrypt_sk_scratch_space(module, basek, k) | module.scalar_znx_alloc_bytes(1))
+ module.scalar_znx_alloc_bytes(rank_in)
+ GLWESecretExec::bytes_of(module, rank_out)
(GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1))
+ ScalarZnx::alloc_bytes(n, rank_in)
+ GLWESecretExec::bytes_of(module, n, rank_out)
}
pub fn encrypt_pk_scratch_space<B: Backend>(
module: &Module<B>,
_n: usize,
_basek: usize,
_k: usize,
_rank_in: usize,
_rank_out: usize,
) -> usize {
GGLWECiphertext::encrypt_pk_scratch_space(module, _basek, _k, _rank_out)
GGLWECiphertext::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank_out)
}
}
@@ -272,13 +273,8 @@ impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWESwitchingKeyEncryptSkFamily<B>
+ ScalarZnxAllocBytes
+ VecZnxSwithcDegree
+ VecZnxAllocBytes
+ VecZnxAddScalarInplace,
Scratch<B>:
ScratchAvailable + TakeScalarZnx<B> + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx<B>,
Module<B>: GLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
@@ -288,6 +284,7 @@ impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
scratch.available()
>= GLWESwitchingKey::encrypt_sk_scratch_space(
module,
sk_out.n(),
self.basek(),
self.k(),
self.rank_in(),
@@ -297,6 +294,7 @@ impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
scratch.available(),
GLWESwitchingKey::encrypt_sk_scratch_space(
module,
sk_out.n(),
self.basek(),
self.k(),
self.rank_in(),
@@ -305,7 +303,9 @@ impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
)
}
let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(module, sk_in.rank());
let n: usize = sk_in.n().max(sk_out.n());
let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank());
(0..sk_in.rank()).for_each(|i| {
module.vec_znx_switch_degree(
&mut sk_in_tmp.as_vec_znx_mut(),
@@ -315,9 +315,9 @@ impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
);
});
let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(module, sk_out.rank());
let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank());
{
let (mut tmp, _) = scratch2.take_scalar_znx(module, 1);
let (mut tmp, _) = scratch2.take_scalar_znx(n, 1);
(0..sk_out.rank()).for_each(|i| {
module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
@@ -341,17 +341,18 @@ impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
impl GLWESwitchingKeyCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k: usize,
rank_in: usize,
rank_out: usize,
) -> usize
where
Module<B>: GLWESwitchingKeyEncryptSkFamily<B> + ScalarZnxAllocBytes + VecZnxAllocBytes,
Module<B>: GLWESwitchingKeyEncryptSkFamily<B>,
{
(GGLWECiphertext::encrypt_sk_scratch_space(module, basek, k) | module.scalar_znx_alloc_bytes(1))
+ module.scalar_znx_alloc_bytes(rank_in)
+ GLWESecretExec::bytes_of(module, rank_out)
(GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1))
+ ScalarZnx::alloc_bytes(n, rank_in)
+ GLWESecretExec::bytes_of(module, n, rank_out)
}
}
@@ -366,13 +367,8 @@ impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWESwitchingKeyEncryptSkFamily<B>
+ ScalarZnxAllocBytes
+ VecZnxSwithcDegree
+ VecZnxAllocBytes
+ VecZnxAddScalarInplace,
Scratch<B>:
ScratchAvailable + TakeScalarZnx<B> + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx<B>,
Module<B>: GLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + ScratchAvailable + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
@@ -382,6 +378,7 @@ impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> {
scratch.available()
>= GLWESwitchingKey::encrypt_sk_scratch_space(
module,
sk_out.n(),
self.basek(),
self.k(),
self.rank_in(),
@@ -391,6 +388,7 @@ impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> {
scratch.available(),
GLWESwitchingKey::encrypt_sk_scratch_space(
module,
sk_out.n(),
self.basek(),
self.k(),
self.rank_in(),
@@ -399,7 +397,9 @@ impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> {
)
}
let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(module, sk_in.rank());
let n: usize = sk_in.n().max(sk_out.n());
let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank());
(0..sk_in.rank()).for_each(|i| {
module.vec_znx_switch_degree(
&mut sk_in_tmp.as_vec_znx_mut(),
@@ -409,9 +409,9 @@ impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> {
);
});
let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(module, sk_out.rank());
let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_exec(n, sk_out.rank());
{
let (mut tmp, _) = scratch2.take_scalar_znx(module, 1);
let (mut tmp, _) = scratch2.take_scalar_znx(n, 1);
(0..sk_out.rank()).for_each(|i| {
module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
@@ -435,15 +435,15 @@ impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> {
pub trait AutomorphismKeyEncryptSkFamily<B: Backend> = GGLWEEncryptSkFamily<B>;
impl AutomorphismKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize
where
Module<B>: AutomorphismKeyEncryptSkFamily<B> + ScalarZnxAllocBytes + VecZnxAllocBytes,
Module<B>: AutomorphismKeyEncryptSkFamily<B>,
{
GLWESwitchingKey::encrypt_sk_scratch_space(module, basek, k, rank, rank) + GLWESecret::bytes_of(module, rank)
GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank)
}
pub fn encrypt_pk_scratch_space<B: Backend>(module: &Module<B>, _basek: usize, _k: usize, _rank: usize) -> usize {
GLWESwitchingKey::encrypt_pk_scratch_space(module, _basek, _k, _rank, _rank)
pub fn encrypt_pk_scratch_space<B: Backend>(module: &Module<B>, _n: usize, _basek: usize, _k: usize, _rank: usize) -> usize {
GLWESwitchingKey::encrypt_pk_scratch_space(module, _n, _basek, _k, _rank, _rank)
}
}
@@ -458,31 +458,26 @@ impl<DataSelf: DataMut> AutomorphismKey<DataSelf> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: AutomorphismKeyEncryptSkFamily<B>
+ ScalarZnxAllocBytes
+ VecZnxAllocBytes
+ VecZnxAutomorphism
+ VecZnxSwithcDegree
+ VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeScalarZnx<B> + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx<B>,
Module<B>: AutomorphismKeyEncryptSkFamily<B> + VecZnxAutomorphism + VecZnxSwithcDegree + VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
assert_eq!(self.n(), module.n());
assert_eq!(sk.n(), module.n());
assert_eq!(self.n(), sk.n());
assert_eq!(self.rank_out(), self.rank_in());
assert_eq!(sk.rank(), self.rank());
assert!(
scratch.available() >= AutomorphismKey::encrypt_sk_scratch_space(module, self.basek(), self.k(), self.rank()),
scratch.available()
>= AutomorphismKey::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()),
"scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}",
scratch.available(),
self.rank(),
self.size(),
AutomorphismKey::encrypt_sk_scratch_space(module, self.basek(), self.k(), self.rank())
AutomorphismKey::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank())
)
}
let (mut sk_out, scratch_1) = scratch.take_glwe_secret(module, sk.rank());
let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank());
{
(0..self.rank()).for_each(|i| {
@@ -504,11 +499,11 @@ impl<DataSelf: DataMut> AutomorphismKey<DataSelf> {
}
impl AutomorphismKeyCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize
where
Module<B>: AutomorphismKeyEncryptSkFamily<B> + ScalarZnxAllocBytes + VecZnxAllocBytes,
Module<B>: AutomorphismKeyEncryptSkFamily<B>,
{
GLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, basek, k, rank, rank) + GLWESecret::bytes_of(module, rank)
GLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, n, basek, k, rank, rank) + GLWESecret::bytes_of(n, rank)
}
}
@@ -523,32 +518,26 @@ impl<DataSelf: DataMut> AutomorphismKeyCompressed<DataSelf> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: AutomorphismKeyEncryptSkFamily<B>
+ ScalarZnxAllocBytes
+ VecZnxAllocBytes
+ VecZnxSwithcDegree
+ VecZnxAutomorphism
+ VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeScalarZnx<B> + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx<B>,
Module<B>: AutomorphismKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAutomorphism + VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretExec<B> + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
assert_eq!(self.n(), module.n());
assert_eq!(sk.n(), module.n());
assert_eq!(self.n(), sk.n());
assert_eq!(self.rank_out(), self.rank_in());
assert_eq!(sk.rank(), self.rank());
assert!(
scratch.available()
>= AutomorphismKeyCompressed::encrypt_sk_scratch_space(module, self.basek(), self.k(), self.rank()),
>= AutomorphismKeyCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank()),
"scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}",
scratch.available(),
self.rank(),
self.size(),
AutomorphismKeyCompressed::encrypt_sk_scratch_space(module, self.basek(), self.k(), self.rank())
AutomorphismKeyCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k(), self.rank())
)
}
let (mut sk_out, scratch_1) = scratch.take_glwe_secret(module, sk.rank());
let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank());
{
(0..self.rank()).for_each(|i| {
@@ -573,16 +562,16 @@ pub trait GLWETensorKeyEncryptSkFamily<B: Backend> =
GGLWEEncryptSkFamily<B> + VecZnxBigAllocBytes + VecZnxDftToVecZnxBigTmpA<B> + SvpApply<B>;
impl GLWETensorKey<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize
where
Module<B>: GLWETensorKeyEncryptSkFamily<B> + ScalarZnxAllocBytes + VecZnxAllocBytes,
Module<B>: GLWETensorKeyEncryptSkFamily<B>,
{
GLWESecretExec::bytes_of(module, rank)
+ module.vec_znx_dft_alloc_bytes(rank, 1)
+ module.vec_znx_big_alloc_bytes(1, 1)
+ module.vec_znx_dft_alloc_bytes(1, 1)
+ GLWESecret::bytes_of(module, 1)
+ GLWESwitchingKey::encrypt_sk_scratch_space(module, basek, k, rank, rank)
GLWESecretExec::bytes_of(module, n, rank)
+ module.vec_znx_dft_alloc_bytes(n, rank, 1)
+ module.vec_znx_big_alloc_bytes(n, 1, 1)
+ module.vec_znx_dft_alloc_bytes(n, 1, 1)
+ GLWESecret::bytes_of(n, 1)
+ GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k, rank, rank)
}
}
@@ -596,35 +585,31 @@ impl<DataSelf: DataMut> GLWETensorKey<DataSelf> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWETensorKeyEncryptSkFamily<B>
+ ScalarZnxAllocBytes
+ VecZnxSwithcDegree
+ VecZnxAllocBytes
+ VecZnxAddScalarInplace,
Scratch<B>:
ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx<B> + TakeVecZnx<B>,
Module<B>: GLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
assert_eq!(self.rank(), sk.rank());
assert_eq!(self.n(), module.n());
assert_eq!(sk.n(), module.n());
assert_eq!(self.n(), sk.n());
}
let n: usize = sk.n();
let rank: usize = self.rank();
let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(module, rank);
let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank);
sk_dft_prep.prepare(module, &sk);
let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(module, rank, 1);
let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1);
(0..rank).for_each(|i| {
module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
});
let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(module, 1, 1);
let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(module, 1);
let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(module, 1, 1);
let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(n, 1, 1);
let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(n, 1);
let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(n, 1, 1);
(0..rank).for_each(|i| {
(i..rank).for_each(|j| {
@@ -648,11 +633,11 @@ impl<DataSelf: DataMut> GLWETensorKey<DataSelf> {
}
impl GLWETensorKeyCompressed<Vec<u8>> {
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> usize
where
Module<B>: GLWETensorKeyEncryptSkFamily<B> + ScalarZnxAllocBytes + VecZnxAllocBytes,
Module<B>: GLWETensorKeyEncryptSkFamily<B>,
{
GLWETensorKey::encrypt_sk_scratch_space(module, basek, k, rank)
GLWETensorKey::encrypt_sk_scratch_space(module, n, basek, k, rank)
}
}
@@ -666,35 +651,30 @@ impl<DataSelf: DataMut> GLWETensorKeyCompressed<DataSelf> {
sigma: f64,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWETensorKeyEncryptSkFamily<B>
+ ScalarZnxAllocBytes
+ VecZnxSwithcDegree
+ VecZnxAllocBytes
+ VecZnxAddScalarInplace,
Scratch<B>:
ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx<B> + TakeVecZnx<B>,
Module<B>: GLWETensorKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace,
Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeGLWESecretExec<B> + TakeScalarZnx + TakeVecZnx,
{
#[cfg(debug_assertions)]
{
assert_eq!(self.rank(), sk.rank());
assert_eq!(self.n(), module.n());
assert_eq!(sk.n(), module.n());
assert_eq!(self.n(), sk.n());
}
let n: usize = sk.n();
let rank: usize = self.rank();
let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(module, rank);
let (mut sk_dft_prep, scratch1) = scratch.take_glwe_secret_exec(n, rank);
sk_dft_prep.prepare(module, &sk);
let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(module, rank, 1);
let (mut sk_dft, scratch2) = scratch1.take_vec_znx_dft(n, rank, 1);
(0..rank).for_each(|i| {
module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
});
let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(module, 1, 1);
let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(module, 1);
let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(module, 1, 1);
let (mut sk_ij_big, scratch3) = scratch2.take_vec_znx_big(n, 1, 1);
let (mut sk_ij, scratch4) = scratch3.take_glwe_secret(n, 1);
let (mut sk_ij_dft, scratch5) = scratch4.take_vec_znx_dft(n, 1, 1);
let mut source_xa: Source = Source::new(seed_xa);

View File

@@ -8,6 +8,7 @@ use crate::{AutomorphismKey, GGSWCiphertextExec, GLWECiphertext, GLWEExternalPro
impl GLWESwitchingKey<Vec<u8>> {
pub fn external_product_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_in: usize,
@@ -18,11 +19,12 @@ impl GLWESwitchingKey<Vec<u8>> {
where
Module<B>: GLWEExternalProductFamily<B>,
{
GLWECiphertext::external_product_scratch_space(module, basek, k_out, k_in, k_ggsw, digits, rank)
GLWECiphertext::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank)
}
pub fn external_product_inplace_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_ggsw: usize,
@@ -32,7 +34,7 @@ impl GLWESwitchingKey<Vec<u8>> {
where
Module<B>: GLWEExternalProductFamily<B>,
{
GLWECiphertext::external_product_inplace_scratch_space(module, basek, k_out, k_ggsw, digits, rank)
GLWECiphertext::external_product_inplace_scratch_space(module, n, basek, k_out, k_ggsw, digits, rank)
}
}
@@ -118,6 +120,7 @@ impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
impl AutomorphismKey<Vec<u8>> {
pub fn external_product_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_in: usize,
@@ -128,11 +131,12 @@ impl AutomorphismKey<Vec<u8>> {
where
Module<B>: GLWEExternalProductFamily<B>,
{
GLWESwitchingKey::external_product_scratch_space(module, basek, k_out, k_in, ggsw_k, digits, rank)
GLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, ggsw_k, digits, rank)
}
pub fn external_product_inplace_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
ggsw_k: usize,
@@ -142,7 +146,7 @@ impl AutomorphismKey<Vec<u8>> {
where
Module<B>: GLWEExternalProductFamily<B>,
{
GLWESwitchingKey::external_product_inplace_scratch_space(module, basek, k_out, ggsw_k, digits, rank)
GLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_out, ggsw_k, digits, rank)
}
}

View File

@@ -10,6 +10,7 @@ use crate::{
impl AutomorphismKey<Vec<u8>> {
pub fn keyswitch_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_in: usize,
@@ -20,11 +21,12 @@ impl AutomorphismKey<Vec<u8>> {
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWESwitchingKey::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank, rank)
GLWESwitchingKey::keyswitch_scratch_space(module, n, basek, k_out, k_in, k_ksk, digits, rank, rank)
}
pub fn keyswitch_inplace_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_ksk: usize,
@@ -34,7 +36,7 @@ impl AutomorphismKey<Vec<u8>> {
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWESwitchingKey::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank)
GLWESwitchingKey::keyswitch_inplace_scratch_space(module, n, basek, k_out, k_ksk, digits, rank)
}
}
@@ -68,6 +70,7 @@ impl<DataSelf: DataMut> AutomorphismKey<DataSelf> {
impl GLWESwitchingKey<Vec<u8>> {
pub fn keyswitch_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_in: usize,
@@ -79,11 +82,14 @@ impl GLWESwitchingKey<Vec<u8>> {
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWECiphertext::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out)
GLWECiphertext::keyswitch_scratch_space(
module, n, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out,
)
}
pub fn keyswitch_inplace_scratch_space<B: Backend>(
module: &Module<B>,
n: usize,
basek: usize,
k_out: usize,
k_ksk: usize,
@@ -93,7 +99,7 @@ impl GLWESwitchingKey<Vec<u8>> {
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWECiphertext::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank)
GLWECiphertext::keyswitch_inplace_scratch_space(module, n, basek, k_out, k_ksk, digits, rank)
}
}

View File

@@ -1,14 +1,15 @@
use backend::hal::{
api::{MatZnxAlloc, MatZnxAllocBytes, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo},
api::{FillUniform, Reset, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
layouts::{Backend, Data, DataMut, DataRef, MatZnx, ReaderFrom, WriterTo},
};
use crate::{GLWECiphertext, Infos};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
pub trait GGLWEExecLayoutFamily<B: Backend> = VmpPMatAlloc<B> + VmpPMatAllocBytes + VmpPMatPrepare<B>;
use std::fmt;
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct GGLWECiphertext<D: Data> {
pub(crate) data: MatZnx<D>,
pub(crate) basek: usize,
@@ -16,6 +17,40 @@ pub struct GGLWECiphertext<D: Data> {
pub(crate) digits: usize,
}
impl<D: DataRef> fmt::Debug for GGLWECiphertext<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataMut> FillUniform for GGLWECiphertext<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.data.fill_uniform(source);
}
}
impl<D: DataMut> Reset for GGLWECiphertext<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.data.reset();
self.basek = 0;
self.k = 0;
self.digits = 0;
}
}
impl<D: DataRef> fmt::Display for GGLWECiphertext<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GGLWECiphertext: basek={} k={} digits={}) {}",
self.basek, self.k, self.digits, self.data
)
}
}
impl<D: DataRef> GGLWECiphertext<D> {
pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
GLWECiphertext {
@@ -37,18 +72,7 @@ impl<D: DataMut> GGLWECiphertext<D> {
}
impl GGLWECiphertext<Vec<u8>> {
pub fn alloc<B: Backend>(
module: &Module<B>,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self {
let size: usize = k.div_ceil(basek);
debug_assert!(
size > digits,
@@ -66,25 +90,14 @@ impl GGLWECiphertext<Vec<u8>> {
);
Self {
data: module.mat_znx_alloc(rows, rank_in, rank_out + 1, size),
data: MatZnx::alloc(n, rows, rank_in, rank_out + 1, size),
basek: basek,
k,
digits,
}
}
pub fn bytes_of<B: Backend>(
module: &Module<B>,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> usize
where
Module<B>: MatZnxAllocBytes,
{
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize {
let size: usize = k.div_ceil(basek);
debug_assert!(
size > digits,
@@ -101,7 +114,7 @@ impl GGLWECiphertext<Vec<u8>> {
size
);
module.mat_znx_alloc_bytes(rows, rank_in, rank_out + 1, rows)
MatZnx::alloc_bytes(n, rows, rank_in, rank_out + 1, rows)
}
}
@@ -157,46 +170,57 @@ impl<D: DataRef> WriterTo for GGLWECiphertext<D> {
}
}
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct GLWESwitchingKey<D: Data> {
pub(crate) key: GGLWECiphertext<D>,
pub(crate) sk_in_n: usize, // Degree of sk_in
pub(crate) sk_out_n: usize, // Degree of sk_out
}
impl<D: DataRef> fmt::Debug for GLWESwitchingKey<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataRef> fmt::Display for GLWESwitchingKey<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GLWESwitchingKey: sk_in_n={} sk_out_n={}) {}",
self.sk_in_n, self.sk_out_n, self.key.data
)
}
}
impl<D: DataMut> FillUniform for GLWESwitchingKey<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.key.fill_uniform(source);
}
}
impl<D: DataMut> Reset for GLWESwitchingKey<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.key.reset();
self.sk_in_n = 0;
self.sk_out_n = 0;
}
}
impl GLWESwitchingKey<Vec<u8>> {
pub fn alloc<B: Backend>(
module: &Module<B>,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self {
GLWESwitchingKey {
key: GGLWECiphertext::alloc(module, basek, k, rows, digits, rank_in, rank_out),
key: GGLWECiphertext::alloc(n, basek, k, rows, digits, rank_in, rank_out),
sk_in_n: 0,
sk_out_n: 0,
}
}
pub fn bytes_of<B: Backend>(
module: &Module<B>,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> usize
where
Module<B>: MatZnxAllocBytes,
{
GGLWECiphertext::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, rank_in, rank_out)
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> usize {
GGLWECiphertext::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, rank_in, rank_out)
}
}
@@ -270,28 +294,50 @@ impl<D: DataRef> WriterTo for GLWESwitchingKey<D> {
}
}
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct AutomorphismKey<D: Data> {
pub(crate) key: GLWESwitchingKey<D>,
pub(crate) p: i64,
}
impl<D: DataRef> fmt::Debug for AutomorphismKey<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataMut> FillUniform for AutomorphismKey<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.key.fill_uniform(source);
}
}
impl<D: DataMut> Reset for AutomorphismKey<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.key.reset();
self.p = 0;
}
}
impl<D: DataRef> fmt::Display for AutomorphismKey<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "(AutomorphismKey: p={}) {}", self.p, self.key)
}
}
impl AutomorphismKey<Vec<u8>> {
pub fn alloc<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self {
AutomorphismKey {
key: GLWESwitchingKey::alloc(module, basek, k, rows, digits, rank, rank),
key: GLWESwitchingKey::alloc(n, basek, k, rows, digits, rank, rank),
p: 0,
}
}
pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
where
Module<B>: MatZnxAllocBytes,
{
GLWESwitchingKey::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, rank, rank)
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize {
GLWESwitchingKey::bytes_of(n, basek, k, rows, digits, rank, rank)
}
}
@@ -359,32 +405,59 @@ impl<D: DataRef> WriterTo for AutomorphismKey<D> {
}
}
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct GLWETensorKey<D: Data> {
pub(crate) keys: Vec<GLWESwitchingKey<D>>,
}
impl<D: DataRef> fmt::Debug for GLWETensorKey<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataMut> FillUniform for GLWETensorKey<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.keys
.iter_mut()
.for_each(|key: &mut GLWESwitchingKey<D>| key.fill_uniform(source))
}
}
impl<D: DataMut> Reset for GLWETensorKey<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.keys
.iter_mut()
.for_each(|key: &mut GLWESwitchingKey<D>| key.reset())
}
}
impl<D: DataRef> fmt::Display for GLWETensorKey<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "(GLWETensorKey)",)?;
for (i, key) in self.keys.iter().enumerate() {
write!(f, "{}: {}", i, key)?;
}
Ok(())
}
}
impl GLWETensorKey<Vec<u8>> {
pub fn alloc<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self {
let mut keys: Vec<GLWESwitchingKey<Vec<u8>>> = Vec::new();
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
(0..pairs).for_each(|_| {
keys.push(GLWESwitchingKey::alloc(
module, basek, k, rows, digits, 1, rank,
));
keys.push(GLWESwitchingKey::alloc(n, basek, k, rows, digits, 1, rank));
});
Self { keys: keys }
}
pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
where
Module<B>: MatZnxAllocBytes,
{
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize {
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
pairs * GLWESwitchingKey::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, 1, rank)
pairs * GLWESwitchingKey::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, 1, rank)
}
}

View File

@@ -1,12 +1,13 @@
use backend::hal::{
api::{MatZnxAlloc, MatZnxAllocBytes, VecZnxCopy, VecZnxFillUniform},
api::{FillUniform, Reset, VecZnxCopy, VecZnxFillUniform},
layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo},
};
use crate::{AutomorphismKey, Decompress, GGLWECiphertext, GLWECiphertextCompressed, GLWESwitchingKey, GLWETensorKey, Infos};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::fmt;
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct GGLWECiphertextCompressed<D: Data> {
pub(crate) data: MatZnx<D>,
pub(crate) basek: usize,
@@ -16,19 +17,44 @@ pub struct GGLWECiphertextCompressed<D: Data> {
pub(crate) seed: Vec<[u8; 32]>,
}
impl<D: DataRef> fmt::Debug for GGLWECiphertextCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataMut> FillUniform for GGLWECiphertextCompressed<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.data.fill_uniform(source);
}
}
impl<D: DataMut> Reset for GGLWECiphertextCompressed<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.data.reset();
self.basek = 0;
self.k = 0;
self.digits = 0;
self.rank_out = 0;
self.seed = Vec::new();
}
}
impl<D: DataRef> fmt::Display for GGLWECiphertextCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GGLWECiphertextCompressed: basek={} k={} digits={}) {}",
self.basek, self.k, self.digits, self.data
)
}
}
impl GGLWECiphertextCompressed<Vec<u8>> {
pub fn alloc<B: Backend>(
module: &Module<B>,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self {
let size: usize = k.div_ceil(basek);
debug_assert!(
size > digits,
@@ -46,7 +72,7 @@ impl GGLWECiphertextCompressed<Vec<u8>> {
);
Self {
data: module.mat_znx_alloc(rows, rank_in, 1, size),
data: MatZnx::alloc(n, rows, rank_in, 1, size),
basek: basek,
k,
rank_out,
@@ -55,10 +81,7 @@ impl GGLWECiphertextCompressed<Vec<u8>> {
}
}
pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize
where
Module<B>: MatZnxAllocBytes,
{
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize {
let size: usize = k.div_ceil(basek);
debug_assert!(
size > digits,
@@ -75,7 +98,7 @@ impl GGLWECiphertextCompressed<Vec<u8>> {
size
);
module.mat_znx_alloc_bytes(rows, rank_in, 1, rows)
MatZnx::alloc_bytes(n, rows, rank_in, 1, rows)
}
}
@@ -145,11 +168,9 @@ impl<D: DataMut> ReaderFrom for GGLWECiphertextCompressed<D> {
self.digits = reader.read_u64::<LittleEndian>()? as usize;
self.rank_out = reader.read_u64::<LittleEndian>()? as usize;
let seed_len = reader.read_u64::<LittleEndian>()? as usize;
if seed_len != self.seed.len() {
} else {
for s in &mut self.seed {
reader.read_exact(s)?;
}
self.seed = vec![[0u8; 32]; seed_len];
for s in &mut self.seed {
reader.read_exact(s)?;
}
self.data.read_from(reader)
}
@@ -228,13 +249,46 @@ impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GGLWECiphertextCompresse
}
}
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct GLWESwitchingKeyCompressed<D: Data> {
pub(crate) key: GGLWECiphertextCompressed<D>,
pub(crate) sk_in_n: usize, // Degree of sk_in
pub(crate) sk_out_n: usize, // Degree of sk_out
}
impl<D: DataRef> fmt::Debug for GLWESwitchingKeyCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataMut> FillUniform for GLWESwitchingKeyCompressed<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.key.fill_uniform(source);
}
}
impl<D: DataMut> Reset for GLWESwitchingKeyCompressed<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.key.reset();
self.sk_in_n = 0;
self.sk_out_n = 0;
}
}
impl<D: DataRef> fmt::Display for GLWESwitchingKeyCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(GLWESwitchingKeyCompressed: sk_in_n={} sk_out_n={}) {}",
self.sk_in_n, self.sk_out_n, self.key.data
)
}
}
impl<D: Data> Infos for GLWESwitchingKeyCompressed<D> {
type Inner = MatZnx<D>;
@@ -270,30 +324,16 @@ impl<D: Data> GLWESwitchingKeyCompressed<D> {
}
impl GLWESwitchingKeyCompressed<Vec<u8>> {
pub fn alloc<B: Backend>(
module: &Module<B>,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self {
GLWESwitchingKeyCompressed {
key: GGLWECiphertextCompressed::alloc(module, basek, k, rows, digits, rank_in, rank_out),
key: GGLWECiphertextCompressed::alloc(n, basek, k, rows, digits, rank_in, rank_out),
sk_in_n: 0,
sk_out_n: 0,
}
}
pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize
where
Module<B>: MatZnxAllocBytes,
{
GGLWECiphertextCompressed::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, rank_in)
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize) -> usize {
GGLWECiphertextCompressed::bytes_of(n, basek, k, rows, digits, rank_in)
}
}
@@ -327,28 +367,50 @@ impl<D: DataMut> GLWESwitchingKey<D> {
}
}
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct AutomorphismKeyCompressed<D: Data> {
pub(crate) key: GLWESwitchingKeyCompressed<D>,
pub(crate) p: i64,
}
impl<D: DataRef> fmt::Debug for AutomorphismKeyCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataMut> FillUniform for AutomorphismKeyCompressed<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.key.fill_uniform(source);
}
}
impl<D: DataMut> Reset for AutomorphismKeyCompressed<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.key.reset();
self.p = 0;
}
}
impl<D: DataRef> fmt::Display for AutomorphismKeyCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "(AutomorphismKeyCompressed: p={}) {}", self.p, self.key)
}
}
impl AutomorphismKeyCompressed<Vec<u8>> {
pub fn alloc<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self {
AutomorphismKeyCompressed {
key: GLWESwitchingKeyCompressed::alloc(module, basek, k, rows, digits, rank, rank),
key: GLWESwitchingKeyCompressed::alloc(n, basek, k, rows, digits, rank, rank),
p: 0,
}
}
pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
where
Module<B>: MatZnxAllocBytes,
{
GLWESwitchingKeyCompressed::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, rank)
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize {
GLWESwitchingKeyCompressed::<Vec<u8>>::bytes_of(n, basek, k, rows, digits, rank)
}
}
@@ -410,32 +472,61 @@ impl<D: DataMut> AutomorphismKey<D> {
}
}
#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Clone)]
pub struct GLWETensorKeyCompressed<D: Data> {
pub(crate) keys: Vec<GLWESwitchingKeyCompressed<D>>,
}
impl<D: DataRef> fmt::Debug for GLWETensorKeyCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: DataMut> FillUniform for GLWETensorKeyCompressed<D> {
fn fill_uniform(&mut self, source: &mut sampling::source::Source) {
self.keys
.iter_mut()
.for_each(|key: &mut GLWESwitchingKeyCompressed<D>| key.fill_uniform(source))
}
}
impl<D: DataMut> Reset for GLWETensorKeyCompressed<D>
where
MatZnx<D>: Reset,
{
fn reset(&mut self) {
self.keys
.iter_mut()
.for_each(|key: &mut GLWESwitchingKeyCompressed<D>| key.reset())
}
}
impl<D: DataRef> fmt::Display for GLWETensorKeyCompressed<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "(GLWETensorKeyCompressed)",)?;
for (i, key) in self.keys.iter().enumerate() {
write!(f, "{}: {}", i, key)?;
}
Ok(())
}
}
impl GLWETensorKeyCompressed<Vec<u8>> {
pub fn alloc<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: MatZnxAlloc,
{
pub fn alloc(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self {
let mut keys: Vec<GLWESwitchingKeyCompressed<Vec<u8>>> = Vec::new();
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
(0..pairs).for_each(|_| {
keys.push(GLWESwitchingKeyCompressed::alloc(
module, basek, k, rows, digits, 1, rank,
n, basek, k, rows, digits, 1, rank,
));
});
Self { keys: keys }
}
pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
where
Module<B>: MatZnxAllocBytes,
{
pub fn bytes_of(n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize {
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
pairs * GLWESwitchingKeyCompressed::<Vec<u8>>::bytes_of(module, basek, k, rows, digits, 1)
pairs * GLWESwitchingKeyCompressed::bytes_of(n, basek, k, rows, digits, 1)
}
}

View File

@@ -14,7 +14,16 @@ pub struct GGLWECiphertextExec<D: Data, B: Backend> {
}
impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
pub fn alloc(
module: &Module<B>,
n: usize,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> Self
where
Module<B>: GGLWEExecLayoutFamily<B>,
{
@@ -35,7 +44,7 @@ impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> {
);
Self {
data: module.vmp_pmat_alloc(rows, rank_in, rank_out + 1, size),
data: module.vmp_pmat_alloc(n, rows, rank_in, rank_out + 1, size),
basek: basek,
k,
digits,
@@ -44,6 +53,7 @@ impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> {
pub fn bytes_of(
module: &Module<B>,
n: usize,
basek: usize,
k: usize,
rows: usize,
@@ -70,7 +80,7 @@ impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> {
size
);
module.vmp_pmat_alloc_bytes(rows, rank_in, rank_out + 1, rows)
module.vmp_pmat_alloc_bytes(n, rows, rank_in, rank_out + 1, rows)
}
}
@@ -129,12 +139,21 @@ pub struct GLWESwitchingKeyExec<D: Data, B: Backend> {
}
impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize) -> Self
pub fn alloc(
module: &Module<B>,
n: usize,
basek: usize,
k: usize,
rows: usize,
digits: usize,
rank_in: usize,
rank_out: usize,
) -> Self
where
Module<B>: GGLWEExecLayoutFamily<B>,
{
GLWESwitchingKeyExec::<Vec<u8>, B> {
key: GGLWECiphertextExec::alloc(module, basek, k, rows, digits, rank_in, rank_out),
key: GGLWECiphertextExec::alloc(module, n, basek, k, rows, digits, rank_in, rank_out),
sk_in_n: 0,
sk_out_n: 0,
}
@@ -142,6 +161,7 @@ impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> {
pub fn bytes_of(
module: &Module<B>,
n: usize,
basek: usize,
k: usize,
rows: usize,
@@ -152,7 +172,7 @@ impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> {
where
Module<B>: GGLWEExecLayoutFamily<B>,
{
GGLWECiphertextExec::bytes_of(module, basek, k, rows, digits, rank_in, rank_out)
GGLWECiphertextExec::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out)
}
pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self
@@ -161,6 +181,7 @@ impl<B: Backend> GLWESwitchingKeyExec<Vec<u8>, B> {
{
let mut ksk_exec: GLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.n(),
other.basek(),
other.k(),
other.rows(),
@@ -234,21 +255,21 @@ pub struct AutomorphismKeyExec<D: Data, B: Backend> {
}
impl<B: Backend> AutomorphismKeyExec<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: GGLWEExecLayoutFamily<B>,
{
AutomorphismKeyExec::<Vec<u8>, B> {
key: GLWESwitchingKeyExec::alloc(module, basek, k, rows, digits, rank, rank),
key: GLWESwitchingKeyExec::alloc(module, n, basek, k, rows, digits, rank, rank),
p: 0,
}
}
pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
where
Module<B>: GGLWEExecLayoutFamily<B>,
{
GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, basek, k, rows, digits, rank, rank)
GLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, rank, rank)
}
pub fn from<DataOther: DataRef>(module: &Module<B>, other: &AutomorphismKey<DataOther>, scratch: &mut Scratch<B>) -> Self
@@ -257,6 +278,7 @@ impl<B: Backend> AutomorphismKeyExec<Vec<u8>, B> {
{
let mut atk_exec: AutomorphismKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.n(),
other.basek(),
other.k(),
other.rows(),
@@ -323,7 +345,7 @@ pub struct GLWETensorKeyExec<D: Data, B: Backend> {
}
impl<B: Backend> GLWETensorKeyExec<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: GGLWEExecLayoutFamily<B>,
{
@@ -331,18 +353,18 @@ impl<B: Backend> GLWETensorKeyExec<Vec<u8>, B> {
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
(0..pairs).for_each(|_| {
keys.push(GLWESwitchingKeyExec::alloc(
module, basek, k, rows, digits, 1, rank,
module, n, basek, k, rows, digits, 1, rank,
));
});
Self { keys }
}
pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
where
Module<B>: GGLWEExecLayoutFamily<B>,
{
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
pairs * GLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, basek, k, rows, digits, 1, rank)
pairs * GLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, 1, rank)
}
}

View File

@@ -1,5 +1,5 @@
use backend::hal::{
api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAlloc, VecZnxStd, VecZnxSubScalarInplace, ZnxZero},
api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxStd, VecZnxSubScalarInplace, ZnxZero},
layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned},
oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl},
};
@@ -16,15 +16,20 @@ impl<D: DataRef> GGLWECiphertext<D> {
) where
DataSk: DataRef,
DataWant: DataRef,
Module<B>: GLWEDecryptFamily<B> + VecZnxStd + VecZnxAlloc + VecZnxSubScalarInplace,
Module<B>: GLWEDecryptFamily<B> + VecZnxStd + VecZnxSubScalarInplace,
B: TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>,
{
let digits: usize = self.digits();
let basek: usize = self.basek();
let k: usize = self.k();
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, basek, k));
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(
module,
self.n(),
basek,
k,
));
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self.n(), basek, k);
(0..self.rank_in()).for_each(|col_i| {
(0..self.rows()).for_each(|row_i| {

View File

@@ -0,0 +1,54 @@
use backend::hal::tests::serialization::test_reader_writer_interface;
use crate::{
AutomorphismKey, AutomorphismKeyCompressed, GGLWECiphertext, GGLWECiphertextCompressed, GLWESwitchingKey,
GLWESwitchingKeyCompressed, GLWETensorKey, GLWETensorKeyCompressed,
};
#[test]
fn test_gglwe_serialization() {
let original: GGLWECiphertext<Vec<u8>> = GGLWECiphertext::alloc(1024, 12, 54, 3, 1, 2, 2);
test_reader_writer_interface(original);
}
#[test]
fn test_gglwe_serialization_compressed() {
let original: GGLWECiphertextCompressed<Vec<u8>> = GGLWECiphertextCompressed::alloc(1024, 12, 54, 3, 1, 2, 2);
test_reader_writer_interface(original);
}
#[test]
fn test_glwe_switching_key_serialization() {
let original: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(1024, 12, 54, 3, 1, 2, 2);
test_reader_writer_interface(original);
}
#[test]
fn test_glwe_switching_key_serialization_compressed() {
let original: GLWESwitchingKeyCompressed<Vec<u8>> = GLWESwitchingKeyCompressed::alloc(1024, 12, 54, 3, 1, 2, 2);
test_reader_writer_interface(original);
}
#[test]
fn test_automorphism_key_serialization() {
let original: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(1024, 12, 54, 3, 1, 2);
test_reader_writer_interface(original);
}
#[test]
fn test_automorphism_key_serialization_compressed() {
let original: AutomorphismKeyCompressed<Vec<u8>> = AutomorphismKeyCompressed::alloc(1024, 12, 54, 3, 1, 2);
test_reader_writer_interface(original);
}
#[test]
fn test_tensor_key_serialization() {
let original: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(1024, 12, 54, 3, 1, 2);
test_reader_writer_interface(original);
}
#[test]
fn test_tensor_key_serialization_compressed() {
let original: GLWETensorKeyCompressed<Vec<u8>> = GLWETensorKeyCompressed::alloc(1024, 12, 54, 3, 1, 2);
test_reader_writer_interface(original);
}

View File

@@ -1,8 +1,7 @@
use backend::hal::{
api::{
MatZnxAlloc, ScalarZnxAlloc, ScalarZnxAllocBytes, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace,
VecZnxAlloc, VecZnxAllocBytes, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy, VecZnxStd,
VecZnxSubScalarInplace, VecZnxSwithcDegree,
ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxCopy,
VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree,
},
layouts::{Backend, Module, ScratchOwned},
oep::{
@@ -18,19 +17,14 @@ use crate::{
noise::log2_std_noise_gglwe_product,
};
pub(crate) trait AutomorphismTestModuleFamily<B: Backend> = MatZnxAlloc
+ AutomorphismKeyEncryptSkFamily<B>
+ ScalarZnxAllocBytes
+ VecZnxAllocBytes
pub(crate) trait AutomorphismTestModuleFamily<B: Backend> = AutomorphismKeyEncryptSkFamily<B>
+ GLWEKeyswitchFamily<B>
+ ScalarZnxAlloc
+ VecZnxAutomorphism
+ GGLWEExecLayoutFamily<B>
+ VecZnxSwithcDegree
+ VecZnxAddScalarInplace
+ VecZnxAutomorphism
+ VecZnxAutomorphismInplace
+ VecZnxAlloc
+ GLWEDecryptFamily<B>
+ VecZnxSubScalarInplace
+ VecZnxStd
@@ -55,19 +49,20 @@ pub(crate) fn test_automorphisk_key_encrypt_sk<B: Backend>(
Module<B>: AutomorphismTestModuleFamily<B>,
B: AutomorphismTestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(module, basek, k_ksk, rows, digits, rank);
let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space(
module, basek, k_ksk, rank,
module, n, basek, k_ksk, rank,
));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk.fill_ternary_prob(0.5, &mut source_xs);
let p = -5;
@@ -110,19 +105,20 @@ pub(crate) fn test_automorphisk_key_encrypt_sk_compressed<B: Backend>(
Module<B>: AutomorphismTestModuleFamily<B>,
B: AutomorphismTestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
let mut atk_compressed: AutomorphismKeyCompressed<Vec<u8>> =
AutomorphismKeyCompressed::alloc(module, basek, k_ksk, rows, digits, rank);
AutomorphismKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_scratch_space(
module, basek, k_ksk, rank,
module, n, basek, k_ksk, rank,
));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk.fill_ternary_prob(0.5, &mut source_xs);
let p = -5;
@@ -151,7 +147,7 @@ pub(crate) fn test_automorphisk_key_encrypt_sk_compressed<B: Backend>(
});
let sk_out_exec = GLWESecretExec::from(module, &sk_out);
let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(module, basek, k_ksk, rows, digits, rank);
let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_ksk, rows, digits, rank);
atk.decompress(module, &atk_compressed);
atk.key
@@ -174,30 +170,31 @@ pub(crate) fn test_gglwe_automorphism<B: Backend>(
Module<B>: AutomorphismTestModuleFamily<B>,
B: AutomorphismTestScratchFamily<B>,
{
let n: usize = module.n();
let digits_in: usize = 1;
let rows_in: usize = k_in / (basek * digits);
let rows_apply: usize = k_in.div_ceil(basek * digits);
let mut auto_key_in: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(&module, basek, k_in, rows_in, digits_in, rank);
let mut auto_key_out: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(&module, basek, k_out, rows_in, digits_in, rank);
let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(&module, basek, k_apply, rows_apply, digits, rank);
let mut auto_key_in: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank);
let mut auto_key_out: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_out, rows_in, digits_in, rank);
let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
AutomorphismKey::encrypt_sk_scratch_space(&module, basek, k_apply, rank)
| AutomorphismKey::automorphism_scratch_space(&module, basek, k_out, k_in, k_apply, digits, rank),
AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank)
| AutomorphismKey::automorphism_scratch_space(module, n, basek, k_out, k_in, k_apply, digits, rank),
);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, rank);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk.fill_ternary_prob(0.5, &mut source_xs);
// gglwe_{s1}(s0) = s0 -> s1
auto_key_in.encrypt_sk(
&module,
module,
p0,
&sk,
&mut source_xa,
@@ -208,7 +205,7 @@ pub(crate) fn test_gglwe_automorphism<B: Backend>(
// gglwe_{s2}(s1) -> s1 -> s2
auto_key_apply.encrypt_sk(
&module,
module,
p1,
&sk,
&mut source_xa,
@@ -218,21 +215,16 @@ pub(crate) fn test_gglwe_automorphism<B: Backend>(
);
let mut auto_key_apply_exec: AutomorphismKeyExec<Vec<u8>, B> =
AutomorphismKeyExec::alloc(&module, basek, k_apply, rows_apply, digits, rank);
AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank);
auto_key_apply_exec.prepare(&module, &auto_key_apply, scratch.borrow());
auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow());
// gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0)
auto_key_out.automorphism(
&module,
&auto_key_in,
&auto_key_apply_exec,
scratch.borrow(),
);
auto_key_out.automorphism(module, &auto_key_in, &auto_key_apply_exec, scratch.borrow());
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_out);
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_out);
let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, rank);
let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk
(0..rank).for_each(|i| {
module.vec_znx_automorphism(
@@ -244,13 +236,13 @@ pub(crate) fn test_gglwe_automorphism<B: Backend>(
);
});
let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(&module, &sk_auto);
let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto);
(0..auto_key_out.rank_in()).for_each(|col_i| {
(0..auto_key_out.rows()).for_each(|row_i| {
auto_key_out
.at(row_i, col_i)
.decrypt(&module, &mut pt, &sk_auto_dft, scratch.borrow());
.decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow());
module.vec_znx_sub_scalar_inplace(
&mut pt.data,
@@ -262,7 +254,7 @@ pub(crate) fn test_gglwe_automorphism<B: Backend>(
let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2();
let noise_want: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
n as f64,
basek * digits,
0.5,
0.5,
@@ -298,29 +290,30 @@ pub(crate) fn test_gglwe_automorphism_inplace<B: Backend>(
Module<B>: AutomorphismTestModuleFamily<B>,
B: AutomorphismTestScratchFamily<B>,
{
let n: usize = module.n();
let digits_in: usize = 1;
let rows_in: usize = k_in / (basek * digits);
let rows_apply: usize = k_in.div_ceil(basek * digits);
let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(&module, basek, k_in, rows_in, digits_in, rank);
let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(&module, basek, k_apply, rows_apply, digits, rank);
let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_in, rows_in, digits_in, rank);
let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc(n, basek, k_apply, rows_apply, digits, rank);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
AutomorphismKey::encrypt_sk_scratch_space(&module, basek, k_apply, rank)
| AutomorphismKey::automorphism_inplace_scratch_space(&module, basek, k_in, k_apply, digits, rank),
AutomorphismKey::encrypt_sk_scratch_space(module, n, basek, k_apply, rank)
| AutomorphismKey::automorphism_inplace_scratch_space(module, n, basek, k_in, k_apply, digits, rank),
);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, rank);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk.fill_ternary_prob(0.5, &mut source_xs);
// gglwe_{s1}(s0) = s0 -> s1
auto_key.encrypt_sk(
&module,
module,
p0,
&sk,
&mut source_xa,
@@ -331,7 +324,7 @@ pub(crate) fn test_gglwe_automorphism_inplace<B: Backend>(
// gglwe_{s2}(s1) -> s1 -> s2
auto_key_apply.encrypt_sk(
&module,
module,
p1,
&sk,
&mut source_xa,
@@ -341,16 +334,16 @@ pub(crate) fn test_gglwe_automorphism_inplace<B: Backend>(
);
let mut auto_key_apply_exec: AutomorphismKeyExec<Vec<u8>, B> =
AutomorphismKeyExec::alloc(&module, basek, k_apply, rows_apply, digits, rank);
AutomorphismKeyExec::alloc(module, n, basek, k_apply, rows_apply, digits, rank);
auto_key_apply_exec.prepare(&module, &auto_key_apply, scratch.borrow());
auto_key_apply_exec.prepare(module, &auto_key_apply, scratch.borrow());
// gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0)
auto_key.automorphism_inplace(&module, &auto_key_apply_exec, scratch.borrow());
auto_key.automorphism_inplace(module, &auto_key_apply_exec, scratch.borrow());
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_in);
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_in);
let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, rank);
let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk
(0..rank).for_each(|i| {
@@ -363,13 +356,13 @@ pub(crate) fn test_gglwe_automorphism_inplace<B: Backend>(
);
});
let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(&module, &sk_auto);
let sk_auto_dft: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_auto);
(0..auto_key.rank_in()).for_each(|col_i| {
(0..auto_key.rows()).for_each(|row_i| {
auto_key
.at(row_i, col_i)
.decrypt(&module, &mut pt, &sk_auto_dft, scratch.borrow());
.decrypt(module, &mut pt, &sk_auto_dft, scratch.borrow());
module.vec_znx_sub_scalar_inplace(
&mut pt.data,
0,
@@ -380,7 +373,7 @@ pub(crate) fn test_gglwe_automorphism_inplace<B: Backend>(
let noise_have: f64 = module.vec_znx_std(basek, &pt.data, 0).log2();
let noise_want: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
n as f64,
basek * digits,
0.5,
0.5,

View File

@@ -1,8 +1,7 @@
use backend::hal::{
api::{
MatZnxAlloc, ScalarZnxAlloc, ScalarZnxAllocBytes, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace,
VecZnxAlloc, VecZnxAllocBytes, VecZnxCopy, VecZnxRotateInplace, VecZnxStd, VecZnxSubScalarInplace, VecZnxSwithcDegree,
ZnxViewMut,
ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxCopy, VecZnxRotateInplace, VecZnxStd,
VecZnxSubScalarInplace, VecZnxSwithcDegree, ZnxViewMut,
},
layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned},
oep::{
@@ -21,14 +20,9 @@ use crate::{
pub(crate) trait TestModuleFamily<B: Backend> = GGLWEEncryptSkFamily<B>
+ GLWEDecryptFamily<B>
+ MatZnxAlloc
+ ScalarZnxAlloc
+ ScalarZnxAllocBytes
+ VecZnxAllocBytes
+ VecZnxSwithcDegree
+ VecZnxAddScalarInplace
+ VecZnxStd
+ VecZnxAlloc
+ VecZnxSubScalarInplace
+ VecZnxCopy;
@@ -56,22 +50,23 @@ pub(crate) fn test_gglwe_encrypt_sk<B: Backend>(
Module<B>: TestModuleFamily<B>,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(module, basek, k_ksk, rows, digits, rank_in, rank_out);
let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space(
module, basek, k_ksk, rank_in, rank_out,
module, n, basek, k_ksk, rank_in, rank_out,
));
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_in);
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
sk_in.fill_ternary_prob(0.5, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
sk_out.fill_ternary_prob(0.5, &mut source_xs);
let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out);
@@ -101,22 +96,23 @@ pub(crate) fn test_gglwe_encrypt_sk_compressed<B: Backend>(
Module<B>: TestModuleFamily<B>,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = (k_ksk - digits * basek) / (digits * basek);
let mut ksk_compressed: GLWESwitchingKeyCompressed<Vec<u8>> =
GLWESwitchingKeyCompressed::alloc(module, basek, k_ksk, rows, digits, rank_in, rank_out);
GLWESwitchingKeyCompressed::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKeyCompressed::encrypt_sk_scratch_space(
module, basek, k_ksk, rank_in, rank_out,
module, n, basek, k_ksk, rank_in, rank_out,
));
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_in);
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
sk_in.fill_ternary_prob(0.5, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
sk_out.fill_ternary_prob(0.5, &mut source_xs);
let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out);
@@ -132,7 +128,7 @@ pub(crate) fn test_gglwe_encrypt_sk_compressed<B: Backend>(
scratch.borrow(),
);
let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(module, basek, k_ksk, rows, digits, rank_in, rank_out);
let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_in, rank_out);
ksk.decompress(module, &ksk_compressed);
ksk.key
@@ -155,29 +151,16 @@ pub(crate) fn test_gglwe_keyswitch<B: Backend>(
TestModuleFamily<B> + GGLWEEncryptSkFamily<B> + GLWEDecryptFamily<B> + GLWEKeyswitchFamily<B> + GGLWEExecLayoutFamily<B>,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = k_in.div_ceil(basek * digits);
let digits_in: usize = 1;
let mut ct_gglwe_s0s1: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(
module,
basek,
k_in,
rows,
digits_in,
rank_in_s0s1,
rank_out_s0s1,
);
let mut ct_gglwe_s1s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(
module,
basek,
k_ksk,
rows,
digits,
rank_out_s0s1,
rank_out_s1s2,
);
let mut ct_gglwe_s0s1: GLWESwitchingKey<Vec<u8>> =
GLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in_s0s1, rank_out_s0s1);
let mut ct_gglwe_s1s2: GLWESwitchingKey<Vec<u8>> =
GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out_s0s1, rank_out_s1s2);
let mut ct_gglwe_s0s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(
module,
n,
basek,
k_out,
rows,
@@ -192,6 +175,7 @@ pub(crate) fn test_gglwe_keyswitch<B: Backend>(
let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space(
module,
n,
basek,
k_ksk,
rank_in_s0s1 | rank_out_s0s1,
@@ -199,6 +183,7 @@ pub(crate) fn test_gglwe_keyswitch<B: Backend>(
));
let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::keyswitch_scratch_space(
module,
n,
basek,
k_out,
k_in,
@@ -208,13 +193,13 @@ pub(crate) fn test_gglwe_keyswitch<B: Backend>(
ct_gglwe_s1s2.rank_out(),
));
let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_in_s0s1);
let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in_s0s1);
sk0.fill_ternary_prob(0.5, &mut source_xs);
let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out_s0s1);
let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s0s1);
sk1.fill_ternary_prob(0.5, &mut source_xs);
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out_s1s2);
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out_s1s2);
sk2.fill_ternary_prob(0.5, &mut source_xs);
let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2);
@@ -252,7 +237,7 @@ pub(crate) fn test_gglwe_keyswitch<B: Backend>(
);
let max_noise: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
n as f64,
basek * digits,
0.5,
0.5,
@@ -286,13 +271,13 @@ pub(crate) fn test_gglwe_keyswitch_inplace<B: Backend>(
+ GLWEDecryptFamily<B>,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = k_ct.div_ceil(basek * digits);
let digits_in: usize = 1;
let mut ct_gglwe_s0s1: GLWESwitchingKey<Vec<u8>> =
GLWESwitchingKey::alloc(module, basek, k_ct, rows, digits_in, rank_in, rank_out);
let mut ct_gglwe_s1s2: GLWESwitchingKey<Vec<u8>> =
GLWESwitchingKey::alloc(module, basek, k_ksk, rows, digits, rank_out, rank_out);
GLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out);
let mut ct_gglwe_s1s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ksk, rows, digits, rank_out, rank_out);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
@@ -300,24 +285,25 @@ pub(crate) fn test_gglwe_keyswitch_inplace<B: Backend>(
let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_scratch_space(
module,
n,
basek,
k_ksk,
rank_in | rank_out,
rank_out,
));
let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::keyswitch_inplace_scratch_space(
module, basek, k_ct, k_ksk, digits, rank_out,
module, n, basek, k_ct, k_ksk, digits, rank_out,
));
let var_xs: f64 = 0.5;
let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_in);
let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
sk0.fill_ternary_prob(var_xs, &mut source_xs);
let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out);
let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
sk1.fill_ternary_prob(var_xs, &mut source_xs);
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out);
let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
sk2.fill_ternary_prob(var_xs, &mut source_xs);
let sk2_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk2);
@@ -352,7 +338,7 @@ pub(crate) fn test_gglwe_keyswitch_inplace<B: Backend>(
let ct_gglwe_s0s2: GLWESwitchingKey<Vec<u8>> = ct_gglwe_s0s1;
let max_noise: f64 = log2_std_noise_gglwe_product(
module.n() as f64,
n as f64,
basek * digits,
var_xs,
var_xs,
@@ -388,25 +374,25 @@ pub(crate) fn test_gglwe_external_product<B: Backend>(
+ VecZnxRotateInplace,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = k_in.div_ceil(basek * digits);
let digits_in: usize = 1;
let mut ct_gglwe_in: GLWESwitchingKey<Vec<u8>> =
GLWESwitchingKey::alloc(module, basek, k_in, rows, digits_in, rank_in, rank_out);
let mut ct_gglwe_in: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_in, rows, digits_in, rank_in, rank_out);
let mut ct_gglwe_out: GLWESwitchingKey<Vec<u8>> =
GLWESwitchingKey::alloc(module, basek, k_out, rows, digits_in, rank_in, rank_out);
let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(module, basek, k_ggsw, rows, digits, rank_out);
GLWESwitchingKey::alloc(n, basek, k_out, rows, digits_in, rank_in, rank_out);
let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out);
let mut pt_rgsw: ScalarZnx<Vec<u8>> = module.scalar_znx_alloc(1);
let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
GLWESwitchingKey::encrypt_sk_scratch_space(module, basek, k_in, rank_in, rank_out)
| GLWESwitchingKey::external_product_scratch_space(module, basek, k_out, k_in, k_ggsw, digits, rank_out)
| GGSWCiphertext::encrypt_sk_scratch_space(module, basek, k_ggsw, rank_out),
GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_in, rank_in, rank_out)
| GLWESwitchingKey::external_product_scratch_space(module, n, basek, k_out, k_in, k_ggsw, digits, rank_out)
| GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out),
);
let r: usize = 1;
@@ -415,10 +401,10 @@ pub(crate) fn test_gglwe_external_product<B: Backend>(
let var_xs: f64 = 0.5;
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_in);
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
sk_in.fill_ternary_prob(var_xs, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
sk_out.fill_ternary_prob(var_xs, &mut source_xs);
let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out);
@@ -444,7 +430,7 @@ pub(crate) fn test_gglwe_external_product<B: Backend>(
);
let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> =
GGSWCiphertextExec::alloc(module, basek, k_ggsw, rows, digits, rank_out);
GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out);
ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow());
@@ -458,12 +444,12 @@ pub(crate) fn test_gglwe_external_product<B: Backend>(
let var_gct_err_lhs: f64 = sigma * sigma;
let var_gct_err_rhs: f64 = 0f64;
let var_msg: f64 = 1f64 / module.n() as f64; // X^{k}
let var_msg: f64 = 1f64 / n as f64; // X^{k}
let var_a0_err: f64 = sigma * sigma;
let var_a1_err: f64 = 1f64 / 12f64;
let max_noise: f64 = noise_ggsw_product(
module.n() as f64,
n as f64,
basek * digits,
var_xs,
var_msg,
@@ -499,24 +485,24 @@ pub(crate) fn test_gglwe_external_product_inplace<B: Backend>(
+ VecZnxRotateInplace,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = k_ct.div_ceil(basek * digits);
let digits_in: usize = 1;
let mut ct_gglwe: GLWESwitchingKey<Vec<u8>> =
GLWESwitchingKey::alloc(module, basek, k_ct, rows, digits_in, rank_in, rank_out);
let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(module, basek, k_ggsw, rows, digits, rank_out);
let mut ct_gglwe: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(n, basek, k_ct, rows, digits_in, rank_in, rank_out);
let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(n, basek, k_ggsw, rows, digits, rank_out);
let mut pt_rgsw: ScalarZnx<Vec<u8>> = module.scalar_znx_alloc(1);
let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut source_xa: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
GLWESwitchingKey::encrypt_sk_scratch_space(module, basek, k_ct, rank_in, rank_out)
| GLWESwitchingKey::external_product_inplace_scratch_space(module, basek, k_ct, k_ggsw, digits, rank_out)
| GGSWCiphertext::encrypt_sk_scratch_space(module, basek, k_ggsw, rank_out),
GLWESwitchingKey::encrypt_sk_scratch_space(module, n, basek, k_ct, rank_in, rank_out)
| GLWESwitchingKey::external_product_inplace_scratch_space(module, n, basek, k_ct, k_ggsw, digits, rank_out)
| GGSWCiphertext::encrypt_sk_scratch_space(module, n, basek, k_ggsw, rank_out),
);
let r: usize = 1;
@@ -525,10 +511,10 @@ pub(crate) fn test_gglwe_external_product_inplace<B: Backend>(
let var_xs: f64 = 0.5;
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_in);
let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_in);
sk_in.fill_ternary_prob(var_xs, &mut source_xs);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank_out);
let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank_out);
sk_out.fill_ternary_prob(var_xs, &mut source_xs);
let sk_out_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk_out);
@@ -554,7 +540,7 @@ pub(crate) fn test_gglwe_external_product_inplace<B: Backend>(
);
let mut ct_rgsw_exec: GGSWCiphertextExec<Vec<u8>, B> =
GGSWCiphertextExec::alloc(module, basek, k_ggsw, rows, digits, rank_out);
GGSWCiphertextExec::alloc(module, n, basek, k_ggsw, rows, digits, rank_out);
ct_rgsw_exec.prepare(module, &ct_rgsw, scratch.borrow());
@@ -568,12 +554,12 @@ pub(crate) fn test_gglwe_external_product_inplace<B: Backend>(
let var_gct_err_lhs: f64 = sigma * sigma;
let var_gct_err_rhs: f64 = 0f64;
let var_msg: f64 = 1f64 / module.n() as f64; // X^{k}
let var_msg: f64 = 1f64 / n as f64; // X^{k}
let var_a0_err: f64 = sigma * sigma;
let var_a1_err: f64 = 1f64 / 12f64;
let max_noise: f64 = noise_ggsw_product(
module.n() as f64,
n as f64,
basek * digits,
var_xs,
var_msg,

View File

@@ -1,8 +1,7 @@
use backend::hal::{
api::{
MatZnxAlloc, ScalarZnxAlloc, ScalarZnxAllocBytes, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace,
VecZnxAlloc, VecZnxAllocBytes, VecZnxBigAlloc, VecZnxCopy, VecZnxDftAlloc, VecZnxStd, VecZnxSubScalarInplace,
VecZnxSwithcDegree,
ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxCopy, VecZnxDftAlloc, VecZnxStd,
VecZnxSubScalarInplace, VecZnxSwithcDegree,
},
layouts::{Backend, Module, ScratchOwned, VecZnxDft},
oep::{
@@ -19,14 +18,9 @@ use crate::{
pub(crate) trait TestModuleFamily<B: Backend> = GGLWEEncryptSkFamily<B>
+ GLWEDecryptFamily<B>
+ MatZnxAlloc
+ ScalarZnxAlloc
+ ScalarZnxAllocBytes
+ VecZnxAllocBytes
+ VecZnxSwithcDegree
+ VecZnxAddScalarInplace
+ VecZnxStd
+ VecZnxAlloc
+ VecZnxSubScalarInplace;
pub(crate) trait TestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B>
@@ -51,9 +45,10 @@ where
+ VecZnxBigAlloc<B>,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = k / basek;
let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(&module, basek, k, rows, 1, rank);
let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
@@ -61,14 +56,15 @@ where
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWETensorKey::encrypt_sk_scratch_space(
module,
n,
basek,
tensor_key.k(),
rank,
));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, rank);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk.fill_ternary_prob(0.5, &mut source_xs);
let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(&module, &sk);
let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
sk_exec.prepare(module, &sk);
tensor_key.encrypt_sk(
@@ -80,12 +76,12 @@ where
scratch.borrow(),
);
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k);
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
let mut sk_ij_dft = module.vec_znx_dft_alloc(1, 1);
let mut sk_ij_big = module.vec_znx_big_alloc(1, 1);
let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, 1);
let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(rank, 1);
let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
(0..rank).for_each(|i| {
module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
@@ -108,7 +104,7 @@ where
tensor_key
.at(i, j)
.at(row_i, col_i)
.decrypt(&module, &mut pt, &sk_exec, scratch.borrow());
.decrypt(module, &mut pt, &sk_exec, scratch.borrow());
module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);
@@ -136,24 +132,25 @@ pub(crate) fn test_tensor_key_encrypt_sk_compressed<B: Backend>(
+ VecZnxCopy,
B: TestScratchFamily<B>,
{
let n: usize = module.n();
let rows: usize = k / basek;
let mut tensor_key_compressed: GLWETensorKeyCompressed<Vec<u8>> =
GLWETensorKeyCompressed::alloc(&module, basek, k, rows, 1, rank);
let mut tensor_key_compressed: GLWETensorKeyCompressed<Vec<u8>> = GLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank);
let mut source_xs: Source = Source::new([0u8; 32]);
let mut source_xe: Source = Source::new([0u8; 32]);
let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWETensorKeyCompressed::encrypt_sk_scratch_space(
module,
n,
basek,
tensor_key_compressed.k(),
rank,
));
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, rank);
let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
sk.fill_ternary_prob(0.5, &mut source_xs);
let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(&module, &sk);
let mut sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
sk_exec.prepare(module, &sk);
let seed_xa: [u8; 32] = [1u8; 32];
@@ -167,15 +164,15 @@ pub(crate) fn test_tensor_key_encrypt_sk_compressed<B: Backend>(
scratch.borrow(),
);
let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(&module, basek, k, rows, 1, rank);
let mut tensor_key: GLWETensorKey<Vec<u8>> = GLWETensorKey::alloc(n, basek, k, rows, 1, rank);
tensor_key.decompress(module, &tensor_key_compressed);
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k);
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
let mut sk_ij_dft = module.vec_znx_dft_alloc(1, 1);
let mut sk_ij_big = module.vec_znx_big_alloc(1, 1);
let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(&module, 1);
let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(rank, 1);
let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
(0..rank).for_each(|i| {
module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
@@ -198,7 +195,7 @@ pub(crate) fn test_tensor_key_encrypt_sk_compressed<B: Backend>(
tensor_key
.at(i, j)
.at(row_i, col_i)
.decrypt(&module, &mut pt, &sk_exec, scratch.borrow());
.decrypt(module, &mut pt, &sk_exec, scratch.borrow());
module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);

View File

@@ -1,4 +1,5 @@
mod cpu_spqlios;
mod generic_serialization;
mod generics_automorphism_key;
mod generics_gglwe;
mod generics_tensor_key;