#[macro_use]
mod macros;
mod gglwe;
mod gglwe_to_ggsw_key;
mod ggsw;
mod glwe;
mod glwe_automorphism_key;
mod glwe_plaintext;
mod glwe_public_key;
mod glwe_secret;
mod glwe_secret_tensor;
mod glwe_switching_key;
mod glwe_tensor;
mod glwe_tensor_key;
mod glwe_to_lwe_key;
mod lwe;
mod lwe_plaintext;
mod lwe_secret;
mod lwe_switching_key;
mod lwe_to_glwe_key;
mod scratch_views;
pub mod compressed;
pub mod prepared;
pub use self::compressed::{
GGLWECompressed, GGLWECompressedSeed, GGLWECompressedSeedMut, GGLWECompressedToBackendMut, GGLWECompressedToBackendRef,
GGLWEDecompress, GGLWEToGGSWKeyCompressed, GGLWEToGGSWKeyCompressedToBackendMut, GGLWEToGGSWKeyCompressedToBackendRef,
GGLWEToGGSWKeyDecompress, GGSWCompressed, GGSWCompressedSeed, GGSWCompressedSeedMut, GGSWCompressedToBackendMut,
GGSWCompressedToBackendRef, GGSWDecompress, GLWEAutomorphismKeyCompressed, GLWEAutomorphismKeyDecompress, GLWECompressed,
GLWECompressedSeed, GLWECompressedSeedMut, GLWECompressedToBackendMut, GLWECompressedToBackendRef, GLWEDecompress,
GLWESwitchingKeyCompressed, GLWESwitchingKeyDecompress, GLWETensorKeyCompressed, GLWETensorKeyDecompress,
GLWEToLWESwitchingKeyCompressed, GLWEToLWESwitchingKeyDecompress, LWECompressed, LWECompressedToBackendMut,
LWECompressedToBackendRef, LWEDecompress, LWESwitchingKeyCompressed, LWESwitchingKeyDecompress, LWEToGLWEKeyCompressed,
LWEToGLWEKeyDecompress,
};
pub use gglwe::*;
pub use gglwe_to_ggsw_key::*;
pub use ggsw::*;
pub use glwe::*;
pub use glwe_automorphism_key::*;
pub use glwe_plaintext::*;
pub use glwe_public_key::*;
pub use glwe_secret::*;
pub use glwe_secret_tensor::*;
pub use glwe_switching_key::*;
pub use glwe_tensor::*;
pub use glwe_tensor_key::*;
pub use glwe_to_lwe_key::*;
pub use lwe::*;
pub use lwe_plaintext::*;
pub use lwe_secret::*;
pub use lwe_switching_key::*;
pub use lwe_to_glwe_key::*;
pub use prepared::*;
pub use scratch_views::*;
use crate::dist::Distribution;
use poulpy_hal::layouts::{Backend, Data, MatZnx, Module, ScalarZnx, VecZnx};
pub type BackendGLWE<BE> = GLWE<<BE as Backend>::OwnedBuf>;
pub type BackendGGLWE<BE> = GGLWE<<BE as Backend>::OwnedBuf>;
pub type BackendGGSW<BE> = GGSW<<BE as Backend>::OwnedBuf>;
pub type BackendLWE<BE> = LWE<<BE as Backend>::OwnedBuf>;
pub type BackendGLWESecret<BE> = GLWESecret<<BE as Backend>::OwnedBuf>;
pub type BackendLWESecret<BE> = LWESecret<<BE as Backend>::OwnedBuf>;
pub type BackendGLWEPlaintext<BE> = GLWEPlaintext<<BE as Backend>::OwnedBuf>;
pub type BackendLWEPlaintext<BE> = LWEPlaintext<<BE as Backend>::OwnedBuf>;
pub type BackendGLWEPrepared<BE> = GLWEPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGGLWEPrepared<BE> = GGLWEPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGGSWPrepared<BE> = GGSWPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGLWESecretPrepared<BE> = GLWESecretPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGLWEPublicKeyPrepared<BE> = GLWEPublicKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGLWESecretTensorPrepared<BE> = GLWESecretTensorPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGLWESwitchingKeyPrepared<BE> = GLWESwitchingKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGLWEAutomorphismKeyPrepared<BE> = GLWEAutomorphismKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGLWETensorKeyPrepared<BE> = GLWETensorKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGLWEToLWEKeyPrepared<BE> = GLWEToLWEKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendLWESwitchingKeyPrepared<BE> = LWESwitchingKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendLWEToGLWEKeyPrepared<BE> = LWEToGLWEKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub type BackendGGLWEToGGSWKeyPrepared<BE> = GGLWEToGGSWKeyPrepared<<BE as Backend>::OwnedBuf, BE>;
pub trait GetDegree {
fn ring_degree(&self) -> Degree;
}
impl<B: Backend> GetDegree for Module<B> {
fn ring_degree(&self) -> Degree {
Self::n(self).into()
}
}
pub trait ModuleCoreAlloc {
type OwnedBuf: Data;
fn glwe_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWE<Self::OwnedBuf>;
fn glwe_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWE<Self::OwnedBuf>;
fn gglwe_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWE<Self::OwnedBuf>;
fn gglwe_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWE<Self::OwnedBuf>;
fn ggsw_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSW<Self::OwnedBuf>;
fn ggsw_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> GGSW<Self::OwnedBuf>;
fn glwe_plaintext_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPlaintext<Self::OwnedBuf>;
fn glwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> GLWEPlaintext<Self::OwnedBuf>;
fn glwe_secret_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecret<Self::OwnedBuf>;
fn glwe_secret_alloc(&self, rank: Rank) -> GLWESecret<Self::OwnedBuf>;
fn glwe_secret_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecretTensor<Self::OwnedBuf>;
fn glwe_secret_tensor_alloc(&self, rank: Rank) -> GLWESecretTensor<Self::OwnedBuf>;
fn glwe_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWETensor<Self::OwnedBuf>;
fn glwe_tensor_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWETensor<Self::OwnedBuf>;
fn glwe_public_key_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPublicKey<Self::OwnedBuf>;
fn glwe_public_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKey<Self::OwnedBuf>;
fn glwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKey<Self::OwnedBuf>;
fn glwe_switching_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWESwitchingKey<Self::OwnedBuf>;
fn glwe_automorphism_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEAutomorphismKey<Self::OwnedBuf>;
fn glwe_automorphism_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWEAutomorphismKey<Self::OwnedBuf>;
fn glwe_tensor_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKey<Self::OwnedBuf>;
fn glwe_tensor_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWETensorKey<Self::OwnedBuf>;
fn glwe_to_lwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWEKey<Self::OwnedBuf>;
fn glwe_to_lwe_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum)
-> GLWEToLWEKey<Self::OwnedBuf>;
fn gglwe_to_ggsw_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKey<Self::OwnedBuf>;
fn gglwe_to_ggsw_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWEToGGSWKey<Self::OwnedBuf>;
fn lwe_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWE<Self::OwnedBuf>;
fn lwe_alloc(&self, n: Degree, base2k: Base2K, k: TorusPrecision) -> LWE<Self::OwnedBuf>;
fn lwe_plaintext_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWEPlaintext<Self::OwnedBuf>;
fn lwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWEPlaintext<Self::OwnedBuf>;
fn lwe_secret_alloc(&self, n: Degree) -> LWESecret<Self::OwnedBuf>;
fn lwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKey<Self::OwnedBuf>;
fn lwe_switching_key_alloc(
&self,
n: Degree,
base2k: Base2K,
k: TorusPrecision,
dnum: Dnum,
) -> LWESwitchingKey<Self::OwnedBuf>;
fn lwe_to_glwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKey<Self::OwnedBuf>;
fn lwe_to_glwe_key_alloc(
&self,
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rank_out: Rank,
dnum: Dnum,
) -> LWEToGLWEKey<Self::OwnedBuf>;
}
impl<B: Backend> ModuleCoreAlloc for Module<B> {
type OwnedBuf = B::OwnedBuf;
fn glwe_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWE<B::OwnedBuf> {
let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
GLWE {
data: VecZnx::from_data(
B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(
infos.n().as_usize(),
(infos.rank() + 1).as_usize(),
size,
)),
infos.n().as_usize(),
(infos.rank() + 1).as_usize(),
size,
),
base2k: infos.base2k(),
}
}
fn glwe_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWE<B::OwnedBuf> {
self.glwe_alloc_from_infos(&GLWELayout {
n: self.ring_degree(),
base2k,
k,
rank,
})
}
fn gglwe_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWE<B::OwnedBuf> {
let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
assert!(
size as u32 > infos.dsize().0,
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
infos.dsize().0
);
assert!(
infos.dnum().0 * infos.dsize().0 <= size as u32,
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
infos.dnum().0,
infos.dsize().0,
);
GGLWE {
data: MatZnx::from_data(
B::alloc_zeroed_bytes(MatZnx::<Vec<u8>>::bytes_of(
infos.n().as_usize(),
infos.dnum().as_usize(),
infos.rank_in().as_usize(),
(infos.rank_out() + 1).as_usize(),
size,
)),
infos.n().as_usize(),
infos.dnum().as_usize(),
infos.rank_in().as_usize(),
(infos.rank_out() + 1).as_usize(),
size,
),
base2k: infos.base2k(),
dsize: infos.dsize(),
}
}
fn gglwe_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWE<B::OwnedBuf> {
self.gglwe_alloc_from_infos(&GGLWELayout {
n: self.ring_degree(),
base2k,
k,
rank_in,
rank_out,
dnum,
dsize,
})
}
fn ggsw_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSW<B::OwnedBuf> {
let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
assert!(
size as u32 > infos.dsize().0,
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
infos.dsize().0
);
assert!(
infos.dnum().0 * infos.dsize().0 <= size as u32,
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
infos.dnum().0,
infos.dsize().0,
);
GGSW {
data: MatZnx::from_data(
B::alloc_zeroed_bytes(MatZnx::<Vec<u8>>::bytes_of(
infos.n().as_usize(),
infos.dnum().as_usize(),
(infos.rank() + 1).as_usize(),
(infos.rank() + 1).as_usize(),
size,
)),
infos.n().as_usize(),
infos.dnum().as_usize(),
(infos.rank() + 1).as_usize(),
(infos.rank() + 1).as_usize(),
size,
),
base2k: infos.base2k(),
dsize: infos.dsize(),
}
}
fn ggsw_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> GGSW<B::OwnedBuf> {
self.ggsw_alloc_from_infos(&GGSWLayout {
n: self.ring_degree(),
base2k,
k,
rank,
dnum,
dsize,
})
}
fn glwe_plaintext_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPlaintext<B::OwnedBuf> {
let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
GLWEPlaintext {
data: VecZnx::from_data(
B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), 1, size)),
infos.n().as_usize(),
1,
size,
),
base2k: infos.base2k(),
}
}
fn glwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> GLWEPlaintext<B::OwnedBuf> {
self.glwe_plaintext_alloc_from_infos(&GLWEPlaintextLayout {
n: self.ring_degree(),
base2k,
k,
})
}
fn glwe_secret_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecret<B::OwnedBuf> {
GLWESecret {
data: ScalarZnx::from_data(
B::alloc_zeroed_bytes(ScalarZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), infos.rank().as_usize())),
infos.n().as_usize(),
infos.rank().as_usize(),
),
dist: Distribution::NONE,
}
}
fn glwe_secret_alloc(&self, rank: Rank) -> GLWESecret<B::OwnedBuf> {
self.glwe_secret_alloc_from_infos(&GLWESecretLayout {
n: self.ring_degree(),
rank,
})
}
fn glwe_secret_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWESecretTensor<B::OwnedBuf> {
let pairs = GLWESecretTensor::<Vec<u8>>::pairs(infos.rank().as_usize());
GLWESecretTensor {
data: ScalarZnx::from_data(
B::alloc_zeroed_bytes(ScalarZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), pairs)),
infos.n().as_usize(),
pairs,
),
rank: infos.rank(),
dist: Distribution::NONE,
}
}
fn glwe_secret_tensor_alloc(&self, rank: Rank) -> GLWESecretTensor<B::OwnedBuf> {
self.glwe_secret_tensor_alloc_from_infos(&GLWESecretLayout {
n: self.ring_degree(),
rank,
})
}
fn glwe_tensor_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWETensor<B::OwnedBuf> {
let cols = infos.rank().as_usize() + 1;
let pairs = (((cols + 1) * cols) >> 1).max(1);
let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
GLWETensor {
data: VecZnx::from_data(
B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(infos.n().as_usize(), pairs, size)),
infos.n().as_usize(),
pairs,
size,
),
base2k: infos.base2k(),
rank: infos.rank(),
}
}
fn glwe_tensor_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWETensor<B::OwnedBuf> {
self.glwe_tensor_alloc_from_infos(&GLWELayout {
n: self.ring_degree(),
base2k,
k,
rank,
})
}
fn glwe_public_key_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWEPublicKey<B::OwnedBuf> {
GLWEPublicKey {
key: self.glwe_alloc_from_infos(infos),
dist: Distribution::NONE,
}
}
fn glwe_public_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKey<B::OwnedBuf> {
self.glwe_public_key_alloc_from_infos(&GLWELayout {
n: self.ring_degree(),
base2k,
k,
rank,
})
}
fn glwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKey<B::OwnedBuf> {
GLWESwitchingKey {
key: self.gglwe_alloc_from_infos(infos),
input_degree: Degree(0),
output_degree: Degree(0),
}
}
fn glwe_switching_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWESwitchingKey<B::OwnedBuf> {
self.glwe_switching_key_alloc_from_infos(&GGLWELayout {
n: self.ring_degree(),
base2k,
k,
rank_in,
rank_out,
dnum,
dsize,
})
}
fn glwe_automorphism_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEAutomorphismKey<B::OwnedBuf> {
GLWEAutomorphismKey {
key: self.gglwe_alloc_from_infos(infos),
p: 0,
}
}
fn glwe_automorphism_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWEAutomorphismKey<B::OwnedBuf> {
self.glwe_automorphism_key_alloc_from_infos(&GGLWELayout {
n: self.ring_degree(),
base2k,
k,
rank_in: rank,
rank_out: rank,
dnum,
dsize,
})
}
fn glwe_tensor_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKey<B::OwnedBuf> {
GLWETensorKey(self.gglwe_alloc_from_infos(infos))
}
fn glwe_tensor_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWETensorKey<B::OwnedBuf> {
let pairs = (((rank.0 + 1) * rank.0) >> 1).max(1);
self.glwe_tensor_key_alloc_from_infos(&GGLWELayout {
n: self.ring_degree(),
base2k,
k,
rank_in: Rank(pairs),
rank_out: rank,
dnum,
dsize,
})
}
fn glwe_to_lwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWEKey<B::OwnedBuf> {
assert_eq!(infos.rank_out().0, 1, "rank_out > 1 is not supported for GLWEToLWEKey");
assert_eq!(infos.dsize().0, 1, "dsize > 1 is not supported for GLWEToLWEKey");
GLWEToLWEKey(self.glwe_switching_key_alloc_from_infos(infos))
}
fn glwe_to_lwe_key_alloc(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> GLWEToLWEKey<B::OwnedBuf> {
self.glwe_to_lwe_key_alloc_from_infos(&GGLWELayout {
n: self.ring_degree(),
base2k,
k,
rank_in,
rank_out: Rank(1),
dnum,
dsize: Dsize(1),
})
}
fn gglwe_to_ggsw_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKey<B::OwnedBuf> {
assert_eq!(
infos.rank_in(),
infos.rank_out(),
"rank_in != rank_out is not supported for GGLWEToGGSWKey"
);
GGLWEToGGSWKey {
keys: (0..infos.rank().as_usize())
.map(|_| self.gglwe_alloc_from_infos(infos))
.collect(),
}
}
fn gglwe_to_ggsw_key_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWEToGGSWKey<B::OwnedBuf> {
self.gglwe_to_ggsw_key_alloc_from_infos(&GGLWELayout {
n: self.ring_degree(),
base2k,
k,
rank_in: rank,
rank_out: rank,
dnum,
dsize,
})
}
fn lwe_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWE<B::OwnedBuf> {
let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
let n = infos.n().as_usize();
LWE {
body: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(1, 1, size)), 1, 1, size),
mask: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(n, 1, size)), n, 1, size),
base2k: infos.base2k(),
}
}
fn lwe_alloc(&self, n: Degree, base2k: Base2K, k: TorusPrecision) -> LWE<B::OwnedBuf> {
self.lwe_alloc_from_infos(&LWELayout { n, base2k, k })
}
fn lwe_plaintext_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWEPlaintext<B::OwnedBuf> {
let size = infos.max_k().as_usize().div_ceil(infos.base2k().as_usize());
LWEPlaintext {
data: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(1, 1, size)), 1, 1, size),
base2k: infos.base2k(),
}
}
fn lwe_plaintext_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWEPlaintext<B::OwnedBuf> {
let size = k.as_usize().div_ceil(base2k.as_usize());
LWEPlaintext {
data: VecZnx::from_data(B::alloc_zeroed_bytes(VecZnx::<Vec<u8>>::bytes_of(1, 1, size)), 1, 1, size),
base2k,
}
}
fn lwe_secret_alloc(&self, n: Degree) -> LWESecret<B::OwnedBuf> {
LWESecret {
data: ScalarZnx::from_data(
B::alloc_zeroed_bytes(ScalarZnx::<Vec<u8>>::bytes_of(n.as_usize(), 1)),
n.as_usize(),
1,
),
dist: Distribution::NONE,
}
}
fn lwe_switching_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKey<B::OwnedBuf> {
assert_eq!(infos.dsize().0, 1, "dsize > 1 is not supported for LWESwitchingKey");
assert_eq!(infos.rank_in().0, 1, "rank_in > 1 is not supported for LWESwitchingKey");
assert_eq!(infos.rank_out().0, 1, "rank_out > 1 is not supported for LWESwitchingKey");
LWESwitchingKey(self.glwe_switching_key_alloc_from_infos(infos))
}
fn lwe_switching_key_alloc(&self, n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> LWESwitchingKey<B::OwnedBuf> {
self.lwe_switching_key_alloc_from_infos(&LWESwitchingKeyLayout { n, base2k, k, dnum })
}
fn lwe_to_glwe_key_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKey<B::OwnedBuf> {
assert_eq!(infos.rank_in().0, 1, "rank_in > 1 is not supported for LWEToGLWEKey");
assert_eq!(infos.dsize().0, 1, "dsize > 1 is not supported for LWEToGLWEKey");
LWEToGLWEKey(self.glwe_switching_key_alloc_from_infos(infos))
}
fn lwe_to_glwe_key_alloc(
&self,
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rank_out: Rank,
dnum: Dnum,
) -> LWEToGLWEKey<B::OwnedBuf> {
self.lwe_to_glwe_key_alloc_from_infos(&GGLWELayout {
n,
base2k,
k,
rank_in: Rank(1),
rank_out,
dnum,
dsize: Dsize(1),
})
}
}
pub trait ModuleCoreCompressedAlloc {
fn glwe_compressed_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWECompressed<Vec<u8>>;
fn glwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWECompressed<Vec<u8>>;
fn lwe_compressed_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWECompressed<Vec<u8>>;
fn lwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWECompressed<Vec<u8>>;
fn gglwe_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWECompressed<Vec<u8>>;
fn gglwe_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWECompressed<Vec<u8>>;
fn ggsw_compressed_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSWCompressed<Vec<u8>>;
fn ggsw_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGSWCompressed<Vec<u8>>;
fn glwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKeyCompressed<Vec<u8>>;
fn glwe_switching_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWESwitchingKeyCompressed<Vec<u8>>;
fn glwe_automorphism_key_compressed_alloc_from_infos<A: GGLWEInfos>(
&self,
infos: &A,
) -> GLWEAutomorphismKeyCompressed<Vec<u8>>;
fn glwe_automorphism_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWEAutomorphismKeyCompressed<Vec<u8>>;
fn glwe_tensor_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKeyCompressed<Vec<u8>>;
fn glwe_tensor_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWETensorKeyCompressed<Vec<u8>>;
fn glwe_to_lwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>>;
fn glwe_to_lwe_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
dnum: Dnum,
) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>>;
fn lwe_to_glwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKeyCompressed<Vec<u8>>;
fn lwe_to_glwe_key_compressed_alloc(
&self,
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rank_out: Rank,
dnum: Dnum,
) -> LWEToGLWEKeyCompressed<Vec<u8>>;
fn lwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKeyCompressed<Vec<u8>>;
fn lwe_switching_key_compressed_alloc(
&self,
n: Degree,
base2k: Base2K,
k: TorusPrecision,
dnum: Dnum,
) -> LWESwitchingKeyCompressed<Vec<u8>>;
fn gglwe_to_ggsw_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKeyCompressed<Vec<u8>>;
fn gglwe_to_ggsw_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWEToGGSWKeyCompressed<Vec<u8>>;
}
impl<B: Backend> ModuleCoreCompressedAlloc for Module<B> {
fn glwe_compressed_alloc_from_infos<A: GLWEInfos>(&self, infos: &A) -> GLWECompressed<Vec<u8>> {
GLWECompressed::alloc_from_infos(infos)
}
fn glwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWECompressed<Vec<u8>> {
GLWECompressed::alloc(self.ring_degree(), base2k, k, rank)
}
fn lwe_compressed_alloc_from_infos<A: LWEInfos>(&self, infos: &A) -> LWECompressed<Vec<u8>> {
LWECompressed::alloc_from_infos(infos)
}
fn lwe_compressed_alloc(&self, base2k: Base2K, k: TorusPrecision) -> LWECompressed<Vec<u8>> {
LWECompressed::alloc(base2k, k)
}
fn gglwe_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWECompressed<Vec<u8>> {
GGLWECompressed::alloc_from_infos(infos)
}
fn gglwe_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWECompressed<Vec<u8>> {
GGLWECompressed::alloc(self.ring_degree(), base2k, k, rank_in, rank_out, dnum, dsize)
}
fn ggsw_compressed_alloc_from_infos<A: GGSWInfos>(&self, infos: &A) -> GGSWCompressed<Vec<u8>> {
GGSWCompressed::alloc_from_infos(infos)
}
fn ggsw_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGSWCompressed<Vec<u8>> {
GGSWCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
}
fn glwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWESwitchingKeyCompressed<Vec<u8>> {
GLWESwitchingKeyCompressed::alloc_from_infos(infos)
}
fn glwe_switching_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
rank_out: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWESwitchingKeyCompressed<Vec<u8>> {
GLWESwitchingKeyCompressed::alloc(self.ring_degree(), base2k, k, rank_in, rank_out, dnum, dsize)
}
fn glwe_automorphism_key_compressed_alloc_from_infos<A: GGLWEInfos>(
&self,
infos: &A,
) -> GLWEAutomorphismKeyCompressed<Vec<u8>> {
GLWEAutomorphismKeyCompressed::alloc_from_infos(infos)
}
fn glwe_automorphism_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWEAutomorphismKeyCompressed<Vec<u8>> {
GLWEAutomorphismKeyCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
}
fn glwe_tensor_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWETensorKeyCompressed<Vec<u8>> {
GLWETensorKeyCompressed::alloc_from_infos(infos)
}
fn glwe_tensor_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GLWETensorKeyCompressed<Vec<u8>> {
GLWETensorKeyCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
}
fn glwe_to_lwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
GLWEToLWESwitchingKeyCompressed::alloc_from_infos(infos)
}
fn glwe_to_lwe_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank_in: Rank,
dnum: Dnum,
) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
GLWEToLWESwitchingKeyCompressed::alloc(self.ring_degree(), base2k, k, rank_in, dnum)
}
fn lwe_to_glwe_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWEToGLWEKeyCompressed<Vec<u8>> {
LWEToGLWEKeyCompressed::alloc_from_infos(infos)
}
fn lwe_to_glwe_key_compressed_alloc(
&self,
n: Degree,
base2k: Base2K,
k: TorusPrecision,
rank_out: Rank,
dnum: Dnum,
) -> LWEToGLWEKeyCompressed<Vec<u8>> {
LWEToGLWEKeyCompressed::alloc(n, base2k, k, rank_out, dnum)
}
fn lwe_switching_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> LWESwitchingKeyCompressed<Vec<u8>> {
LWESwitchingKeyCompressed::alloc_from_infos(infos)
}
fn lwe_switching_key_compressed_alloc(
&self,
n: Degree,
base2k: Base2K,
k: TorusPrecision,
dnum: Dnum,
) -> LWESwitchingKeyCompressed<Vec<u8>> {
LWESwitchingKeyCompressed::alloc(n, base2k, k, dnum)
}
fn gglwe_to_ggsw_key_compressed_alloc_from_infos<A: GGLWEInfos>(&self, infos: &A) -> GGLWEToGGSWKeyCompressed<Vec<u8>> {
GGLWEToGGSWKeyCompressed::alloc_from_infos(infos)
}
fn gglwe_to_ggsw_key_compressed_alloc(
&self,
base2k: Base2K,
k: TorusPrecision,
rank: Rank,
dnum: Dnum,
dsize: Dsize,
) -> GGLWEToGGSWKeyCompressed<Vec<u8>> {
GGLWEToGGSWKeyCompressed::alloc(self.ring_degree(), base2k, k, rank, dnum, dsize)
}
}
macro_rules! newtype_u32 {
($(#[$meta:meta])* $name:ident) => {
$(#[$meta])*
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct $name(pub u32);
impl From<$name> for u32 {
#[inline]
fn from(v: $name) -> u32 {
v.0
}
}
impl From<$name> for usize {
#[inline]
fn from(v: $name) -> usize {
v.0 as usize
}
}
impl From<u32> for $name {
#[inline]
fn from(v: u32) -> $name {
$name(v)
}
}
impl From<usize> for $name {
#[inline]
fn from(v: usize) -> $name {
debug_assert!(v <= u32::MAX as usize, "{} overflow: {v} > u32::MAX", stringify!($name));
$name(v as u32)
}
}
impl ::core::fmt::Display for $name {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "{}", self.0)
}
}
impl ::core::ops::Add for $name {
type Output = $name;
#[inline]
fn add(self, rhs: $name) -> $name {
$name(self.0.saturating_add(rhs.0))
}
}
impl ::core::ops::Sub for $name {
type Output = $name;
#[inline]
fn sub(self, rhs: $name) -> $name {
$name(self.0.saturating_sub(rhs.0))
}
}
impl ::core::ops::Mul for $name {
type Output = $name;
#[inline]
fn mul(self, rhs: $name) -> $name {
$name(self.0.saturating_mul(rhs.0))
}
}
impl ::core::ops::Add<u32> for $name {
type Output = $name;
#[inline]
fn add(self, rhs: u32) -> $name {
$name(self.0.saturating_add(rhs))
}
}
impl ::core::ops::Sub<u32> for $name {
type Output = $name;
#[inline]
fn sub(self, rhs: u32) -> $name {
$name(self.0.saturating_sub(rhs))
}
}
impl ::core::ops::Mul<u32> for $name {
type Output = $name;
#[inline]
fn mul(self, rhs: u32) -> $name {
$name(self.0.saturating_mul(rhs))
}
}
impl $name {
#[inline]
pub const fn as_u32(self) -> u32 {
self.0
}
#[inline]
pub const fn as_usize(self) -> usize {
self.0 as usize
}
#[inline]
pub fn div_ceil<T: Into<u32>>(self, rhs: T) -> u32 {
self.0.div_ceil(rhs.into())
}
}
impl ::core::ops::Add<$name> for u32 {
type Output = $name;
#[inline]
fn add(self, rhs: $name) -> $name {
$name(self.saturating_add(rhs.0))
}
}
impl ::core::ops::Sub<$name> for u32 {
type Output = $name;
#[inline]
fn sub(self, rhs: $name) -> $name {
$name(self.saturating_sub(rhs.0))
}
}
impl ::core::ops::Mul<$name> for u32 {
type Output = $name;
#[inline]
fn mul(self, rhs: $name) -> $name {
$name(self.saturating_mul(rhs.0))
}
}
impl ::core::cmp::PartialEq<u32> for $name {
#[inline]
fn eq(&self, other: &u32) -> bool {
self.0 == *other
}
}
impl ::core::cmp::PartialEq<$name> for u32 {
#[inline]
fn eq(&self, other: &$name) -> bool {
*self == other.0
}
}
impl ::core::cmp::PartialOrd<u32> for $name {
#[inline]
fn partial_cmp(&self, other: &u32) -> Option<::core::cmp::Ordering> {
self.0.partial_cmp(other)
}
}
impl ::core::cmp::PartialOrd<$name> for u32 {
#[inline]
fn partial_cmp(&self, other: &$name) -> Option<::core::cmp::Ordering> {
self.partial_cmp(&other.0)
}
}
};
}
newtype_u32!(
Degree
);
newtype_u32!(
TorusPrecision
);
newtype_u32!(
Base2K
);
newtype_u32!(
Dnum
);
newtype_u32!(
Rank
);
newtype_u32!(
Dsize
);
impl Degree {
pub fn log2(&self) -> usize {
debug_assert!(
self.0 > 0 && self.0.is_power_of_two(),
"Degree::log2 requires a positive power of two, got {}",
self.0
);
self.0.trailing_zeros() as usize
}
}