mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
Various fixes
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
use backend::{
|
use backend::{
|
||||||
FFT64, MatZnxDftOps, MatZnxDftScratch, Module, ScalarZnxDft, ScalarZnxDftAlloc, ScalarZnxDftOps,
|
FFT64, MatZnxDftOps, MatZnxDftScratch, Module, ScalarZnxDft, ScalarZnxDftAlloc, ScalarZnxDftOps, Scratch, VecZnxAlloc,
|
||||||
Scratch, VecZnxAlloc, VecZnxBigAlloc, VecZnxBigOps, VecZnxBigScratch, VecZnxDftAlloc, VecZnxDftOps, VecZnxOps, ZnxView,
|
VecZnxBigAlloc, VecZnxBigOps, VecZnxBigScratch, VecZnxDftAlloc, VecZnxDftOps, VecZnxOps, ZnxView, ZnxViewMut, ZnxZero,
|
||||||
ZnxViewMut, ZnxZero,
|
|
||||||
};
|
};
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.set_basek(a.basek());
|
self.set_basek(a.basek());
|
||||||
self.set_k(set_k(self, a, b));
|
self.set_k(set_k_binary(self, a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_inplace<A>(&mut self, module: &Module<FFT64>, a: &A)
|
fn add_inplace<A>(&mut self, module: &Module<FFT64>, a: &A)
|
||||||
@@ -69,9 +69,7 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
module.vec_znx_add_inplace(&mut self_mut.data, i, &a_ref.data, i);
|
module.vec_znx_add_inplace(&mut self_mut.data, i, &a_ref.data, i);
|
||||||
});
|
});
|
||||||
|
|
||||||
if a.rank() != 0 {
|
self.set_k(set_k_unary(self, a))
|
||||||
self.set_k(a.k().min(self.k()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub<A, B>(&mut self, module: &Module<FFT64>, a: &A, b: &B)
|
fn sub<A, B>(&mut self, module: &Module<FFT64>, a: &A, b: &B)
|
||||||
@@ -119,7 +117,7 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.set_basek(a.basek());
|
self.set_basek(a.basek());
|
||||||
self.set_k(set_k(self, a, b));
|
self.set_k(set_k_binary(self, a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_inplace_ab<A>(&mut self, module: &Module<FFT64>, a: &A)
|
fn sub_inplace_ab<A>(&mut self, module: &Module<FFT64>, a: &A)
|
||||||
@@ -141,9 +139,7 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
module.vec_znx_sub_ab_inplace(&mut self_mut.data, i, &a_ref.data, i);
|
module.vec_znx_sub_ab_inplace(&mut self_mut.data, i, &a_ref.data, i);
|
||||||
});
|
});
|
||||||
|
|
||||||
if a.rank() != 0 {
|
self.set_k(set_k_unary(self, a))
|
||||||
self.set_k(a.k().min(self.k()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub_inplace_ba<A>(&mut self, module: &Module<FFT64>, a: &A)
|
fn sub_inplace_ba<A>(&mut self, module: &Module<FFT64>, a: &A)
|
||||||
@@ -165,9 +161,7 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
module.vec_znx_sub_ba_inplace(&mut self_mut.data, i, &a_ref.data, i);
|
module.vec_znx_sub_ba_inplace(&mut self_mut.data, i, &a_ref.data, i);
|
||||||
});
|
});
|
||||||
|
|
||||||
if a.rank() != 0 {
|
self.set_k(set_k_unary(self, a))
|
||||||
self.set_k(a.k().min(self.k()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rotate<A>(&mut self, module: &Module<FFT64>, k: i64, a: &A)
|
fn rotate<A>(&mut self, module: &Module<FFT64>, k: i64, a: &A)
|
||||||
@@ -189,9 +183,7 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.set_basek(a.basek());
|
self.set_basek(a.basek());
|
||||||
if a.rank() != 0 {
|
self.set_k(set_k_unary(self, a))
|
||||||
self.set_k(a.k().min(self.k()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rotate_inplace(&mut self, module: &Module<FFT64>, k: i64) {
|
fn rotate_inplace(&mut self, module: &Module<FFT64>, k: i64) {
|
||||||
@@ -216,8 +208,6 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
assert_eq!(self.n(), module.n());
|
assert_eq!(self.n(), module.n());
|
||||||
assert_eq!(a.n(), module.n());
|
assert_eq!(a.n(), module.n());
|
||||||
assert_eq!(self.rank(), a.rank());
|
assert_eq!(self.rank(), a.rank());
|
||||||
assert_eq!(self.k(), a.k());
|
|
||||||
assert_eq!(self.basek(), a.basek());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
|
let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
|
||||||
@@ -227,7 +217,7 @@ pub trait GLWEOps: GLWECiphertextToMut + SetMetaData + Sized {
|
|||||||
module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
|
module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.set_k(a.k());
|
self.set_k(a.k().min(self.size() * self.basek()));
|
||||||
self.set_basek(a.basek());
|
self.set_basek(a.basek());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,17 +267,31 @@ impl GLWECiphertext<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// c = op(a, b)
|
// c = op(a, b)
|
||||||
fn set_k(c: &impl Infos, a: &impl Infos, b: &impl Infos) -> usize {
|
fn set_k_binary(c: &impl Infos, a: &impl Infos, b: &impl Infos) -> usize {
|
||||||
|
// If either operands is a ciphertext
|
||||||
if a.rank() != 0 || b.rank() != 0 {
|
if a.rank() != 0 || b.rank() != 0 {
|
||||||
|
// If a is a plaintext (but b ciphertext)
|
||||||
let k = if a.rank() == 0 {
|
let k = if a.rank() == 0 {
|
||||||
b.k()
|
b.k()
|
||||||
|
// If b is a plaintext (but a ciphertext)
|
||||||
} else if b.rank() == 0 {
|
} else if b.rank() == 0 {
|
||||||
a.k()
|
a.k()
|
||||||
|
// If a & b are both ciphertexts
|
||||||
} else {
|
} else {
|
||||||
a.k().min(b.k())
|
a.k().min(b.k())
|
||||||
};
|
};
|
||||||
k.min(c.k())
|
k.min(c.k())
|
||||||
|
// If a & b are both plaintexts
|
||||||
} else {
|
} else {
|
||||||
c.k()
|
c.k()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a = op(a, b)
|
||||||
|
fn set_k_unary(a: &impl Infos, b: &impl Infos) -> usize {
|
||||||
|
if a.rank() != 0 || b.rank() != 0 {
|
||||||
|
a.k().min(b.k())
|
||||||
|
} else {
|
||||||
|
a.k()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::{GLWEAutomorphismKey, GLWECiphertext, GLWEOps, Infos, ScratchCore};
|
use crate::{GLWEAutomorphismKey, GLWECiphertext, GLWEOps, Infos, ScratchCore};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use backend::{FFT64, Module, Scratch, VecZnxOps};
|
use backend::{FFT64, Module, Scratch};
|
||||||
|
|
||||||
/// [StreamPacker] enables only the fly GLWE packing
|
/// [StreamPacker] enables only the fly GLWE packing
|
||||||
/// with constant memory of Log(N) ciphertexts.
|
/// with constant memory of Log(N) ciphertexts.
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use backend::{Decoding, Encoding, FFT64, Module, ScratchOwned, Stats, VecZnxOps, ZnxZero};
|
use backend::{FFT64, FillUniform, Module, ScratchOwned, Stats};
|
||||||
use itertools::izip;
|
|
||||||
use sampling::source::Source;
|
use sampling::source::Source;
|
||||||
|
|
||||||
use crate::{FourierGLWECiphertext, FourierGLWESecret, GLWECiphertext, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos};
|
use crate::{FourierGLWECiphertext, FourierGLWESecret, GLWECiphertext, GLWEOps, GLWEPlaintext, GLWEPublicKey, GLWESecret, Infos};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encrypt_sk() {
|
fn encrypt_sk() {
|
||||||
@@ -35,7 +34,8 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k_ct: usize, k_pt: usize, sigma:
|
|||||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||||
|
|
||||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_ct, rank);
|
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_ct, rank);
|
||||||
let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_pt);
|
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_pt);
|
||||||
|
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_pt);
|
||||||
|
|
||||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||||
let mut source_xe: Source = Source::new([0u8; 32]);
|
let mut source_xe: Source = Source::new([0u8; 32]);
|
||||||
@@ -50,17 +50,13 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k_ct: usize, k_pt: usize, sigma:
|
|||||||
sk.fill_ternary_prob(0.5, &mut source_xs);
|
sk.fill_ternary_prob(0.5, &mut source_xs);
|
||||||
let sk_dft: FourierGLWESecret<Vec<u8>, FFT64> = FourierGLWESecret::from(&module, &sk);
|
let sk_dft: FourierGLWESecret<Vec<u8>, FFT64> = FourierGLWESecret::from(&module, &sk);
|
||||||
|
|
||||||
let mut data_want: Vec<i64> = vec![0i64; module.n()];
|
pt_want
|
||||||
|
.data
|
||||||
data_want
|
.fill_uniform(basek, 0, pt_want.size(), &mut source_xa);
|
||||||
.iter_mut()
|
|
||||||
.for_each(|x| *x = source_xa.next_i64() & 0xFF);
|
|
||||||
|
|
||||||
pt.data.encode_vec_i64(0, basek, k_pt, &data_want, 10);
|
|
||||||
|
|
||||||
ct.encrypt_sk(
|
ct.encrypt_sk(
|
||||||
&module,
|
&module,
|
||||||
&pt,
|
&pt_want,
|
||||||
&sk_dft,
|
&sk_dft,
|
||||||
&mut source_xa,
|
&mut source_xa,
|
||||||
&mut source_xe,
|
&mut source_xe,
|
||||||
@@ -68,26 +64,14 @@ fn test_encrypt_sk(log_n: usize, basek: usize, k_ct: usize, k_pt: usize, sigma:
|
|||||||
scratch.borrow(),
|
scratch.borrow(),
|
||||||
);
|
);
|
||||||
|
|
||||||
pt.data.zero();
|
ct.decrypt(&module, &mut pt_have, &sk_dft, scratch.borrow());
|
||||||
|
|
||||||
ct.decrypt(&module, &mut pt, &sk_dft, scratch.borrow());
|
pt_want.sub_inplace_ab(&module, &pt_have);
|
||||||
|
|
||||||
let mut data_have: Vec<i64> = vec![0i64; module.n()];
|
let noise_have: f64 = pt_want.data.std(0, basek) * (ct.k() as f64).exp2();
|
||||||
|
let noise_want: f64 = sigma;
|
||||||
|
|
||||||
pt.data
|
assert!(noise_have <= noise_want + 0.2);
|
||||||
.decode_vec_i64(0, basek, pt.size() * basek, &mut data_have);
|
|
||||||
|
|
||||||
// TODO: properly assert the decryption noise through std(dec(ct) - pt)
|
|
||||||
let scale: f64 = (1 << (pt.size() * basek - k_pt)) as f64;
|
|
||||||
izip!(data_want.iter(), data_have.iter()).for_each(|(a, b)| {
|
|
||||||
let b_scaled = (*b as f64) / scale;
|
|
||||||
assert!(
|
|
||||||
(*a as f64 - b_scaled).abs() < 0.1,
|
|
||||||
"{} {}",
|
|
||||||
*a as f64,
|
|
||||||
b_scaled
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_encrypt_zero_sk(log_n: usize, basek: usize, k_ct: usize, sigma: f64, rank: usize) {
|
fn test_encrypt_zero_sk(log_n: usize, basek: usize, k_ct: usize, sigma: f64, rank: usize) {
|
||||||
@@ -127,6 +111,7 @@ fn test_encrypt_pk(log_n: usize, basek: usize, k_ct: usize, k_pk: usize, sigma:
|
|||||||
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
let module: Module<FFT64> = Module::<FFT64>::new(1 << log_n);
|
||||||
|
|
||||||
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_ct, rank);
|
let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&module, basek, k_ct, rank);
|
||||||
|
let mut pt_have = GLWEPlaintext::alloc(&module, basek, k_ct);
|
||||||
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_ct);
|
let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_ct);
|
||||||
|
|
||||||
let mut source_xs: Source = Source::new([0u8; 32]);
|
let mut source_xs: Source = Source::new([0u8; 32]);
|
||||||
@@ -147,13 +132,9 @@ fn test_encrypt_pk(log_n: usize, basek: usize, k_ct: usize, k_pk: usize, sigma:
|
|||||||
| GLWECiphertext::encrypt_pk_scratch_space(&module, basek, pk.k()),
|
| GLWECiphertext::encrypt_pk_scratch_space(&module, basek, pk.k()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut data_want: Vec<i64> = vec![0i64; module.n()];
|
pt_want
|
||||||
|
.data
|
||||||
data_want
|
.fill_uniform(basek, 0, pt_want.size(), &mut source_xa);
|
||||||
.iter_mut()
|
|
||||||
.for_each(|x| *x = source_xa.next_i64() & 0);
|
|
||||||
|
|
||||||
pt_want.data.encode_vec_i64(0, basek, k_ct, &data_want, 10);
|
|
||||||
|
|
||||||
ct.encrypt_pk(
|
ct.encrypt_pk(
|
||||||
&module,
|
&module,
|
||||||
@@ -165,11 +146,9 @@ fn test_encrypt_pk(log_n: usize, basek: usize, k_ct: usize, k_pk: usize, sigma:
|
|||||||
scratch.borrow(),
|
scratch.borrow(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&module, basek, k_ct);
|
|
||||||
|
|
||||||
ct.decrypt(&module, &mut pt_have, &sk_dft, scratch.borrow());
|
ct.decrypt(&module, &mut pt_have, &sk_dft, scratch.borrow());
|
||||||
|
|
||||||
module.vec_znx_sub_ab_inplace(&mut pt_want.data, 0, &pt_have.data, 0);
|
pt_want.sub_inplace_ab(&module, &pt_have);
|
||||||
|
|
||||||
let noise_have: f64 = pt_want.data.std(0, basek).log2();
|
let noise_have: f64 = pt_want.data.std(0, basek).log2();
|
||||||
let noise_want: f64 = ((((rank as f64) + 1.0) * module.n() as f64 * 0.5 * sigma * sigma).sqrt()).log2() - (k_ct as f64);
|
let noise_want: f64 = ((((rank as f64) + 1.0) * module.n() as f64 * 0.5 * sigma * sigma).sqrt()).log2() - (k_ct as f64);
|
||||||
|
|||||||
Reference in New Issue
Block a user