Add schemes (#71)

* Move br + cbt to schemes/tfhe

* refactor blind rotation

* refactor circuit bootstrapping

* renamed exec -> prepared
This commit is contained in:
Jean-Philippe Bossuat
2025-08-15 15:06:26 +02:00
committed by GitHub
parent 8d9897b88b
commit c7219c35e9
130 changed files with 2631 additions and 3270 deletions

View File

@@ -3,21 +3,24 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{GGLWEAutomorphismKey, Infos, prepared::GGLWESwitchingKeyExec};
use crate::layouts::{
GGLWEAutomorphismKey, Infos,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
#[derive(PartialEq, Eq)]
pub struct GGLWEAutomorphismKeyExec<D: Data, B: Backend> {
pub(crate) key: GGLWESwitchingKeyExec<D, B>,
pub struct GGLWEAutomorphismKeyPrepared<D: Data, B: Backend> {
pub(crate) key: GGLWESwitchingKeyPrepared<D, B>,
pub(crate) p: i64,
}
impl<B: Backend> GGLWEAutomorphismKeyExec<Vec<u8>, B> {
impl<B: Backend> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
GGLWEAutomorphismKeyExec::<Vec<u8>, B> {
key: GGLWESwitchingKeyExec::alloc(module, n, basek, k, rows, digits, rank, rank),
GGLWEAutomorphismKeyPrepared::<Vec<u8>, B> {
key: GGLWESwitchingKeyPrepared::alloc(module, n, basek, k, rows, digits, rank, rank),
p: 0,
}
}
@@ -26,28 +29,11 @@ impl<B: Backend> GGLWEAutomorphismKeyExec<Vec<u8>, B> {
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, rank, rank)
}
pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GGLWEAutomorphismKey<DataOther>, scratch: &mut Scratch<B>) -> Self
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
let mut atk_exec: GGLWEAutomorphismKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.n(),
other.basek(),
other.k(),
other.rows(),
other.digits(),
other.rank(),
);
atk_exec.prepare(module, other, scratch);
atk_exec
GGLWESwitchingKeyPrepared::bytes_of(module, n, basek, k, rows, digits, rank, rank)
}
}
impl<D: Data, B: Backend> Infos for GGLWEAutomorphismKeyExec<D, B> {
impl<D: Data, B: Backend> Infos for GGLWEAutomorphismKeyPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -63,7 +49,7 @@ impl<D: Data, B: Backend> Infos for GGLWEAutomorphismKeyExec<D, B> {
}
}
impl<D: Data, B: Backend> GGLWEAutomorphismKeyExec<D, B> {
impl<D: Data, B: Backend> GGLWEAutomorphismKeyPrepared<D, B> {
pub fn p(&self) -> i64 {
self.p
}
@@ -85,13 +71,31 @@ impl<D: Data, B: Backend> GGLWEAutomorphismKeyExec<D, B> {
}
}
impl<D: DataMut, B: Backend> GGLWEAutomorphismKeyExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKey<DataOther>, scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VmpPMatPrepare<B>,
{
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWEAutomorphismKey<DR>> for GGLWEAutomorphismKeyPrepared<D, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKey<DR>, scratch: &mut Scratch<B>) {
self.key.prepare(module, &other.key, scratch);
self.p = other.p;
}
}
}
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> for GGLWEAutomorphismKey<D>
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> {
let mut atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = GGLWEAutomorphismKeyPrepared::alloc(
module,
self.n(),
self.basek(),
self.k(),
self.rows(),
self.digits(),
self.rank(),
);
atk_prepared.prepare(module, self, scratch);
atk_prepared
}
}

View File

