use poulpy_hal::{
api::{TakeMatZnx, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxDft, TakeVmpPMat},
layouts::{Backend, Scratch},
};
use crate::{
dist::Distribution,
layouts::{
Degree, GGLWEAutomorphismKey, GGLWECiphertext, GGLWEInfos, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GGSWInfos,
GLWECiphertext, GLWEInfos, GLWEPlaintext, GLWEPublicKey, GLWESecret, Rank,
prepared::{
GGLWEAutomorphismKeyPrepared, GGLWECiphertextPrepared, GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared,
GGSWCiphertextPrepared, GLWEPublicKeyPrepared, GLWESecretPrepared,
},
},
};
pub trait TakeGLWECt {
fn take_glwe_ct(&mut self, infos: &A) -> (GLWECiphertext<&mut [u8]>, &mut Self)
where
A: GLWEInfos;
}
pub trait TakeGLWECtSlice {
fn take_glwe_ct_slice(&mut self, size: usize, infos: &A) -> (Vec>, &mut Self)
where
A: GLWEInfos;
}
pub trait TakeGLWEPt {
fn take_glwe_pt(&mut self, infos: &A) -> (GLWEPlaintext<&mut [u8]>, &mut Self)
where
A: GLWEInfos;
}
pub trait TakeGGLWE {
fn take_gglwe(&mut self, infos: &A) -> (GGLWECiphertext<&mut [u8]>, &mut Self)
where
A: GGLWEInfos;
}
pub trait TakeGGLWEPrepared {
fn take_gglwe_prepared(&mut self, infos: &A) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos;
}
pub trait TakeGGSW {
fn take_ggsw(&mut self, infos: &A) -> (GGSWCiphertext<&mut [u8]>, &mut Self)
where
A: GGSWInfos;
}
pub trait TakeGGSWPrepared {
fn take_ggsw_prepared(&mut self, infos: &A) -> (GGSWCiphertextPrepared<&mut [u8], B>, &mut Self)
where
A: GGSWInfos;
}
pub trait TakeGLWESecret {
fn take_glwe_secret(&mut self, n: Degree, rank: Rank) -> (GLWESecret<&mut [u8]>, &mut Self);
}
pub trait TakeGLWESecretPrepared {
fn take_glwe_secret_prepared(&mut self, n: Degree, rank: Rank) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self);
}
pub trait TakeGLWEPk {
fn take_glwe_pk(&mut self, infos: &A) -> (GLWEPublicKey<&mut [u8]>, &mut Self)
where
A: GLWEInfos;
}
pub trait TakeGLWEPkPrepared {
fn take_glwe_pk_prepared(&mut self, infos: &A) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GLWEInfos;
}
pub trait TakeGLWESwitchingKey {
fn take_glwe_switching_key(&mut self, infos: &A) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self)
where
A: GGLWEInfos;
}
pub trait TakeGGLWESwitchingKeyPrepared {
fn take_gglwe_switching_key_prepared(&mut self, infos: &A) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos;
}
pub trait TakeTensorKey {
fn take_tensor_key(&mut self, infos: &A) -> (GGLWETensorKey<&mut [u8]>, &mut Self)
where
A: GGLWEInfos;
}
pub trait TakeGGLWETensorKeyPrepared {
fn take_gglwe_tensor_key_prepared(&mut self, infos: &A) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos;
}
pub trait TakeGGLWEAutomorphismKey {
fn take_gglwe_automorphism_key(&mut self, infos: &A) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self)
where
A: GGLWEInfos;
}
pub trait TakeGGLWEAutomorphismKeyPrepared {
fn take_gglwe_automorphism_key_prepared(&mut self, infos: &A) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos;
}
impl TakeGLWECt for Scratch
where
Scratch: TakeVecZnx,
{
fn take_glwe_ct(&mut self, infos: &A) -> (GLWECiphertext<&mut [u8]>, &mut Self)
where
A: GLWEInfos,
{
let (data, scratch) = self.take_vec_znx(infos.n().into(), (infos.rank() + 1).into(), infos.size());
(
GLWECiphertext::builder()
.base2k(infos.base2k())
.k(infos.k())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGLWECtSlice for Scratch
where
Scratch: TakeVecZnx,
{
fn take_glwe_ct_slice(&mut self, size: usize, infos: &A) -> (Vec>, &mut Self)
where
A: GLWEInfos,
{
let mut scratch: &mut Scratch = self;
let mut cts: Vec> = Vec::with_capacity(size);
for _ in 0..size {
let (ct, new_scratch) = scratch.take_glwe_ct(infos);
scratch = new_scratch;
cts.push(ct);
}
(cts, scratch)
}
}
impl TakeGLWEPt for Scratch
where
Scratch: TakeVecZnx,
{
fn take_glwe_pt(&mut self, infos: &A) -> (GLWEPlaintext<&mut [u8]>, &mut Self)
where
A: GLWEInfos,
{
let (data, scratch) = self.take_vec_znx(infos.n().into(), 1, infos.size());
(
GLWEPlaintext::builder()
.base2k(infos.base2k())
.k(infos.k())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGGLWE for Scratch
where
Scratch: TakeMatZnx,
{
fn take_gglwe(&mut self, infos: &A) -> (GGLWECiphertext<&mut [u8]>, &mut Self)
where
A: GGLWEInfos,
{
let (data, scratch) = self.take_mat_znx(
infos.n().into(),
infos.dnum().0.div_ceil(infos.dsize().0) as usize,
infos.rank_in().into(),
(infos.rank_out() + 1).into(),
infos.size(),
);
(
GGLWECiphertext::builder()
.base2k(infos.base2k())
.k(infos.k())
.dsize(infos.dsize())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGGLWEPrepared for Scratch
where
Scratch: TakeVmpPMat,
{
fn take_gglwe_prepared(&mut self, infos: &A) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos,
{
let (data, scratch) = self.take_vmp_pmat(
infos.n().into(),
infos.dnum().into(),
infos.rank_in().into(),
(infos.rank_out() + 1).into(),
infos.size(),
);
(
GGLWECiphertextPrepared::builder()
.base2k(infos.base2k())
.dsize(infos.dsize())
.k(infos.k())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGGSW for Scratch
where
Scratch: TakeMatZnx,
{
fn take_ggsw(&mut self, infos: &A) -> (GGSWCiphertext<&mut [u8]>, &mut Self)
where
A: GGSWInfos,
{
let (data, scratch) = self.take_mat_znx(
infos.n().into(),
infos.dnum().into(),
(infos.rank() + 1).into(),
(infos.rank() + 1).into(),
infos.size(),
);
(
GGSWCiphertext::builder()
.base2k(infos.base2k())
.dsize(infos.dsize())
.k(infos.k())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGGSWPrepared for Scratch
where
Scratch: TakeVmpPMat,
{
fn take_ggsw_prepared(&mut self, infos: &A) -> (GGSWCiphertextPrepared<&mut [u8], B>, &mut Self)
where
A: GGSWInfos,
{
let (data, scratch) = self.take_vmp_pmat(
infos.n().into(),
infos.dnum().into(),
(infos.rank() + 1).into(),
(infos.rank() + 1).into(),
infos.size(),
);
(
GGSWCiphertextPrepared::builder()
.base2k(infos.base2k())
.dsize(infos.dsize())
.k(infos.k())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGLWEPk for Scratch
where
Scratch: TakeVecZnx,
{
fn take_glwe_pk(&mut self, infos: &A) -> (GLWEPublicKey<&mut [u8]>, &mut Self)
where
A: GLWEInfos,
{
let (data, scratch) = self.take_vec_znx(infos.n().into(), (infos.rank() + 1).into(), infos.size());
(
GLWEPublicKey::builder()
.base2k(infos.base2k())
.k(infos.k())
.base2k(infos.base2k())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGLWEPkPrepared for Scratch
where
Scratch: TakeVecZnxDft,
{
fn take_glwe_pk_prepared(&mut self, infos: &A) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GLWEInfos,
{
let (data, scratch) = self.take_vec_znx_dft(infos.n().into(), (infos.rank() + 1).into(), infos.size());
(
GLWEPublicKeyPrepared::builder()
.base2k(infos.base2k())
.k(infos.k())
.data(data)
.build()
.unwrap(),
scratch,
)
}
}
impl TakeGLWESecret for Scratch
where
Scratch: TakeScalarZnx,
{
fn take_glwe_secret(&mut self, n: Degree, rank: Rank) -> (GLWESecret<&mut [u8]>, &mut Self) {
let (data, scratch) = self.take_scalar_znx(n.into(), rank.into());
(
GLWESecret {
data,
dist: Distribution::NONE,
},
scratch,
)
}
}
impl TakeGLWESecretPrepared for Scratch
where
Scratch: TakeSvpPPol,
{
fn take_glwe_secret_prepared(&mut self, n: Degree, rank: Rank) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self) {
let (data, scratch) = self.take_svp_ppol(n.into(), rank.into());
(
GLWESecretPrepared {
data,
dist: Distribution::NONE,
},
scratch,
)
}
}
impl TakeGLWESwitchingKey for Scratch
where
Scratch: TakeMatZnx,
{
fn take_glwe_switching_key(&mut self, infos: &A) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self)
where
A: GGLWEInfos,
{
let (data, scratch) = self.take_gglwe(infos);
(
GGLWESwitchingKey {
key: data,
sk_in_n: 0,
sk_out_n: 0,
},
scratch,
)
}
}
impl TakeGGLWESwitchingKeyPrepared for Scratch
where
Scratch: TakeGGLWEPrepared,
{
fn take_gglwe_switching_key_prepared(&mut self, infos: &A) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos,
{
let (data, scratch) = self.take_gglwe_prepared(infos);
(
GGLWESwitchingKeyPrepared {
key: data,
sk_in_n: 0,
sk_out_n: 0,
},
scratch,
)
}
}
impl TakeGGLWEAutomorphismKey for Scratch
where
Scratch: TakeMatZnx,
{
fn take_gglwe_automorphism_key(&mut self, infos: &A) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self)
where
A: GGLWEInfos,
{
let (data, scratch) = self.take_glwe_switching_key(infos);
(GGLWEAutomorphismKey { key: data, p: 0 }, scratch)
}
}
impl TakeGGLWEAutomorphismKeyPrepared for Scratch
where
Scratch: TakeGGLWESwitchingKeyPrepared,
{
fn take_gglwe_automorphism_key_prepared(&mut self, infos: &A) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos,
{
let (data, scratch) = self.take_gglwe_switching_key_prepared(infos);
(GGLWEAutomorphismKeyPrepared { key: data, p: 0 }, scratch)
}
}
impl TakeTensorKey for Scratch
where
Scratch: TakeMatZnx,
{
fn take_tensor_key(&mut self, infos: &A) -> (GGLWETensorKey<&mut [u8]>, &mut Self)
where
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
infos.rank_out(),
"rank_in != rank_out is not supported for GGLWETensorKey"
);
let mut keys: Vec> = Vec::new();
let pairs: usize = (((infos.rank_out().0 + 1) * infos.rank_out().0) >> 1).max(1) as usize;
let mut scratch: &mut Scratch = self;
let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.layout();
ksk_infos.rank_in = Rank(1);
if pairs != 0 {
let (gglwe, s) = scratch.take_glwe_switching_key(&ksk_infos);
scratch = s;
keys.push(gglwe);
}
for _ in 1..pairs {
let (gglwe, s) = scratch.take_glwe_switching_key(&ksk_infos);
scratch = s;
keys.push(gglwe);
}
(GGLWETensorKey { keys }, scratch)
}
}
impl TakeGGLWETensorKeyPrepared for Scratch
where
Scratch: TakeVmpPMat,
{
fn take_gglwe_tensor_key_prepared(&mut self, infos: &A) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self)
where
A: GGLWEInfos,
{
assert_eq!(
infos.rank_in(),
infos.rank_out(),
"rank_in != rank_out is not supported for GGLWETensorKeyPrepared"
);
let mut keys: Vec> = Vec::new();
let pairs: usize = (((infos.rank_out().0 + 1) * infos.rank_out().0) >> 1).max(1) as usize;
let mut scratch: &mut Scratch = self;
let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.layout();
ksk_infos.rank_in = Rank(1);
if pairs != 0 {
let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(&ksk_infos);
scratch = s;
keys.push(gglwe);
}
for _ in 1..pairs {
let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(&ksk_infos);
scratch = s;
keys.push(gglwe);
}
(GGLWETensorKeyPrepared { keys }, scratch)
}
}