mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
Dev serialization (#64)
* Added compressed serialization for GLWECiphertext + Ciphertext decompression * Added compressed serialization for GGLWECiphertext & GLWESwitchingkey * generalized automorphism test * Removed ops on scalar_znx, replaced by as_vec_znx/as_vec_znx_mut and then call op on vec_znx * Added tests for automorphism key encryption * Added tensorkey compressed * added ggsw compressed
This commit is contained in:
committed by
GitHub
parent
4c59733566
commit
9aa4b1f1e2
@@ -64,7 +64,7 @@ impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> {
|
||||
(0..rank + 1).for_each(|col_j| {
|
||||
// rlwe encrypt of vec_znx_pt into vec_znx_ct
|
||||
|
||||
self.at_mut(row_i, col_j).encrypt_sk_private(
|
||||
self.at_mut(row_i, col_j).encrypt_sk_internal(
|
||||
module,
|
||||
Some((&tmp_pt, col_j)),
|
||||
sk,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use backend::hal::{
|
||||
api::{MatZnxAlloc, MatZnxAllocBytes, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, Scratch, VmpPMat, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo},
|
||||
};
|
||||
|
||||
use crate::{GLWECiphertext, Infos};
|
||||
@@ -135,125 +135,3 @@ impl<D: DataRef> WriterTo for GGSWCiphertext<D> {
|
||||
self.data.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGSWCiphertextExec<D: Data, B: Backend> {
|
||||
pub(crate) data: VmpPMat<D, B>,
|
||||
pub(crate) basek: usize,
|
||||
pub(crate) k: usize,
|
||||
pub(crate) digits: usize,
|
||||
}
|
||||
|
||||
impl<B: Backend> GGSWCiphertextExec<Vec<u8>, B> {
|
||||
pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
|
||||
where
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
let size: usize = k.div_ceil(basek);
|
||||
debug_assert!(digits > 0, "invalid ggsw: `digits` == 0");
|
||||
|
||||
debug_assert!(
|
||||
size > digits,
|
||||
"invalid ggsw: ceil(k/basek): {} <= digits: {}",
|
||||
size,
|
||||
digits
|
||||
);
|
||||
|
||||
assert!(
|
||||
rows * digits <= size,
|
||||
"invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
|
||||
rows,
|
||||
digits,
|
||||
size
|
||||
);
|
||||
|
||||
Self {
|
||||
data: module.vmp_pmat_alloc(rows, rank + 1, rank + 1, k.div_ceil(basek)),
|
||||
basek,
|
||||
k: k,
|
||||
digits,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
|
||||
where
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
let size: usize = k.div_ceil(basek);
|
||||
debug_assert!(
|
||||
size > digits,
|
||||
"invalid ggsw: ceil(k/basek): {} <= digits: {}",
|
||||
size,
|
||||
digits
|
||||
);
|
||||
|
||||
assert!(
|
||||
rows * digits <= size,
|
||||
"invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
|
||||
rows,
|
||||
digits,
|
||||
size
|
||||
);
|
||||
|
||||
module.vmp_pmat_alloc_bytes(rows, rank + 1, rank + 1, size)
|
||||
}
|
||||
|
||||
pub fn from<DataOther: DataRef>(
|
||||
module: &Module<B>,
|
||||
other: &GGSWCiphertext<DataOther>,
|
||||
scratch: &mut Scratch<B>,
|
||||
) -> GGSWCiphertextExec<Vec<u8>, B>
|
||||
where
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
let mut ggsw_exec: GGSWCiphertextExec<Vec<u8>, B> = Self::alloc(
|
||||
module,
|
||||
other.basek(),
|
||||
other.k(),
|
||||
other.rows(),
|
||||
other.digits(),
|
||||
other.rank(),
|
||||
);
|
||||
ggsw_exec.prepare(module, other, scratch);
|
||||
ggsw_exec
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> Infos for GGSWCiphertextExec<D, B> {
|
||||
type Inner = VmpPMat<D, B>;
|
||||
|
||||
fn inner(&self) -> &Self::Inner {
|
||||
&self.data
|
||||
}
|
||||
|
||||
fn basek(&self) -> usize {
|
||||
self.basek
|
||||
}
|
||||
|
||||
fn k(&self) -> usize {
|
||||
self.k
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGSWCiphertextExec<D, B> {
|
||||
pub fn rank(&self) -> usize {
|
||||
self.data.cols_out() - 1
|
||||
}
|
||||
|
||||
pub fn digits(&self) -> usize {
|
||||
self.digits
|
||||
}
|
||||
}
|
||||
|
||||
impl<DataSelf: DataMut, B: Backend> GGSWCiphertextExec<DataSelf, B> {
|
||||
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGSWCiphertext<DataOther>, scratch: &mut Scratch<B>)
|
||||
where
|
||||
DataOther: DataRef,
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
module.vmp_prepare(&mut self.data, &other.data, scratch);
|
||||
self.k = other.k;
|
||||
self.basek = other.basek;
|
||||
self.digits = other.digits;
|
||||
}
|
||||
}
|
||||
|
||||
80
core/src/ggsw/layout_compressed.rs
Normal file
80
core/src/ggsw/layout_compressed.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use backend::hal::{
|
||||
api::{MatZnxAlloc, MatZnxAllocBytes, VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, MatZnx, Module, ReaderFrom, WriterTo},
|
||||
};
|
||||
|
||||
use crate::{GGLWECiphertextCompressed, GGSWCiphertext, Infos};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGSWCiphertextCompressed<D: Data> {
|
||||
pub(crate) data: GGLWECiphertextCompressed<D>,
|
||||
}
|
||||
|
||||
impl GGSWCiphertextCompressed<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,
|
||||
{
|
||||
GGSWCiphertextCompressed {
|
||||
data: GGLWECiphertextCompressed::alloc(module, basek, k, rows, digits, rank, rank),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_of<B: Backend>(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
|
||||
where
|
||||
Module<B>: MatZnxAllocBytes,
|
||||
{
|
||||
GGLWECiphertextCompressed::bytes_of(module, basek, k, rows, digits, rank)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> Infos for GGSWCiphertextCompressed<D> {
|
||||
type Inner = MatZnx<D>;
|
||||
|
||||
fn inner(&self) -> &Self::Inner {
|
||||
self.data.inner()
|
||||
}
|
||||
|
||||
fn basek(&self) -> usize {
|
||||
self.data.basek()
|
||||
}
|
||||
|
||||
fn k(&self) -> usize {
|
||||
self.data.k()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGSWCiphertextCompressed<D> {
|
||||
pub fn rank(&self) -> usize {
|
||||
self.data.rank()
|
||||
}
|
||||
|
||||
pub fn digits(&self) -> usize {
|
||||
self.data.digits()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGSWCiphertextCompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.data.read_from(reader)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGSWCiphertextCompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
self.data.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGSWCiphertext<D> {
|
||||
pub fn decompress<DataOther: DataRef, B: Backend>(&mut self, module: &Module<B>, other: &GGSWCiphertextCompressed<DataOther>)
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
{
|
||||
let rows = self.rows();
|
||||
(0..rows).for_each(|row_i| {
|
||||
self.at_mut(row_i, 0)
|
||||
.decompress(module, &other.data.at(row_i, 0));
|
||||
});
|
||||
}
|
||||
}
|
||||
128
core/src/ggsw/layout_exec.rs
Normal file
128
core/src/ggsw/layout_exec.rs
Normal file
@@ -0,0 +1,128 @@
|
||||
use backend::hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
|
||||
};
|
||||
|
||||
use crate::{GGSWCiphertext, GGSWLayoutFamily, Infos};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGSWCiphertextExec<D: Data, B: Backend> {
|
||||
pub(crate) data: VmpPMat<D, B>,
|
||||
pub(crate) basek: usize,
|
||||
pub(crate) k: usize,
|
||||
pub(crate) digits: usize,
|
||||
}
|
||||
|
||||
impl<B: Backend> GGSWCiphertextExec<Vec<u8>, B> {
|
||||
pub fn alloc(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
|
||||
where
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
let size: usize = k.div_ceil(basek);
|
||||
debug_assert!(digits > 0, "invalid ggsw: `digits` == 0");
|
||||
|
||||
debug_assert!(
|
||||
size > digits,
|
||||
"invalid ggsw: ceil(k/basek): {} <= digits: {}",
|
||||
size,
|
||||
digits
|
||||
);
|
||||
|
||||
assert!(
|
||||
rows * digits <= size,
|
||||
"invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
|
||||
rows,
|
||||
digits,
|
||||
size
|
||||
);
|
||||
|
||||
Self {
|
||||
data: module.vmp_pmat_alloc(rows, rank + 1, rank + 1, k.div_ceil(basek)),
|
||||
basek,
|
||||
k: k,
|
||||
digits,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_of(module: &Module<B>, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
|
||||
where
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
let size: usize = k.div_ceil(basek);
|
||||
debug_assert!(
|
||||
size > digits,
|
||||
"invalid ggsw: ceil(k/basek): {} <= digits: {}",
|
||||
size,
|
||||
digits
|
||||
);
|
||||
|
||||
assert!(
|
||||
rows * digits <= size,
|
||||
"invalid ggsw: rows: {} * digits:{} > ceil(k/basek): {}",
|
||||
rows,
|
||||
digits,
|
||||
size
|
||||
);
|
||||
|
||||
module.vmp_pmat_alloc_bytes(rows, rank + 1, rank + 1, size)
|
||||
}
|
||||
|
||||
pub fn from<DataOther: DataRef>(
|
||||
module: &Module<B>,
|
||||
other: &GGSWCiphertext<DataOther>,
|
||||
scratch: &mut Scratch<B>,
|
||||
) -> GGSWCiphertextExec<Vec<u8>, B>
|
||||
where
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
let mut ggsw_exec: GGSWCiphertextExec<Vec<u8>, B> = Self::alloc(
|
||||
module,
|
||||
other.basek(),
|
||||
other.k(),
|
||||
other.rows(),
|
||||
other.digits(),
|
||||
other.rank(),
|
||||
);
|
||||
ggsw_exec.prepare(module, other, scratch);
|
||||
ggsw_exec
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> Infos for GGSWCiphertextExec<D, B> {
|
||||
type Inner = VmpPMat<D, B>;
|
||||
|
||||
fn inner(&self) -> &Self::Inner {
|
||||
&self.data
|
||||
}
|
||||
|
||||
fn basek(&self) -> usize {
|
||||
self.basek
|
||||
}
|
||||
|
||||
fn k(&self) -> usize {
|
||||
self.k
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGSWCiphertextExec<D, B> {
|
||||
pub fn rank(&self) -> usize {
|
||||
self.data.cols_out() - 1
|
||||
}
|
||||
|
||||
pub fn digits(&self) -> usize {
|
||||
self.digits
|
||||
}
|
||||
}
|
||||
|
||||
impl<DataSelf: DataMut, B: Backend> GGSWCiphertextExec<DataSelf, B> {
|
||||
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGSWCiphertext<DataOther>, scratch: &mut Scratch<B>)
|
||||
where
|
||||
DataOther: DataRef,
|
||||
Module<B>: GGSWLayoutFamily<B>,
|
||||
{
|
||||
module.vmp_prepare(&mut self.data, &other.data, scratch);
|
||||
self.k = other.k;
|
||||
self.basek = other.basek;
|
||||
self.digits = other.digits;
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,16 @@ mod encryption;
|
||||
mod external_product;
|
||||
mod keyswitch;
|
||||
mod layout;
|
||||
mod layout_compressed;
|
||||
mod layout_exec;
|
||||
mod noise;
|
||||
|
||||
pub use encryption::GGSWEncryptSkFamily;
|
||||
pub use keyswitch::GGSWKeySwitchFamily;
|
||||
pub use layout::{GGSWCiphertext, GGSWCiphertextExec, GGSWLayoutFamily};
|
||||
pub use noise::GGSWAssertNoiseFamily;
|
||||
pub use encryption::*;
|
||||
pub use keyswitch::*;
|
||||
pub use layout::*;
|
||||
pub use layout_compressed::*;
|
||||
pub use layout_exec::*;
|
||||
pub use noise::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
1
core/src/ggsw/test/cpu_spqlios/mod.rs
Normal file
1
core/src/ggsw/test/cpu_spqlios/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
mod fft64;
|
||||
@@ -1,8 +1,8 @@
|
||||
use backend::hal::{
|
||||
api::{
|
||||
MatZnxAlloc, ScalarZnxAlloc, ScalarZnxAllocBytes, ScalarZnxAutomorphism, ScalarZnxAutomorphismInplace, ScratchOwnedAlloc,
|
||||
ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxAlloc, VecZnxAllocBytes, VecZnxAutomorphismInplace,
|
||||
VecZnxRotateInplace, VecZnxStd, VecZnxSubABInplace, VecZnxSwithcDegree, ZnxViewMut,
|
||||
MatZnxAlloc, ScalarZnxAlloc, ScalarZnxAllocBytes, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace,
|
||||
VecZnxAlloc, VecZnxAllocBytes, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxRotateInplace, VecZnxStd,
|
||||
VecZnxSubABInplace, VecZnxSwithcDegree, ZnxViewMut,
|
||||
},
|
||||
layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned},
|
||||
oep::{
|
||||
@@ -321,8 +321,8 @@ pub(crate) fn test_automorphism<B: Backend>(
|
||||
+ GGLWEExecLayoutFamily<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ ScalarZnxAutomorphismInplace
|
||||
+ ScalarZnxAutomorphism,
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ VecZnxAutomorphism,
|
||||
B: TestScratchFamily<B>,
|
||||
{
|
||||
let rows: usize = k_in.div_ceil(basek * digits);
|
||||
@@ -393,7 +393,7 @@ pub(crate) fn test_automorphism<B: Backend>(
|
||||
|
||||
ct_out.automorphism(module, &ct_in, &auto_key_exec, &tsk_exec, scratch.borrow());
|
||||
|
||||
module.scalar_znx_automorphism_inplace(p, &mut pt_scalar, 0);
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0);
|
||||
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
@@ -433,8 +433,8 @@ pub(crate) fn test_automorphism_inplace<B: Backend>(
|
||||
+ GGLWEExecLayoutFamily<B>
|
||||
+ VecZnxSwithcDegree
|
||||
+ VecZnxAutomorphismInplace
|
||||
+ ScalarZnxAutomorphismInplace
|
||||
+ ScalarZnxAutomorphism,
|
||||
+ VecZnxAutomorphism
|
||||
+ VecZnxAutomorphismInplace,
|
||||
B: TestScratchFamily<B>,
|
||||
{
|
||||
let rows: usize = k_ct.div_ceil(digits * basek);
|
||||
@@ -501,7 +501,7 @@ pub(crate) fn test_automorphism_inplace<B: Backend>(
|
||||
|
||||
ct.automorphism_inplace(module, &auto_key_exec, &tsk_exec, scratch.borrow());
|
||||
|
||||
module.scalar_znx_automorphism_inplace(p, &mut pt_scalar, 0);
|
||||
module.vec_znx_automorphism_inplace(p, &mut pt_scalar.as_vec_znx_mut(), 0);
|
||||
|
||||
let max_noise = |col_j: usize| -> f64 {
|
||||
noise_ggsw_keyswitch(
|
||||
@@ -595,7 +595,7 @@ pub(crate) fn test_external_product<B: Backend>(
|
||||
|
||||
ct_ggsw_lhs_out.external_product(module, &ct_ggsw_lhs_in, &ct_rhs_exec, scratch.borrow());
|
||||
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs, 0);
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0);
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
@@ -695,7 +695,7 @@ pub(crate) fn test_external_product_inplace<B: Backend>(
|
||||
|
||||
ct_ggsw_lhs.external_product_inplace(module, &ct_rhs_exec, scratch.borrow());
|
||||
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs, 0);
|
||||
module.vec_znx_rotate_inplace(k as i64, &mut pt_ggsw_lhs.as_vec_znx_mut(), 0);
|
||||
|
||||
let var_gct_err_lhs: f64 = sigma * sigma;
|
||||
let var_gct_err_rhs: f64 = 0f64;
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
mod cpu_spqlios;
|
||||
mod generic_tests;
|
||||
mod test_fft64;
|
||||
|
||||
Reference in New Issue
Block a user