@@ -3,17 +3,20 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{GGLWECiphertext, Infos};
use crate::layouts::{
GGLWECiphertext, Infos,
prepared::{Prepare, PrepareAlloc},
};
#[derive(PartialEq, Eq)]
pub struct GGLWECiphertextExec<D: Data, B: Backend> {
pub struct GGLWECiphertextPrepared<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> GGLWECiphertextExec<Vec<u8>, B> {
impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
pub fn alloc(
module: &Module<B>,
n: usize,
@@ -84,7 +87,7 @@ impl<B: Backend> GGLWECiphertextExec<Vec<u8>, B> {
}
}
impl<D: Data, B: Backend> Infos for GGLWECiphertextExec<D, B> {
impl<D: Data, B: Backend> Infos for GGLWECiphertextPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -100,7 +103,7 @@ impl<D: Data, B: Backend> Infos for GGLWECiphertextExec<D, B> {
}
}
impl<D: Data, B: Backend> GGLWECiphertextExec<D, B> {
impl<D: Data, B: Backend> GGLWECiphertextPrepared<D, B> {
pub fn rank(&self) -> usize {
self.data.cols_out() - 1
}
@@ -118,15 +121,34 @@ impl<D: Data, B: Backend> GGLWECiphertextExec<D, B> {
}
}
impl<D: DataMut, B: Backend> GGLWECiphertextExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWECiphertext<DataOther>, scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VmpPMatPrepare<B>,
{
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWECiphertext<DR>> for GGLWECiphertextPrepared<D, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GGLWECiphertext<DR>, scratch: &mut Scratch<B>) {
module.vmp_prepare(&mut self.data, &other.data, scratch);
self.basek = other.basek;
self.k = other.k;
self.digits = other.digits;
}
}
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWECiphertextPrepared<Vec<u8>, B>> for GGLWECiphertext<D>
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWECiphertextPrepared<Vec<u8>, B> {
let mut atk_prepared: GGLWECiphertextPrepared<Vec<u8>, B> = GGLWECiphertextPrepared::alloc(
module,
self.n(),
self.basek(),
self.k(),
self.rows(),
self.digits(),
self.rank_in(),
self.rank_out(),
);
atk_prepared.prepare(module, self, scratch);
atk_prepared
}
}

View File

@@ -3,16 +3,19 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{GGLWESwitchingKey, Infos, prepared::GGLWECiphertextExec};
use crate::layouts::{
GGLWESwitchingKey, Infos,
prepared::{GGLWECiphertextPrepared, Prepare, PrepareAlloc},
};
#[derive(PartialEq, Eq)]
pub struct GGLWESwitchingKeyExec<D: Data, B: Backend> {
pub(crate) key: GGLWECiphertextExec<D, B>,
pub struct GGLWESwitchingKeyPrepared<D: Data, B: Backend> {
pub(crate) key: GGLWECiphertextPrepared<D, B>,
pub(crate) sk_in_n: usize, // Degree of sk_in
pub(crate) sk_out_n: usize, // Degree of sk_out
}
impl<B: Backend> GGLWESwitchingKeyExec<Vec<u8>, B> {
impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc(
module: &Module<B>,
n: usize,
@@ -26,8 +29,8 @@ impl<B: Backend> GGLWESwitchingKeyExec<Vec<u8>, B> {
where
Module<B>: VmpPMatAlloc<B>,
{
GGLWESwitchingKeyExec::<Vec<u8>, B> {
key: GGLWECiphertextExec::alloc(module, n, basek, k, rows, digits, rank_in, rank_out),
GGLWESwitchingKeyPrepared::<Vec<u8>, B> {
key: GGLWECiphertextPrepared::alloc(module, n, basek, k, rows, digits, rank_in, rank_out),
sk_in_n: 0,
sk_out_n: 0,
}
@@ -46,29 +49,11 @@ impl<B: Backend> GGLWESwitchingKeyExec<Vec<u8>, B> {
where
Module<B>: VmpPMatAllocBytes,
{
GGLWECiphertextExec::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out)
}
pub fn from<DataOther: DataRef>(module: &Module<B>, other: &GGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
let mut ksk_exec: GGLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.n(),
other.basek(),
other.k(),
other.rows(),
other.digits(),
other.rank_in(),
other.rank_out(),
);
ksk_exec.prepare(module, other, scratch);
ksk_exec
GGLWECiphertextPrepared::bytes_of(module, n, basek, k, rows, digits, rank_in, rank_out)
}
}
impl<D: Data, B: Backend> Infos for GGLWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> Infos for GGLWESwitchingKeyPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -84,7 +69,7 @@ impl<D: Data, B: Backend> Infos for GGLWESwitchingKeyExec<D, B> {
}
}
impl<D: Data, B: Backend> GGLWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> GGLWESwitchingKeyPrepared<D, B> {
pub fn rank(&self) -> usize {
self.key.data.cols_out() - 1
}
@@ -110,14 +95,33 @@ impl<D: Data, B: Backend> GGLWESwitchingKeyExec<D, B> {
}
}
impl<D: DataMut, B: Backend> GGLWESwitchingKeyExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VmpPMatPrepare<B>,
{
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWESwitchingKey<DR>> for GGLWESwitchingKeyPrepared<D, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GGLWESwitchingKey<DR>, scratch: &mut Scratch<B>) {
self.key.prepare(module, &other.key, scratch);
self.sk_in_n = other.sk_in_n;
self.sk_out_n = other.sk_out_n;
}
}
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWESwitchingKeyPrepared<Vec<u8>, B>> for GGLWESwitchingKey<D>
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
let mut atk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = GGLWESwitchingKeyPrepared::alloc(
module,
self.n(),
self.basek(),
self.k(),
self.rows(),
self.digits(),
self.rank_in(),
self.rank_out(),
);
atk_prepared.prepare(module, self, scratch);
atk_prepared
}
}

View File

@@ -3,22 +3,25 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{GGLWETensorKey, Infos, prepared::GGLWESwitchingKeyExec};
use crate::layouts::{
GGLWETensorKey, Infos,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
#[derive(PartialEq, Eq)]
pub struct GGLWETensorKeyExec<D: Data, B: Backend> {
pub(crate) keys: Vec<GGLWESwitchingKeyExec<D, B>>,
pub struct GGLWETensorKeyPrepared<D: Data, B: Backend> {
pub(crate) keys: Vec<GGLWESwitchingKeyPrepared<D, B>>,
}
impl<B: Backend> GGLWETensorKeyExec<Vec<u8>, B> {
impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
let mut keys: Vec<GGLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new();
let mut keys: Vec<GGLWESwitchingKeyPrepared<Vec<u8>, B>> = Vec::new();
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
(0..pairs).for_each(|_| {
keys.push(GGLWESwitchingKeyExec::alloc(
keys.push(GGLWESwitchingKeyPrepared::alloc(
module, n, basek, k, rows, digits, 1, rank,
));
});
@@ -30,32 +33,11 @@ impl<B: Backend> GGLWETensorKeyExec<Vec<u8>, B> {
Module<B>: VmpPMatAllocBytes,
{
let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
pairs * GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, 1, rank)
}
pub fn from<D: DataRef>(
module: &Module<B>,
other: &GGLWETensorKey<D>,
scratch: &mut Scratch<B>,
) -> GGLWETensorKeyExec<Vec<u8>, B>
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.n(),
other.basek(),
other.k(),
other.rows(),
other.digits(),
other.rank(),
);
tsk_exec.prepare(module, other, scratch);
tsk_exec
pairs * GGLWESwitchingKeyPrepared::bytes_of(module, n, basek, k, rows, digits, 1, rank)
}
}
impl<D: Data, B: Backend> Infos for GGLWETensorKeyExec<D, B> {
impl<D: Data, B: Backend> Infos for GGLWETensorKeyPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -71,7 +53,7 @@ impl<D: Data, B: Backend> Infos for GGLWETensorKeyExec<D, B> {
}
}
impl<D: Data, B: Backend> GGLWETensorKeyExec<D, B> {
impl<D: Data, B: Backend> GGLWETensorKeyPrepared<D, B> {
pub fn rank(&self) -> usize {
self.keys[0].rank()
}
@@ -89,9 +71,9 @@ impl<D: Data, B: Backend> GGLWETensorKeyExec<D, B> {
}
}
impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> {
impl<D: DataMut, B: Backend> GGLWETensorKeyPrepared<D, B> {
// Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyExec<D, B> {
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyPrepared<D, B> {
if i > j {
std::mem::swap(&mut i, &mut j);
};
@@ -100,9 +82,9 @@ impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> {
}
}
impl<D: DataRef, B: Backend> GGLWETensorKeyExec<D, B> {
impl<D: DataRef, B: Backend> GGLWETensorKeyPrepared<D, B> {
// Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyExec<D, B> {
pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyPrepared<D, B> {
if i > j {
std::mem::swap(&mut i, &mut j);
};
@@ -111,12 +93,11 @@ impl<D: DataRef, B: Backend> GGLWETensorKeyExec<D, B> {
}
}
impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWETensorKey<DataOther>, scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VmpPMatPrepare<B>,
{
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWETensorKey<DR>> for GGLWETensorKeyPrepared<D, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GGLWETensorKey<DR>, scratch: &mut Scratch<B>) {
#[cfg(debug_assertions)]
{
assert_eq!(self.keys.len(), other.keys.len());
@@ -129,3 +110,22 @@ impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> {
});
}
}
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>> for GGLWETensorKey<D>
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWETensorKeyPrepared<Vec<u8>, B> {
let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = GGLWETensorKeyPrepared::alloc(
module,
self.n(),
self.basek(),
self.k(),
self.rows(),
self.digits(),
self.rank(),
);
tsk_prepared.prepare(module, self, scratch);
tsk_prepared
}
}

View File

@@ -3,17 +3,20 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{GGSWCiphertext, Infos};
use crate::layouts::{
GGSWCiphertext, Infos,
prepared::{Prepare, PrepareAlloc},
};
#[derive(PartialEq, Eq)]
pub struct GGSWCiphertextExec<D: Data, B: Backend> {
pub struct GGSWCiphertextPrepared<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> {
impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
where
Module<B>: VmpPMatAlloc<B>,
@@ -66,30 +69,9 @@ impl<B: Backend> GGSWCiphertextExec<Vec<u8>, B> {
module.vmp_pmat_alloc_bytes(n, 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>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
let mut ggsw_exec: GGSWCiphertextExec<Vec<u8>, B> = Self::alloc(
module,
other.n(),
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> {
impl<D: Data, B: Backend> Infos for GGSWCiphertextPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -105,7 +87,7 @@ impl<D: Data, B: Backend> Infos for GGSWCiphertextExec<D, B> {
}
}
impl<D: Data, B: Backend> GGSWCiphertextExec<D, B> {
impl<D: Data, B: Backend> GGSWCiphertextPrepared<D, B> {
pub fn rank(&self) -> usize {
self.data.cols_out() - 1
}
@@ -115,15 +97,39 @@ impl<D: Data, B: Backend> GGSWCiphertextExec<D, B> {
}
}
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>: VmpPMatPrepare<B>,
{
impl<D: DataRef, B: Backend> GGSWCiphertextPrepared<D, B> {
pub fn data(&self) -> &VmpPMat<D, B> {
&self.data
}
}
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGSWCiphertext<DR>> for GGSWCiphertextPrepared<D, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GGSWCiphertext<DR>, scratch: &mut Scratch<B>) {
module.vmp_prepare(&mut self.data, &other.data, scratch);
self.k = other.k;
self.basek = other.basek;
self.digits = other.digits;
}
}
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGSWCiphertextPrepared<Vec<u8>, B>> for GGSWCiphertext<D>
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGSWCiphertextPrepared<Vec<u8>, B> {
let mut ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = GGSWCiphertextPrepared::alloc(
module,
self.n(),
self.basek(),
self.k(),
self.rows(),
self.digits(),
self.rank(),
);
ggsw_prepared.prepare(module, self, scratch);
ggsw_prepared
}
}

View File

@@ -5,18 +5,21 @@ use backend::hal::{
use crate::{
dist::Distribution,
layouts::{GLWEPublicKey, Infos},
layouts::{
GLWEPublicKey, Infos,
prepared::{Prepare, PrepareAlloc},
},
};
#[derive(PartialEq, Eq)]
pub struct GLWEPublicKeyExec<D: Data, B: Backend> {
pub struct GLWEPublicKeyPrepared<D: Data, B: Backend> {
pub(crate) data: VecZnxDft<D, B>,
pub(crate) basek: usize,
pub(crate) k: usize,
pub(crate) dist: Distribution,
}
impl<D: Data, B: Backend> Infos for GLWEPublicKeyExec<D, B> {
impl<D: Data, B: Backend> Infos for GLWEPublicKeyPrepared<D, B> {
type Inner = VecZnxDft<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -32,13 +35,13 @@ impl<D: Data, B: Backend> Infos for GLWEPublicKeyExec<D, B> {
}
}
impl<D: Data, B: Backend> GLWEPublicKeyExec<D, B> {
impl<D: Data, B: Backend> GLWEPublicKeyPrepared<D, B> {
pub fn rank(&self) -> usize {
self.cols() - 1
}
}
impl<B: Backend> GLWEPublicKeyExec<Vec<u8>, B> {
impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rank: usize) -> Self
where
Module<B>: VecZnxDftAlloc<B>,
@@ -57,25 +60,25 @@ impl<B: Backend> GLWEPublicKeyExec<Vec<u8>, B> {
{
module.vec_znx_dft_alloc_bytes(n, rank + 1, k.div_ceil(basek))
}
}
pub fn from<DataOther>(module: &Module<B>, other: &GLWEPublicKey<DataOther>, scratch: &mut Scratch<B>) -> Self
where
DataOther: DataRef,
Module<B>: VecZnxDftAlloc<B> + VecZnxDftFromVecZnx<B>,
{
let mut pk_exec: GLWEPublicKeyExec<Vec<u8>, B> =
GLWEPublicKeyExec::alloc(module, other.n(), other.basek(), other.k(), other.rank());
pk_exec.prepare(module, other, scratch);
pk_exec
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEPublicKeyPrepared<Vec<u8>, B>> for GLWEPublicKey<D>
where
Module<B>: VecZnxDftAlloc<B> + VecZnxDftFromVecZnx<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GLWEPublicKeyPrepared<Vec<u8>, B> {
let mut pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> =
GLWEPublicKeyPrepared::alloc(module, self.n(), self.basek(), self.k(), self.rank());
pk_prepared.prepare(module, self, scratch);
pk_prepared
}
}
impl<D: DataMut, B: Backend> GLWEPublicKeyExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEPublicKey<DataOther>, _scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VecZnxDftFromVecZnx<B>,
{
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEPublicKey<DR>> for GLWEPublicKeyPrepared<DM, B>
where
Module<B>: VecZnxDftFromVecZnx<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GLWEPublicKey<DR>, _scratch: &mut Scratch<B>) {
#[cfg(debug_assertions)]
{
assert_eq!(self.n(), other.n());

View File

@@ -3,17 +3,24 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, SvpPPol},
};
use crate::{dist::Distribution, layouts::GLWESecret, trait_families::GLWESecretExecModuleFamily};
use crate::{
dist::Distribution,
layouts::{
GLWESecret,
prepared::{Prepare, PrepareAlloc},
},
trait_families::GLWESecretPreparedModuleFamily,
};
pub struct GLWESecretExec<D: Data, B: Backend> {
pub struct GLWESecretPrepared<D: Data, B: Backend> {
pub(crate) data: SvpPPol<D, B>,
pub(crate) dist: Distribution,
}
impl<B: Backend> GLWESecretExec<Vec<u8>, B> {
impl<B: Backend> GLWESecretPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, rank: usize) -> Self
where
Module<B>: GLWESecretExecModuleFamily<B>,
Module<B>: GLWESecretPreparedModuleFamily<B>,
{
Self {
data: module.svp_ppol_alloc(n, rank),
@@ -23,25 +30,13 @@ impl<B: Backend> GLWESecretExec<Vec<u8>, B> {
pub fn bytes_of(module: &Module<B>, n: usize, rank: usize) -> usize
where
Module<B>: GLWESecretExecModuleFamily<B>,
Module<B>: GLWESecretPreparedModuleFamily<B>,
{
module.svp_ppol_alloc_bytes(n, rank)
}
}
impl<B: Backend> GLWESecretExec<Vec<u8>, B> {
pub fn from<D>(module: &Module<B>, sk: &GLWESecret<D>) -> Self
where
D: DataRef,
Module<B>: GLWESecretExecModuleFamily<B>,
{
let mut sk_dft: GLWESecretExec<Vec<u8>, B> = Self::alloc(module, sk.n(), sk.rank());
sk_dft.prepare(module, sk);
sk_dft
}
}
impl<D: Data, B: Backend> GLWESecretExec<D, B> {
impl<D: Data, B: Backend> GLWESecretPrepared<D, B> {
pub fn n(&self) -> usize {
self.data.n()
}
@@ -55,15 +50,29 @@ impl<D: Data, B: Backend> GLWESecretExec<D, B> {
}
}
impl<D: DataMut, B: Backend> GLWESecretExec<D, B> {
pub(crate) fn prepare<O>(&mut self, module: &Module<B>, sk: &GLWESecret<O>)
where
O: DataRef,
Module<B>: GLWESecretExecModuleFamily<B>,
{
(0..self.rank()).for_each(|i| {
module.svp_prepare(&mut self.data, i, &sk.data, i);
});
self.dist = sk.dist
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWESecretPrepared<Vec<u8>, B>> for GLWESecret<D>
where
Module<B>: SvpPrepare<B> + SvpPPolAllocBytes + SvpPPolAlloc<B>,
{
fn prepare_alloc(
&self,
module: &Module<B>,
scratch: &mut backend::hal::layouts::Scratch<B>,
) -> GLWESecretPrepared<Vec<u8>, B> {
let mut sk_dft: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, self.n(), self.rank());
sk_dft.prepare(module, self, scratch);
sk_dft
}
}
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWESecret<DR>> for GLWESecretPrepared<DM, B>
where
Module<B>: SvpPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GLWESecret<DR>, _scratch: &mut backend::hal::layouts::Scratch<B>) {
(0..self.rank()).for_each(|i| {
module.svp_prepare(&mut self.data, i, &other.data, i);
});
self.dist = other.dist
}
}

View File

@@ -3,12 +3,15 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{GLWEToLWESwitchingKey, Infos, prepared::GGLWESwitchingKeyExec};
use crate::layouts::{
GLWEToLWESwitchingKey, Infos,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
#[derive(PartialEq, Eq)]
pub struct GLWEToLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>);
pub struct GLWEToLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>);
impl<D: Data, B: Backend> Infos for GLWEToLWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> Infos for GLWEToLWESwitchingKeyPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -24,7 +27,7 @@ impl<D: Data, B: Backend> Infos for GLWEToLWESwitchingKeyExec<D, B> {
}
}
impl<D: Data, B: Backend> GLWEToLWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> GLWEToLWESwitchingKeyPrepared<D, B> {
pub fn digits(&self) -> usize {
self.0.digits()
}
@@ -42,12 +45,12 @@ impl<D: Data, B: Backend> GLWEToLWESwitchingKeyExec<D, B> {
}
}
impl<B: Backend> GLWEToLWESwitchingKeyExec<Vec<u8>, B> {
impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_in: usize) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
Self(GGLWESwitchingKeyExec::alloc(
Self(GGLWESwitchingKeyPrepared::alloc(
module, n, basek, k, rows, 1, rank_in, 1,
))
}
@@ -56,36 +59,33 @@ impl<B: Backend> GLWEToLWESwitchingKeyExec<Vec<u8>, B> {
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1)
}
pub fn from<DataOther: DataRef>(
module: &Module<B>,
other: &GLWEToLWESwitchingKey<DataOther>,
scratch: &mut Scratch<B>,
) -> Self
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
let mut ksk_exec: GLWEToLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.0.n(),
other.0.basek(),
other.0.k(),
other.0.rows(),
other.0.rank_in(),
);
ksk_exec.prepare(module, other, scratch);
ksk_exec
GGLWESwitchingKeyPrepared::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, rank_in, 1)
}
}
impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GLWEToLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VmpPMatPrepare<B>,
{
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>> for GLWEToLWESwitchingKey<D>
where
Module<B>: VmpPMatPrepare<B> + VmpPMatAlloc<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
let mut ksk_prepared: GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> = GLWEToLWESwitchingKeyPrepared::alloc(
module,
self.0.n(),
self.0.basek(),
self.0.k(),
self.0.rows(),
self.0.rank_in(),
);
ksk_prepared.prepare(module, self, scratch);
ksk_prepared
}
}
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEToLWESwitchingKey<DR>> for GLWEToLWESwitchingKeyPrepared<DM, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &GLWEToLWESwitchingKey<DR>, scratch: &mut Scratch<B>) {
self.0.prepare(module, &other.0, scratch);
}
}

View File

@@ -3,12 +3,15 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{Infos, LWESwitchingKey, prepared::GGLWESwitchingKeyExec};
use crate::layouts::{
Infos, LWESwitchingKey,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
#[derive(PartialEq, Eq)]
pub struct LWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>);
pub struct LWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>);
impl<D: Data, B: Backend> Infos for LWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> Infos for LWESwitchingKeyPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -24,7 +27,7 @@ impl<D: Data, B: Backend> Infos for LWESwitchingKeyExec<D, B> {
}
}
impl<D: Data, B: Backend> LWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> LWESwitchingKeyPrepared<D, B> {
pub fn digits(&self) -> usize {
self.0.digits()
}
@@ -42,12 +45,12 @@ impl<D: Data, B: Backend> LWESwitchingKeyExec<D, B> {
}
}
impl<B: Backend> LWESwitchingKeyExec<Vec<u8>, B> {
impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
Self(GGLWESwitchingKeyExec::alloc(
Self(GGLWESwitchingKeyPrepared::alloc(
module, n, basek, k, rows, 1, 1, 1,
))
}
@@ -56,31 +59,32 @@ impl<B: Backend> LWESwitchingKeyExec<Vec<u8>, B> {
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1)
}
pub fn from<DataOther: DataRef>(module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>) -> Self
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
let mut ksk_exec: LWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.0.n(),
other.0.basek(),
other.0.k(),
other.0.rows(),
);
ksk_exec.prepare(module, other, scratch);
ksk_exec
GGLWESwitchingKeyPrepared::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, 1)
}
}
impl<D: DataMut, B: Backend> LWESwitchingKeyExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWESwitchingKey<DataOther>, scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VmpPMatPrepare<B>,
{
impl<D: DataRef, B: Backend> PrepareAlloc<B, LWESwitchingKeyPrepared<Vec<u8>, B>> for LWESwitchingKey<D>
where
Module<B>: VmpPMatPrepare<B> + VmpPMatAlloc<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> LWESwitchingKeyPrepared<Vec<u8>, B> {
let mut ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = LWESwitchingKeyPrepared::alloc(
module,
self.0.n(),
self.0.basek(),
self.0.k(),
self.0.rows(),
);
ksk_prepared.prepare(module, self, scratch);
ksk_prepared
}
}
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWESwitchingKey<DR>> for LWESwitchingKeyPrepared<DM, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &LWESwitchingKey<DR>, scratch: &mut Scratch<B>) {
self.0.prepare(module, &other.0, scratch);
}
}

View File

@@ -3,13 +3,16 @@ use backend::hal::{
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
};
use crate::layouts::{Infos, LWEToGLWESwitchingKey, prepared::GGLWESwitchingKeyExec};
use crate::layouts::{
Infos, LWEToGLWESwitchingKey,
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc},
};
/// A special [GLWESwitchingKey] required to for the conversion from [LWECiphertext] to [GLWECiphertext].
#[derive(PartialEq, Eq)]
pub struct LWEToGLWESwitchingKeyExec<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyExec<D, B>);
pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>);
impl<D: Data, B: Backend> Infos for LWEToGLWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> Infos for LWEToGLWESwitchingKeyPrepared<D, B> {
type Inner = VmpPMat<D, B>;
fn inner(&self) -> &Self::Inner {
@@ -25,7 +28,7 @@ impl<D: Data, B: Backend> Infos for LWEToGLWESwitchingKeyExec<D, B> {
}
}
impl<D: Data, B: Backend> LWEToGLWESwitchingKeyExec<D, B> {
impl<D: Data, B: Backend> LWEToGLWESwitchingKeyPrepared<D, B> {
pub fn digits(&self) -> usize {
self.0.digits()
}
@@ -43,12 +46,12 @@ impl<D: Data, B: Backend> LWEToGLWESwitchingKeyExec<D, B> {
}
}
impl<B: Backend> LWEToGLWESwitchingKeyExec<Vec<u8>, B> {
impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, rank_out: usize) -> Self
where
Module<B>: VmpPMatAlloc<B>,
{
Self(GGLWESwitchingKeyExec::alloc(
Self(GGLWESwitchingKeyPrepared::alloc(
module, n, basek, k, rows, 1, 1, rank_out,
))
}
@@ -57,36 +60,33 @@ impl<B: Backend> LWEToGLWESwitchingKeyExec<Vec<u8>, B> {
where
Module<B>: VmpPMatAllocBytes,
{
GGLWESwitchingKeyExec::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out)
}
pub fn from<DataOther: DataRef>(
module: &Module<B>,
other: &LWEToGLWESwitchingKey<DataOther>,
scratch: &mut Scratch<B>,
) -> Self
where
Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
{
let mut ksk_exec: LWEToGLWESwitchingKeyExec<Vec<u8>, B> = Self::alloc(
module,
other.0.n(),
other.0.basek(),
other.0.k(),
other.0.rows(),
other.0.rank(),
);
ksk_exec.prepare(module, other, scratch);
ksk_exec
GGLWESwitchingKeyPrepared::<Vec<u8>, B>::bytes_of(module, n, basek, k, rows, digits, 1, rank_out)
}
}
impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyExec<D, B> {
pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DataOther>, scratch: &mut Scratch<B>)
where
DataOther: DataRef,
Module<B>: VmpPMatPrepare<B>,
{
impl<D: DataRef, B: Backend> PrepareAlloc<B, LWEToGLWESwitchingKeyPrepared<Vec<u8>, B>> for LWEToGLWESwitchingKey<D>
where
Module<B>: VmpPMatPrepare<B> + VmpPMatAlloc<B>,
{
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
let mut ksk_prepared: LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> = LWEToGLWESwitchingKeyPrepared::alloc(
module,
self.0.n(),
self.0.basek(),
self.0.k(),
self.0.rows(),
self.0.rank_out(),
);
ksk_prepared.prepare(module, self, scratch);
ksk_prepared
}
}
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWEToGLWESwitchingKey<DR>> for LWEToGLWESwitchingKeyPrepared<DM, B>
where
Module<B>: VmpPMatPrepare<B>,
{
fn prepare(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DR>, scratch: &mut Scratch<B>) {
self.0.prepare(module, &other.0, scratch);
}
}

View File

@@ -9,6 +9,7 @@ mod glwe_to_lwe_ksk;
mod lwe_ksk;
mod lwe_to_glwe_ksk;
use backend::hal::layouts::{Backend, Module, Scratch};
pub use gglwe_atk::*;
pub use gglwe_ct::*;
pub use gglwe_ksk::*;
@@ -19,3 +20,11 @@ pub use glwe_sk::*;
pub use glwe_to_lwe_ksk::*;
pub use lwe_ksk::*;
pub use lwe_to_glwe_ksk::*;
pub trait PrepareAlloc<B: Backend, T> {
fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> T;
}
pub trait Prepare<B: Backend, T> {
fn prepare(&mut self, module: &Module<B>, other: &T, scratch: &mut Scratch<B>);
}