mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
wip
This commit is contained in:
committed by
Jean-Philippe Bossuat
parent
f72363cc4b
commit
2b2b994f7d
@@ -1,24 +1,28 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
compressed::{Decompress, GGLWESwitchingKeyCompressed},
|
||||
AutomorphismKey, AutomorphismKeyToMut, Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree,
|
||||
TorusPrecision,
|
||||
compressed::{
|
||||
GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut,
|
||||
GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress,
|
||||
},
|
||||
prepared::{GetAutomorphismGaloisElement, SetAutomorphismGaloisElement},
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWEAutomorphismKeyCompressed<D: Data> {
|
||||
pub(crate) key: GGLWESwitchingKeyCompressed<D>,
|
||||
pub struct AutomorphismKeyCompressed<D: Data> {
|
||||
pub(crate) key: GLWESwitchingKeyCompressed<D>,
|
||||
pub(crate) p: i64,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWEAutomorphismKeyCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: Data> LWEInfos for AutomorphismKeyCompressed<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.key.n()
|
||||
}
|
||||
|
||||
@@ -34,13 +38,13 @@ impl<D: Data> LWEInfos for GGLWEAutomorphismKeyCompressed<D> {
|
||||
self.key.size()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for GGLWEAutomorphismKeyCompressed<D> {
|
||||
impl<D: Data> GLWEInfos for AutomorphismKeyCompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWEAutomorphismKeyCompressed<D> {
|
||||
impl<D: Data> GGLWEInfos for AutomorphismKeyCompressed<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.key.rank_in()
|
||||
}
|
||||
@@ -58,76 +62,185 @@ impl<D: Data> GGLWEInfos for GGLWEAutomorphismKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWEAutomorphismKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for AutomorphismKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWEAutomorphismKeyCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for AutomorphismKeyCompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.key.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWEAutomorphismKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for AutomorphismKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(AutomorphismKeyCompressed: p={}) {}", self.p, self.key)
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEAutomorphismKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(infos.rank_in(), infos.rank_out());
|
||||
Self {
|
||||
key: GGLWESwitchingKeyCompressed::alloc(infos),
|
||||
pub trait AutomorphismKeyCompressedAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
fn alloc_automorphism_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> AutomorphismKeyCompressed<Vec<u8>> {
|
||||
AutomorphismKeyCompressed {
|
||||
key: self.alloc_glwe_switching_key_compressed(base2k, k, rank, rank, dnum, dsize),
|
||||
p: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
Self {
|
||||
key: GGLWESwitchingKeyCompressed::alloc_with(n, base2k, k, rank, rank, dnum, dsize),
|
||||
p: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_automorphism_key_compressed_from_infos<A>(&self, infos: &A) -> AutomorphismKeyCompressed<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(infos.rank_in(), infos.rank_out());
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
|
||||
assert_eq!(infos.rank_in(), infos.rank_out());
|
||||
self.alloc_automorphism_key_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rank, dnum, dsize)
|
||||
fn bytes_of_automorphism_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize {
|
||||
self.bytes_of_glwe_switching_key_compressed(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
fn bytes_of_automorphism_key_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(infos.rank_in(), infos.rank_out());
|
||||
self.bytes_of_automorphism_key_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWEAutomorphismKeyCompressed<D> {
|
||||
impl AutomorphismKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: AutomorphismKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_automorphism_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
M: AutomorphismKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_automorphism_key_compressed(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: AutomorphismKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_automorphism_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: AutomorphismKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_automorphism_key_compressed(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for AutomorphismKeyCompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.p = reader.read_u64::<LittleEndian>()? as i64;
|
||||
self.key.read_from(reader)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWEAutomorphismKeyCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for AutomorphismKeyCompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u64::<LittleEndian>(self.p as u64)?;
|
||||
self.key.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWEAutomorphismKeyCompressed<DR>> for GGLWEAutomorphismKey<D>
|
||||
pub trait AutomorphismKeyDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKeyCompressed<DR>) {
|
||||
self.key.decompress(module, &other.key);
|
||||
self.p = other.p;
|
||||
fn decompress_automorphism_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: AutomorphismKeyToMut + SetAutomorphismGaloisElement,
|
||||
O: AutomorphismKeyCompressedToRef + GetAutomorphismGaloisElement,
|
||||
{
|
||||
self.decompress_glwe_switching_key(&mut res.to_mut().key, &other.to_ref().key);
|
||||
res.set_p(other.p());
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> AutomorphismKeyDecompress for Module<B> where Self: AutomorphismKeyDecompress {}
|
||||
|
||||
impl<D: DataMut> AutomorphismKey<D>
|
||||
where
|
||||
Self: SetAutomorphismGaloisElement,
|
||||
{
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: AutomorphismKeyCompressedToRef + GetAutomorphismGaloisElement,
|
||||
M: AutomorphismKeyDecompress,
|
||||
{
|
||||
module.decompress_automorphism_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AutomorphismKeyCompressedToRef {
|
||||
fn to_ref(&self) -> AutomorphismKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> AutomorphismKeyCompressedToRef for AutomorphismKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> AutomorphismKeyCompressed<&[u8]> {
|
||||
AutomorphismKeyCompressed {
|
||||
key: self.key.to_ref(),
|
||||
p: self.p,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AutomorphismKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> AutomorphismKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> AutomorphismKeyCompressedToMut for AutomorphismKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> AutomorphismKeyCompressed<&mut [u8]> {
|
||||
AutomorphismKeyCompressed {
|
||||
p: self.p,
|
||||
key: self.key.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, MatZnx, Module, ReaderFrom, WriterTo, ZnxInfos},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
compressed::{Decompress, GLWECiphertextCompressed},
|
||||
Base2K, Dnum, Dsize, GGLWE, GGLWEInfos, GGLWEToMut, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
compressed::{GLWECompressed, GLWEDecompress},
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWECiphertextCompressed<D: Data> {
|
||||
pub struct GGLWECompressed<D: Data> {
|
||||
pub(crate) data: MatZnx<D>,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) k: TorusPrecision,
|
||||
@@ -21,9 +23,9 @@ pub struct GGLWECiphertextCompressed<D: Data> {
|
||||
pub(crate) seed: Vec<[u8; 32]>,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWECiphertextCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
impl<D: Data> LWEInfos for GGLWECompressed<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -38,13 +40,13 @@ impl<D: Data> LWEInfos for GGLWECiphertextCompressed<D> {
|
||||
self.data.size()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for GGLWECiphertextCompressed<D> {
|
||||
impl<D: Data> GLWEInfos for GGLWECompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWECiphertextCompressed<D> {
|
||||
impl<D: Data> GGLWEInfos for GGLWECompressed<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
Rank(self.data.cols_in() as u32)
|
||||
}
|
||||
@@ -62,53 +64,41 @@ impl<D: Data> GGLWEInfos for GGLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for GGLWECompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWECiphertextCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for GGLWECompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.data.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for GGLWECompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"(GGLWECiphertextCompressed: base2k={} k={} dsize={}) {}",
|
||||
"(GGLWECompressed: base2k={} k={} dsize={}) {}",
|
||||
self.base2k.0, self.k.0, self.dsize.0, self.data
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWECiphertextCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
Self::alloc_with(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(
|
||||
n: Degree,
|
||||
pub trait GGLWECompressedAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_gglwe_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self {
|
||||
) -> GGLWECompressed<Vec<u8>> {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
@@ -123,9 +113,9 @@ impl GGLWECiphertextCompressed<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
GGLWECompressed {
|
||||
data: MatZnx::alloc(
|
||||
n.into(),
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
rank_in.into(),
|
||||
1,
|
||||
@@ -139,21 +129,22 @@ impl GGLWECiphertextCompressed<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_gglwe_compressed_from_infos<A>(&self, infos: &A) -> GGLWECompressed<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(
|
||||
infos.n(),
|
||||
assert_eq!(infos.n(), self.ring_degree());
|
||||
self.alloc_gglwe_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
fn bytes_of_gglwe_compressed(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
@@ -168,20 +159,76 @@ impl GGLWECiphertextCompressed<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
MatZnx::alloc_bytes(
|
||||
n.into(),
|
||||
MatZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
rank_in.into(),
|
||||
1,
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_gglwe_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(infos.n(), self.ring_degree());
|
||||
self.bytes_of_gglwe_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWECiphertextCompressed<D> {
|
||||
pub(crate) fn at(&self, row: usize, col: usize) -> GLWECiphertextCompressed<&[u8]> {
|
||||
impl<B: Backend> GGLWECompressedAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
impl GGLWECompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GGLWECompressedAlloc,
|
||||
{
|
||||
module.alloc_gglwe_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self
|
||||
where
|
||||
M: GGLWECompressedAlloc,
|
||||
{
|
||||
module.alloc_gglwe_compressed(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GGLWECompressedAlloc,
|
||||
{
|
||||
module.bytes_of_gglwe_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn byte_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: GGLWECompressedAlloc,
|
||||
{
|
||||
module.bytes_of_gglwe_compressed(base2k, k, rank_in, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWECompressed<D> {
|
||||
pub(crate) fn at(&self, row: usize, col: usize) -> GLWECompressed<&[u8]> {
|
||||
let rank_in: usize = self.rank_in().into();
|
||||
GLWECiphertextCompressed {
|
||||
GLWECompressed {
|
||||
data: self.data.at(row, col),
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
@@ -191,10 +238,10 @@ impl<D: DataRef> GGLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWECiphertextCompressed<D> {
|
||||
pub(crate) fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertextCompressed<&mut [u8]> {
|
||||
impl<D: DataMut> GGLWECompressed<D> {
|
||||
pub(crate) fn at_mut(&mut self, row: usize, col: usize) -> GLWECompressed<&mut [u8]> {
|
||||
let rank_in: usize = self.rank_in().into();
|
||||
GLWECiphertextCompressed {
|
||||
GLWECompressed {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
rank: self.rank_out,
|
||||
@@ -204,7 +251,7 @@ impl<D: DataMut> GGLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWECiphertextCompressed<D> {
|
||||
impl<D: DataMut> ReaderFrom for GGLWECompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -219,7 +266,7 @@ impl<D: DataMut> ReaderFrom for GGLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for GGLWECompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.into())?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.into())?;
|
||||
@@ -233,59 +280,73 @@ impl<D: DataRef> WriterTo for GGLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GGLWECiphertextCompressed<DR>> for GGLWECiphertext<D>
|
||||
pub trait GGLWEDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GLWEDecompress,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &GGLWECiphertextCompressed<DR>) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(
|
||||
self.n(),
|
||||
other.n(),
|
||||
"invalid receiver: self.n()={} != other.n()={}",
|
||||
self.n(),
|
||||
other.n()
|
||||
);
|
||||
assert_eq!(
|
||||
self.size(),
|
||||
other.size(),
|
||||
"invalid receiver: self.size()={} != other.size()={}",
|
||||
self.size(),
|
||||
other.size()
|
||||
);
|
||||
assert_eq!(
|
||||
self.rank_in(),
|
||||
other.rank_in(),
|
||||
"invalid receiver: self.rank_in()={} != other.rank_in()={}",
|
||||
self.rank_in(),
|
||||
other.rank_in()
|
||||
);
|
||||
assert_eq!(
|
||||
self.rank_out(),
|
||||
other.rank_out(),
|
||||
"invalid receiver: self.rank_out()={} != other.rank_out()={}",
|
||||
self.rank_out(),
|
||||
other.rank_out()
|
||||
);
|
||||
fn decompress_gglwe<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GGLWEToMut,
|
||||
O: GGLWECompressedToRef,
|
||||
{
|
||||
let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut();
|
||||
let other: &GGLWECompressed<&[u8]> = &other.to_ref();
|
||||
|
||||
assert_eq!(
|
||||
self.dnum(),
|
||||
other.dnum(),
|
||||
"invalid receiver: self.dnum()={} != other.dnum()={}",
|
||||
self.dnum(),
|
||||
other.dnum()
|
||||
);
|
||||
assert_eq!(res.gglwe_layout(), other.gglwe_layout());
|
||||
|
||||
let rank_in: usize = res.rank_in().into();
|
||||
let dnum: usize = res.dnum().into();
|
||||
|
||||
for row_i in 0..dnum {
|
||||
for col_i in 0..rank_in {
|
||||
self.decompress_glwe(&mut res.at_mut(row_i, col_i), &other.at(row_i, col_i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGLWEDecompress for Module<B> where Self: VecZnxFillUniform + VecZnxCopy {}
|
||||
|
||||
impl<D: DataMut> GGLWE<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GGLWECompressedToRef,
|
||||
M: GGLWEDecompress,
|
||||
{
|
||||
module.decompress_gglwe(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWECompressedToMut {
|
||||
fn to_mut(&mut self) -> GGLWECompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWECompressedToMut for GGLWECompressed<D> {
|
||||
fn to_mut(&mut self) -> GGLWECompressed<&mut [u8]> {
|
||||
GGLWECompressed {
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
dsize: self.dsize(),
|
||||
seed: self.seed.clone(),
|
||||
rank_out: self.rank_out,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWECompressedToRef {
|
||||
fn to_ref(&self) -> GGLWECompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWECompressedToRef for GGLWECompressed<D> {
|
||||
fn to_ref(&self) -> GGLWECompressed<&[u8]> {
|
||||
GGLWECompressed {
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
dsize: self.dsize(),
|
||||
seed: self.seed.clone(),
|
||||
rank_out: self.rank_out,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
|
||||
let rank_in: usize = self.rank_in().into();
|
||||
let dnum: usize = self.dnum().into();
|
||||
|
||||
(0..rank_in).for_each(|col_i| {
|
||||
(0..dnum).for_each(|row_i| {
|
||||
self.at_mut(row_i, col_i)
|
||||
.decompress(module, &other.at(row_i, col_i));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
compressed::{Decompress, GGLWECiphertextCompressed},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeySetMetaData, GLWESwitchingKeyToMut, LWEInfos,
|
||||
Rank, RingDegree, TorusPrecision,
|
||||
compressed::{GGLWECompressed, GGLWECompressedAlloc, GGLWECompressedToMut, GGLWECompressedToRef, GGLWEDecompress},
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWESwitchingKeyCompressed<D: Data> {
|
||||
pub(crate) key: GGLWECiphertextCompressed<D>,
|
||||
pub struct GLWESwitchingKeyCompressed<D: Data> {
|
||||
pub(crate) key: GGLWECompressed<D>,
|
||||
pub(crate) sk_in_n: usize, // Degree of sk_in
|
||||
pub(crate) sk_out_n: usize, // Degree of sk_out
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWESwitchingKeyCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: Data> LWEInfos for GLWESwitchingKeyCompressed<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.key.n()
|
||||
}
|
||||
|
||||
@@ -35,13 +35,13 @@ impl<D: Data> LWEInfos for GGLWESwitchingKeyCompressed<D> {
|
||||
self.key.size()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for GGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: Data> GLWEInfos for GLWESwitchingKeyCompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: Data> GGLWEInfos for GLWESwitchingKeyCompressed<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.key.rank_in()
|
||||
}
|
||||
@@ -59,19 +59,19 @@ impl<D: Data> GGLWEInfos for GGLWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for GLWESwitchingKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for GLWESwitchingKeyCompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.key.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for GLWESwitchingKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
@@ -81,47 +81,100 @@ impl<D: DataRef> fmt::Display for GGLWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
GGLWESwitchingKeyCompressed {
|
||||
key: GGLWECiphertextCompressed::alloc(infos),
|
||||
sk_in_n: 0,
|
||||
sk_out_n: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_with(
|
||||
n: Degree,
|
||||
pub trait GLWESwitchingKeyCompressedAlloc
|
||||
where
|
||||
Self: GGLWECompressedAlloc,
|
||||
{
|
||||
fn alloc_glwe_switching_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self {
|
||||
GGLWESwitchingKeyCompressed {
|
||||
key: GGLWECiphertextCompressed::alloc_with(n, base2k, k, rank_in, rank_out, dnum, dsize),
|
||||
) -> GLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
GLWESwitchingKeyCompressed {
|
||||
key: self.alloc_gglwe_compressed(base2k, k, rank_in, rank_out, dnum, dsize),
|
||||
sk_in_n: 0,
|
||||
sk_out_n: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> GLWESwitchingKeyCompressed<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
GGLWECiphertextCompressed::alloc_bytes(infos)
|
||||
self.alloc_glwe_switching_key_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
GGLWECiphertextCompressed::alloc_bytes_with(n, base2k, k, rank_in, dnum, dsize)
|
||||
fn bytes_of_glwe_switching_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize {
|
||||
self.bytes_of_gglwe_compressed(base2k, k, rank_in, dnum, dsize)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.bytes_of_gglwe_compressed_from_infos(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWESwitchingKeyCompressed<D> {
|
||||
impl GLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_glwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self
|
||||
where
|
||||
M: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_glwe_switching_key_compressed(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_switching_key_compressed(base2k, k, rank_in, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWESwitchingKeyCompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize;
|
||||
self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize;
|
||||
@@ -129,7 +182,7 @@ impl<D: DataMut> ReaderFrom for GGLWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for GLWESwitchingKeyCompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?;
|
||||
writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?;
|
||||
@@ -137,13 +190,64 @@ impl<D: DataRef> WriterTo for GGLWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWESwitchingKeyCompressed<DR>> for GGLWESwitchingKey<D>
|
||||
pub trait GLWESwitchingKeyDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GGLWEDecompress,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &GGLWESwitchingKeyCompressed<DR>) {
|
||||
self.key.decompress(module, &other.key);
|
||||
self.sk_in_n = other.sk_in_n;
|
||||
self.sk_out_n = other.sk_out_n;
|
||||
fn decompress_glwe_switching_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GLWESwitchingKeyToMut + GLWESwitchingKeySetMetaData,
|
||||
O: GLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
let other: &GLWESwitchingKeyCompressed<&[u8]> = &other.to_ref();
|
||||
self.decompress_gglwe(&mut res.to_mut().key, &other.key);
|
||||
res.set_sk_in_n(other.sk_in_n);
|
||||
res.set_sk_out_n(other.sk_out_n);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWESwitchingKeyDecompress for Module<B> where Self: GGLWEDecompress {}
|
||||
|
||||
impl<D: DataMut> GLWESwitchingKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GLWESwitchingKeyCompressedToRef,
|
||||
M: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
module.decompress_glwe_switching_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESwitchingKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> GLWESwitchingKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESwitchingKeyCompressedToMut for GLWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GGLWECompressed<D>: GGLWECompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWESwitchingKeyCompressed<&mut [u8]> {
|
||||
GLWESwitchingKeyCompressed {
|
||||
sk_in_n: self.sk_in_n,
|
||||
sk_out_n: self.sk_out_n,
|
||||
key: self.key.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESwitchingKeyCompressedToRef {
|
||||
fn to_ref(&self) -> GLWESwitchingKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESwitchingKeyCompressedToRef for GLWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GGLWECompressed<D>: GGLWECompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GLWESwitchingKeyCompressed<&[u8]> {
|
||||
GLWESwitchingKeyCompressed {
|
||||
sk_in_n: self.sk_in_n,
|
||||
sk_out_n: self.sk_out_n,
|
||||
key: self.key.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
compressed::{Decompress, GGLWESwitchingKeyCompressed},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree, TensorKey, TensorKeyToMut, TorusPrecision,
|
||||
compressed::{
|
||||
GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut,
|
||||
GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress,
|
||||
},
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWETensorKeyCompressed<D: Data> {
|
||||
pub(crate) keys: Vec<GGLWESwitchingKeyCompressed<D>>,
|
||||
pub struct TensorKeyCompressed<D: Data> {
|
||||
pub(crate) keys: Vec<GLWESwitchingKeyCompressed<D>>,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWETensorKeyCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: Data> LWEInfos for TensorKeyCompressed<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
@@ -32,13 +34,13 @@ impl<D: Data> LWEInfos for GGLWETensorKeyCompressed<D> {
|
||||
self.keys[0].size()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for GGLWETensorKeyCompressed<D> {
|
||||
impl<D: Data> GLWEInfos for TensorKeyCompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWETensorKeyCompressed<D> {
|
||||
impl<D: Data> GGLWEInfos for TensorKeyCompressed<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
@@ -56,21 +58,21 @@ impl<D: Data> GGLWEInfos for GGLWETensorKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWETensorKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for TensorKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWETensorKeyCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for TensorKeyCompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.for_each(|key: &mut GGLWESwitchingKeyCompressed<D>| key.fill_uniform(log_bound, source))
|
||||
.for_each(|key: &mut GLWESwitchingKeyCompressed<D>| key.fill_uniform(log_bound, source))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWETensorKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for TensorKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "(GLWETensorKeyCompressed)",)?;
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
@@ -80,8 +82,27 @@ impl<D: DataRef> fmt::Display for GGLWETensorKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWETensorKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub trait TensorKeyCompressedAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
fn alloc_tensor_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> TensorKeyCompressed<Vec<u8>> {
|
||||
let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
|
||||
TensorKeyCompressed {
|
||||
keys: (0..pairs)
|
||||
.map(|_| self.alloc_glwe_switching_key_compressed(base2k, k, Rank(1), rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_tensor_key_compressed_from_infos<A>(&self, infos: &A) -> TensorKeyCompressed<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
@@ -90,62 +111,67 @@ impl GGLWETensorKeyCompressed<Vec<u8>> {
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWETensorKeyCompressed"
|
||||
);
|
||||
Self::alloc_with(
|
||||
infos.n(),
|
||||
self.alloc_tensor_key_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_out(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
let mut keys: Vec<GGLWESwitchingKeyCompressed<Vec<u8>>> = Vec::new();
|
||||
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
|
||||
(0..pairs).for_each(|_| {
|
||||
keys.push(GGLWESwitchingKeyCompressed::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
rank,
|
||||
dnum,
|
||||
dsize,
|
||||
));
|
||||
});
|
||||
Self { keys }
|
||||
fn bytes_of_tensor_key_compressed(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
|
||||
pairs * self.bytes_of_glwe_switching_key_compressed(base2k, k, Rank(1), dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn bytes_of_tensor_key_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWETensorKeyCompressed"
|
||||
);
|
||||
let rank_out: usize = infos.rank_out().into();
|
||||
let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1);
|
||||
pairs
|
||||
* GGLWESwitchingKeyCompressed::alloc_bytes_with(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
Rank(1),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
|
||||
pairs * GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, dsize)
|
||||
self.bytes_of_tensor_key_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWETensorKeyCompressed<D> {
|
||||
impl TensorKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: TensorKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_tensor_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
M: TensorKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_tensor_key_compressed(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: TensorKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_tensor_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: TensorKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_tensor_key_compressed(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for TensorKeyCompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
let len: usize = reader.read_u64::<LittleEndian>()? as usize;
|
||||
if self.keys.len() != len {
|
||||
@@ -161,7 +187,7 @@ impl<D: DataMut> ReaderFrom for GGLWETensorKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWETensorKeyCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for TensorKeyCompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u64::<LittleEndian>(self.keys.len() as u64)?;
|
||||
for key in &self.keys {
|
||||
@@ -171,8 +197,8 @@ impl<D: DataRef> WriterTo for GGLWETensorKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWETensorKeyCompressed<D> {
|
||||
pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataMut> TensorKeyCompressed<D> {
|
||||
pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyCompressed<D> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
@@ -181,27 +207,70 @@ impl<D: DataMut> GGLWETensorKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWETensorKeyCompressed<DR>> for GGLWETensorKey<D>
|
||||
pub trait TensorKeyDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &GGLWETensorKeyCompressed<DR>) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(
|
||||
self.keys.len(),
|
||||
other.keys.len(),
|
||||
"invalid receiver: self.keys.len()={} != other.keys.len()={}",
|
||||
self.keys.len(),
|
||||
other.keys.len()
|
||||
);
|
||||
}
|
||||
fn decompress_tensor_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: TensorKeyToMut,
|
||||
O: TensorKeyCompressedToRef,
|
||||
{
|
||||
let res: &mut TensorKey<&mut [u8]> = &mut res.to_mut();
|
||||
let other: &TensorKeyCompressed<&[u8]> = &other.to_ref();
|
||||
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.zip(other.keys.iter())
|
||||
.for_each(|(a, b)| {
|
||||
a.decompress(module, b);
|
||||
});
|
||||
assert_eq!(
|
||||
res.keys.len(),
|
||||
other.keys.len(),
|
||||
"invalid receiver: res.keys.len()={} != other.keys.len()={}",
|
||||
res.keys.len(),
|
||||
other.keys.len()
|
||||
);
|
||||
|
||||
for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) {
|
||||
self.decompress_glwe_switching_key(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> TensorKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
|
||||
|
||||
impl<D: DataMut> TensorKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: TensorKeyCompressedToRef,
|
||||
M: TensorKeyDecompress,
|
||||
{
|
||||
module.decompress_tensor_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TensorKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> TensorKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> TensorKeyCompressedToMut for TensorKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> TensorKeyCompressed<&mut [u8]> {
|
||||
TensorKeyCompressed {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TensorKeyCompressedToRef {
|
||||
fn to_ref(&self) -> TensorKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> TensorKeyCompressedToRef for TensorKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> TensorKeyCompressed<&[u8]> {
|
||||
TensorKeyCompressed {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, MatZnx, Module, ReaderFrom, WriterTo, ZnxInfos},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
compressed::{Decompress, GLWECiphertextCompressed},
|
||||
Base2K, Dnum, Dsize, GGSW, GGSWInfos, GGSWToMut, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
compressed::{GLWECompressed, GLWEDecompress},
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGSWCiphertextCompressed<D: Data> {
|
||||
pub struct GGSWCompressed<D: Data> {
|
||||
pub(crate) data: MatZnx<D>,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) base2k: Base2K,
|
||||
@@ -21,9 +22,9 @@ pub struct GGSWCiphertextCompressed<D: Data> {
|
||||
pub(crate) seed: Vec<[u8; 32]>,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGSWCiphertextCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
impl<D: Data> LWEInfos for GGSWCompressed<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -37,13 +38,13 @@ impl<D: Data> LWEInfos for GGSWCiphertextCompressed<D> {
|
||||
self.data.size()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for GGSWCiphertextCompressed<D> {
|
||||
impl<D: Data> GLWEInfos for GGSWCompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGSWInfos for GGSWCiphertextCompressed<D> {
|
||||
impl<D: Data> GGSWInfos for GGSWCompressed<D> {
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.dsize
|
||||
}
|
||||
@@ -53,46 +54,42 @@ impl<D: Data> GGSWInfos for GGSWCiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGSWCiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for GGSWCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGSWCiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for GGSWCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"(GGSWCiphertextCompressed: base2k={} k={} dsize={}) {}",
|
||||
"(GGSWCompressed: base2k={} k={} dsize={}) {}",
|
||||
self.base2k, self.k, self.dsize, self.data
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGSWCiphertextCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for GGSWCompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.data.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl GGSWCiphertextCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
Self::alloc_with(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
pub trait GGSWCompressedAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_ggsw_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> GGSWCompressed<Vec<u8>> {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
assert!(
|
||||
size as u32 > dsize.0,
|
||||
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
|
||||
dsize.0
|
||||
@@ -105,9 +102,9 @@ impl GGSWCiphertextCompressed<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
GGSWCompressed {
|
||||
data: MatZnx::alloc(
|
||||
n.into(),
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
(rank + 1).into(),
|
||||
1,
|
||||
@@ -121,12 +118,11 @@ impl GGSWCiphertextCompressed<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_ggsw_compressed_from_infos<A>(&self, infos: &A) -> GGSWCompressed<Vec<u8>>
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(
|
||||
infos.n(),
|
||||
self.alloc_ggsw_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
@@ -135,9 +131,9 @@ impl GGSWCiphertextCompressed<Vec<u8>> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
fn bytes_of_ggsw_compressed(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
assert!(
|
||||
size as u32 > dsize.0,
|
||||
"invalid ggsw: ceil(k/base2k): {size} <= dsize: {}",
|
||||
dsize.0
|
||||
@@ -150,20 +146,65 @@ impl GGSWCiphertextCompressed<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
MatZnx::alloc_bytes(
|
||||
n.into(),
|
||||
MatZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
(rank + 1).into(),
|
||||
1,
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_ggsw_compressed_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
self.bytes_of_ggsw_compressed(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGSWCiphertextCompressed<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWECiphertextCompressed<&[u8]> {
|
||||
impl GGSWCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: GGSWCompressedAlloc,
|
||||
{
|
||||
module.alloc_ggsw_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
M: GGSWCompressedAlloc,
|
||||
{
|
||||
module.alloc_ggsw_compressed(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: GGSWCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_ggsw_compressed_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: GGSWCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_ggsw_compressed(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGSWCompressed<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWECompressed<&[u8]> {
|
||||
let rank: usize = self.rank().into();
|
||||
GLWECiphertextCompressed {
|
||||
GLWECompressed {
|
||||
data: self.data.at(row, col),
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
@@ -173,10 +214,10 @@ impl<D: DataRef> GGSWCiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGSWCiphertextCompressed<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertextCompressed<&mut [u8]> {
|
||||
impl<D: DataMut> GGSWCompressed<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECompressed<&mut [u8]> {
|
||||
let rank: usize = self.rank().into();
|
||||
GLWECiphertextCompressed {
|
||||
GLWECompressed {
|
||||
data: self.data.at_mut(row, col),
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
@@ -186,7 +227,7 @@ impl<D: DataMut> GGSWCiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGSWCiphertextCompressed<D> {
|
||||
impl<D: DataMut> ReaderFrom for GGSWCompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -201,7 +242,7 @@ impl<D: DataMut> ReaderFrom for GGSWCiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGSWCiphertextCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for GGSWCompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.into())?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.into())?;
|
||||
@@ -215,23 +256,72 @@ impl<D: DataRef> WriterTo for GGSWCiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GGSWCiphertextCompressed<DR>> for GGSWCiphertext<D>
|
||||
pub trait GGSWDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GLWEDecompress,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &GGSWCiphertextCompressed<DR>) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(self.rank(), other.rank())
|
||||
}
|
||||
fn decompress_ggsw<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GGSWToMut,
|
||||
O: GGSWCompressedToRef,
|
||||
{
|
||||
let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
|
||||
let other: &GGSWCompressed<&[u8]> = &other.to_ref();
|
||||
|
||||
let dnum: usize = self.dnum().into();
|
||||
let rank: usize = self.rank().into();
|
||||
(0..dnum).for_each(|row_i| {
|
||||
(0..rank + 1).for_each(|col_j| {
|
||||
self.at_mut(row_i, col_j)
|
||||
.decompress(module, &other.at(row_i, col_j));
|
||||
});
|
||||
});
|
||||
assert_eq!(res.rank(), other.rank());
|
||||
let dnum: usize = res.dnum().into();
|
||||
let rank: usize = res.rank().into();
|
||||
|
||||
for row_i in 0..dnum {
|
||||
for col_j in 0..rank + 1 {
|
||||
self.decompress_glwe(&mut res.at_mut(row_i, col_j), &other.at(row_i, col_j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGSWDecompress for Module<B> where Self: GGSWDecompress {}
|
||||
|
||||
impl<D: DataMut> GGSW<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GGSWCompressedToRef,
|
||||
M: GGSWDecompress,
|
||||
{
|
||||
module.decompress_ggsw(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGSWCompressedToMut {
|
||||
fn to_mut(&mut self) -> GGSWCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGSWCompressedToMut for GGSWCompressed<D> {
|
||||
fn to_mut(&mut self) -> GGSWCompressed<&mut [u8]> {
|
||||
GGSWCompressed {
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
dsize: self.dsize(),
|
||||
rank: self.rank(),
|
||||
seed: self.seed.clone(),
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGSWCompressedToRef {
|
||||
fn to_ref(&self) -> GGSWCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGSWCompressedToRef for GGSWCompressed<D> {
|
||||
fn to_ref(&self) -> GGSWCompressed<&[u8]> {
|
||||
GGSWCompressed {
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
dsize: self.dsize(),
|
||||
rank: self.rank(),
|
||||
seed: self.seed.clone(),
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, VecZnx, WriterTo, ZnxInfos},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo, ZnxInfos,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, Degree, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision, compressed::Decompress};
|
||||
use crate::layouts::{
|
||||
Base2K, GLWE, GLWEInfos, GLWEToMut, GetRingDegree, LWEInfos, Rank, RingDegree, SetGLWEInfos, TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GLWECiphertextCompressed<D: Data> {
|
||||
pub struct GLWECompressed<D: Data> {
|
||||
pub(crate) data: VecZnx<D>,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) k: TorusPrecision,
|
||||
@@ -17,7 +21,7 @@ pub struct GLWECiphertextCompressed<D: Data> {
|
||||
pub(crate) seed: [u8; 32],
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GLWECiphertextCompressed<D> {
|
||||
impl<D: Data> LWEInfos for GLWECompressed<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -30,27 +34,27 @@ impl<D: Data> LWEInfos for GLWECiphertextCompressed<D> {
|
||||
self.data.size()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for GLWECiphertextCompressed<D> {
|
||||
impl<D: Data> GLWEInfos for GLWECompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GLWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for GLWECompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GLWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for GLWECompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"GLWECiphertextCompressed: base2k={} k={} rank={} seed={:?}: {}",
|
||||
"GLWECompressed: base2k={} k={} rank={} seed={:?}: {}",
|
||||
self.base2k(),
|
||||
self.k(),
|
||||
self.rank(),
|
||||
@@ -60,23 +64,23 @@ impl<D: DataRef> fmt::Display for GLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GLWECiphertextCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for GLWECompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.data.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWECiphertextCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_with(infos.n(), infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
|
||||
Self {
|
||||
data: VecZnx::alloc(n.into(), 1, k.0.div_ceil(base2k.0) as usize),
|
||||
pub trait GLWECompressedAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_glwe_compressed(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWECompressed<Vec<u8>> {
|
||||
GLWECompressed {
|
||||
data: VecZnx::alloc(
|
||||
self.ring_degree().into(),
|
||||
1,
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
),
|
||||
base2k,
|
||||
k,
|
||||
rank,
|
||||
@@ -84,19 +88,66 @@ impl GLWECiphertextCompressed<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_glwe_compressed_from_infos<A>(&self, infos: &A) -> GLWECompressed<Vec<u8>>
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k())
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.alloc_glwe_compressed(infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision) -> usize {
|
||||
VecZnx::alloc_bytes(n.into(), 1, k.0.div_ceil(base2k.0) as usize)
|
||||
fn bytes_of_glwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> usize {
|
||||
VecZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
1,
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.bytes_of_glwe_compressed(infos.base2k(), infos.k())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWECiphertextCompressed<D> {
|
||||
impl<B: Backend> GLWECompressedAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
impl GLWECompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWECompressedAlloc,
|
||||
{
|
||||
module.alloc_glwe_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
|
||||
where
|
||||
M: GLWECompressedAlloc,
|
||||
{
|
||||
module.alloc_glwe_compressed(base2k, k, rank)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWECompressedAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> usize
|
||||
where
|
||||
M: GLWECompressedAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_compressed(base2k, k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWECompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -106,7 +157,7 @@ impl<D: DataMut> ReaderFrom for GLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GLWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for GLWECompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.into())?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.into())?;
|
||||
@@ -116,63 +167,82 @@ impl<D: DataRef> WriterTo for GLWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GLWECiphertextCompressed<DR>> for GLWECiphertext<D>
|
||||
pub trait GLWEDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GetRingDegree + VecZnxFillUniform + VecZnxCopy,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &GLWECiphertextCompressed<DR>) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(
|
||||
self.n(),
|
||||
other.n(),
|
||||
"invalid receiver: self.n()={} != other.n()={}",
|
||||
self.n(),
|
||||
other.n()
|
||||
);
|
||||
assert_eq!(
|
||||
self.size(),
|
||||
other.size(),
|
||||
"invalid receiver: self.size()={} != other.size()={}",
|
||||
self.size(),
|
||||
other.size()
|
||||
);
|
||||
assert_eq!(
|
||||
self.rank(),
|
||||
other.rank(),
|
||||
"invalid receiver: self.rank()={} != other.rank()={}",
|
||||
self.rank(),
|
||||
other.rank()
|
||||
);
|
||||
}
|
||||
|
||||
let mut source: Source = Source::new(other.seed);
|
||||
self.decompress_internal(module, other, &mut source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWECiphertext<D> {
|
||||
pub(crate) fn decompress_internal<DataOther, B: Backend>(
|
||||
&mut self,
|
||||
module: &Module<B>,
|
||||
other: &GLWECiphertextCompressed<DataOther>,
|
||||
source: &mut Source,
|
||||
) where
|
||||
DataOther: DataRef,
|
||||
Module<B>: VecZnxCopy + VecZnxFillUniform,
|
||||
fn decompress_glwe<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GLWEToMut + SetGLWEInfos,
|
||||
O: GLWECompressedToRef + GLWEInfos,
|
||||
{
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert_eq!(self.rank(), other.rank());
|
||||
debug_assert_eq!(self.size(), other.size());
|
||||
let res: &mut GLWE<&mut [u8]> = &mut res.to_mut();
|
||||
let other: &GLWECompressed<&[u8]> = &other.to_ref();
|
||||
assert_eq!(
|
||||
res.n(),
|
||||
self.ring_degree(),
|
||||
"invalid receiver: res.n()={} != other.n()={}",
|
||||
res.n(),
|
||||
self.ring_degree()
|
||||
);
|
||||
|
||||
assert_eq!(res.lwe_layout(), other.lwe_layout());
|
||||
assert_eq!(res.glwe_layout(), other.glwe_layout());
|
||||
|
||||
let mut source: Source = Source::new(other.seed);
|
||||
|
||||
self.vec_znx_copy(&mut res.data, 0, &other.data, 0);
|
||||
(1..(other.rank() + 1).into()).for_each(|i| {
|
||||
self.vec_znx_fill_uniform(other.base2k.into(), &mut res.data, i, &mut source);
|
||||
});
|
||||
}
|
||||
|
||||
module.vec_znx_copy(&mut self.data, 0, &other.data, 0);
|
||||
(1..(other.rank() + 1).into()).for_each(|i| {
|
||||
module.vec_znx_fill_uniform(other.base2k.into(), &mut self.data, i, source);
|
||||
});
|
||||
|
||||
self.base2k = other.base2k;
|
||||
self.k = other.k;
|
||||
res.set_base2k(other.base2k());
|
||||
res.set_k(other.k());
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEDecompress for Module<B> where Self: GetRingDegree + VecZnxFillUniform + VecZnxCopy {}
|
||||
|
||||
impl<D: DataMut> GLWE<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GLWECompressedToRef + GLWEInfos,
|
||||
M: GLWEDecompress,
|
||||
{
|
||||
module.decompress_glwe(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWECompressedToRef {
|
||||
fn to_ref(&self) -> GLWECompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWECompressedToRef for GLWECompressed<D> {
|
||||
fn to_ref(&self) -> GLWECompressed<&[u8]> {
|
||||
GLWECompressed {
|
||||
seed: self.seed.clone(),
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
rank: self.rank,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWECompressedToMut {
|
||||
fn to_mut(&mut self) -> GLWECompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWECompressedToMut for GLWECompressed<D> {
|
||||
fn to_mut(&mut self) -> GLWECompressed<&mut [u8]> {
|
||||
GLWECompressed {
|
||||
seed: self.seed.clone(),
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
rank: self.rank,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
use std::fmt;
|
||||
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, compressed::GGLWESwitchingKeyCompressed,
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWEToLWESwitchingKey, GLWEToLWESwitchingKeyToMut, LWEInfos, Rank, RingDegree,
|
||||
TorusPrecision,
|
||||
compressed::{
|
||||
GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut,
|
||||
GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GLWEToLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>);
|
||||
pub struct GLWEToLWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for GLWEToLWESwitchingKeyCompressed<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -21,7 +26,7 @@ impl<D: Data> LWEInfos for GLWEToLWESwitchingKeyCompressed<D> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
fn size(&self) -> usize {
|
||||
@@ -83,54 +88,146 @@ impl<D: DataRef> WriterTo for GLWEToLWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub trait GLWEToLWESwitchingKeyCompressedAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
fn alloc_glwe_to_lwe_switching_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
dnum: Dnum,
|
||||
) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
GLWEToLWESwitchingKeyCompressed(self.alloc_glwe_switching_key_compressed(base2k, k, rank_in, Rank(1), dnum, Dsize(1)))
|
||||
}
|
||||
|
||||
fn alloc_glwe_to_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
|
||||
);
|
||||
Self(GGLWESwitchingKeyCompressed::alloc(infos))
|
||||
self.alloc_glwe_to_lwe_switching_key_compressed(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self {
|
||||
Self(GGLWESwitchingKeyCompressed::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
rank_in,
|
||||
Rank(1),
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
fn bytes_of_glwe_to_lwe_switching_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
dnum: Dnum,
|
||||
) -> usize {
|
||||
self.bytes_of_glwe_switching_key_compressed(base2k, k, rank_in, dnum, Dsize(1))
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn bytes_of_glwe_to_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is unsupported for GLWEToLWESwitchingKeyCompressed"
|
||||
);
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_in: Rank) -> usize {
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rank_in, dnum, Dsize(1))
|
||||
self.bytes_of_glwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyCompressedAlloc for Module<B> where Self: GLWESwitchingKeyCompressedAlloc {}
|
||||
|
||||
impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_glwe_to_lwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
M: GLWEToLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_glwe_to_lwe_switching_key_compressed(base2k, k, rank_in, dnum)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_to_lwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_in: Rank) -> usize
|
||||
where
|
||||
M: GLWEToLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_to_lwe_switching_key_compressed(base2k, k, rank_in, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyDecompress
|
||||
where
|
||||
Self: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
fn decompress_glwe_to_lwe_switching_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GLWEToLWESwitchingKeyToMut,
|
||||
O: GLWEToLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
self.decompress_glwe_switching_key(&mut res.to_mut().0, &other.to_ref().0);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
|
||||
|
||||
impl<D: DataMut> GLWEToLWESwitchingKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GLWEToLWESwitchingKeyCompressedToRef,
|
||||
M: GLWEToLWESwitchingKeyDecompress,
|
||||
{
|
||||
module.decompress_glwe_to_lwe_switching_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyCompressedToRef {
|
||||
fn to_ref(&self) -> GLWEToLWESwitchingKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWEToLWESwitchingKeyCompressedToRef for GLWEToLWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GLWEToLWESwitchingKeyCompressed<&[u8]> {
|
||||
GLWEToLWESwitchingKeyCompressed(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> GLWEToLWESwitchingKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWEToLWESwitchingKeyCompressedToMut for GLWEToLWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWEToLWESwitchingKeyCompressed<&mut [u8]> {
|
||||
GLWEToLWESwitchingKeyCompressed(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,24 @@ use std::fmt;
|
||||
|
||||
use poulpy_hal::{
|
||||
api::ZnFillUniform,
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo, Zn, ZnxInfos, ZnxView, ZnxViewMut},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo, Zn, ZnToMut, ZnToRef, ZnxInfos, ZnxView,
|
||||
ZnxViewMut,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, Degree, LWECiphertext, LWEInfos, TorusPrecision, compressed::Decompress};
|
||||
use crate::layouts::{Base2K, LWE, LWEInfos, LWEToMut, RingDegree, TorusPrecision};
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWECiphertextCompressed<D: Data> {
|
||||
pub struct LWECompressed<D: Data> {
|
||||
pub(crate) data: Zn<D>,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) seed: [u8; 32],
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for LWECiphertextCompressed<D> {
|
||||
impl<D: Data> LWEInfos for LWECompressed<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -25,8 +28,8 @@ impl<D: Data> LWEInfos for LWECiphertextCompressed<D> {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -34,17 +37,17 @@ impl<D: Data> LWEInfos for LWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for LWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for LWECompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for LWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for LWECompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"LWECiphertextCompressed: base2k={} k={} seed={:?}: {}",
|
||||
"LWECompressed: base2k={} k={} seed={:?}: {}",
|
||||
self.base2k(),
|
||||
self.k(),
|
||||
self.seed,
|
||||
@@ -53,22 +56,15 @@ impl<D: DataRef> fmt::Display for LWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for LWECiphertextCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for LWECompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.data.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl LWECiphertextCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
Self::alloc_with(infos.base2k(), infos.k())
|
||||
}
|
||||
|
||||
pub fn alloc_with(base2k: Base2K, k: TorusPrecision) -> Self {
|
||||
Self {
|
||||
pub trait LWECompressedAlloc {
|
||||
fn alloc_lwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> LWECompressed<Vec<u8>> {
|
||||
LWECompressed {
|
||||
data: Zn::alloc(1, 1, k.0.div_ceil(base2k.0) as usize),
|
||||
k,
|
||||
base2k,
|
||||
@@ -76,21 +72,62 @@ impl LWECiphertextCompressed<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_lwe_compressed_from_infos<A>(&self, infos: &A) -> LWECompressed<Vec<u8>>
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(infos.base2k(), infos.k())
|
||||
self.alloc_lwe_compressed(infos.base2k(), infos.k())
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(base2k: Base2K, k: TorusPrecision) -> usize {
|
||||
Zn::alloc_bytes(1, 1, k.0.div_ceil(base2k.0) as usize)
|
||||
fn bytes_of_lwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> usize {
|
||||
Zn::bytes_of(1, 1, k.0.div_ceil(base2k.0) as usize)
|
||||
}
|
||||
|
||||
fn bytes_of_lwe_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
self.bytes_of_lwe_compressed(infos.base2k(), infos.k())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWECompressedAlloc for Module<B> {}
|
||||
|
||||
impl LWECompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: LWEInfos,
|
||||
M: LWECompressedAlloc,
|
||||
{
|
||||
module.alloc_lwe_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> Self
|
||||
where
|
||||
M: LWECompressedAlloc,
|
||||
{
|
||||
module.alloc_lwe_compressed(base2k, k)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: LWEInfos,
|
||||
M: LWECompressedAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> usize
|
||||
where
|
||||
M: LWECompressedAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_compressed(base2k, k)
|
||||
}
|
||||
}
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
impl<D: DataMut> ReaderFrom for LWECiphertextCompressed<D> {
|
||||
impl<D: DataMut> ReaderFrom for LWECompressed<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -99,7 +136,7 @@ impl<D: DataMut> ReaderFrom for LWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for LWECiphertextCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for LWECompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.into())?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.into())?;
|
||||
@@ -108,22 +145,72 @@ impl<D: DataRef> WriterTo for LWECiphertextCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, LWECiphertextCompressed<DR>> for LWECiphertext<D>
|
||||
pub trait LWEDecompress
|
||||
where
|
||||
Module<B>: ZnFillUniform,
|
||||
Self: ZnFillUniform,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &LWECiphertextCompressed<DR>) {
|
||||
debug_assert_eq!(self.size(), other.size());
|
||||
fn decompress_lwe<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: LWEToMut,
|
||||
O: LWECompressedToRef,
|
||||
{
|
||||
let res: &mut LWE<&mut [u8]> = &mut res.to_mut();
|
||||
let other: &LWECompressed<&[u8]> = &other.to_ref();
|
||||
|
||||
assert_eq!(res.lwe_layout(), other.lwe_layout());
|
||||
|
||||
let mut source: Source = Source::new(other.seed);
|
||||
module.zn_fill_uniform(
|
||||
self.n().into(),
|
||||
self.zn_fill_uniform(
|
||||
res.n().into(),
|
||||
other.base2k().into(),
|
||||
&mut self.data,
|
||||
&mut res.data,
|
||||
0,
|
||||
&mut source,
|
||||
);
|
||||
(0..self.size()).for_each(|i| {
|
||||
self.data.at_mut(0, i)[0] = other.data.at(0, i)[0];
|
||||
});
|
||||
for i in 0..res.size() {
|
||||
res.data.at_mut(0, i)[0] = other.data.at(0, i)[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEDecompress for Module<B> where Self: ZnFillUniform {}
|
||||
|
||||
impl<D: DataMut> LWE<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: LWECompressedToRef,
|
||||
M: LWEDecompress,
|
||||
{
|
||||
module.decompress_lwe(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWECompressedToRef {
|
||||
fn to_ref(&self) -> LWECompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWECompressedToRef for LWECompressed<D> {
|
||||
fn to_ref(&self) -> LWECompressed<&[u8]> {
|
||||
LWECompressed {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
seed: self.seed,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWECompressedToMut {
|
||||
fn to_mut(&mut self) -> LWECompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWECompressedToMut for LWECompressed<D> {
|
||||
fn to_mut(&mut self) -> LWECompressed<&mut [u8]> {
|
||||
LWECompressed {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
seed: self.seed,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, TorusPrecision,
|
||||
compressed::{Decompress, GGLWESwitchingKeyCompressed},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, LWESwitchingKeyToMut, Rank, RingDegree,
|
||||
TorusPrecision,
|
||||
compressed::{
|
||||
GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut,
|
||||
GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress,
|
||||
},
|
||||
};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>);
|
||||
pub struct LWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for LWESwitchingKeyCompressed<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -22,7 +25,7 @@ impl<D: Data> LWEInfos for LWESwitchingKeyCompressed<D> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
fn size(&self) -> usize {
|
||||
@@ -83,73 +86,149 @@ impl<D: DataRef> WriterTo for LWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub trait LWESwitchingKeyCompressedAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
fn alloc_lwe_switching_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
dnum: Dnum,
|
||||
) -> LWESwitchingKeyCompressed<Vec<u8>> {
|
||||
LWESwitchingKeyCompressed(self.alloc_glwe_switching_key_compressed(base2k, k, Rank(1), Rank(1), dnum, Dsize(1)))
|
||||
}
|
||||
|
||||
fn alloc_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> LWESwitchingKeyCompressed<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKeyCompressed"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKeyCompressed"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKeyCompressed"
|
||||
);
|
||||
Self(GGLWESwitchingKeyCompressed::alloc(infos))
|
||||
self.alloc_lwe_switching_key_compressed(infos.base2k(), infos.k(), infos.dnum())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self {
|
||||
Self(GGLWESwitchingKeyCompressed::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
Rank(1),
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
fn bytes_of_lwe_switching_key_compressed(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_switching_key_compressed(base2k, k, Rank(1), dnum, Dsize(1))
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn bytes_of_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKey"
|
||||
"dsize > 1 is not supported for LWESwitchingKeyCompressed"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKey"
|
||||
"rank_in > 1 is not supported for LWESwitchingKeyCompressed"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKey"
|
||||
"rank_out > 1 is not supported for LWESwitchingKeyCompressed"
|
||||
);
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, Dsize(1))
|
||||
self.bytes_of_glwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, LWESwitchingKeyCompressed<DR>> for LWESwitchingKey<D>
|
||||
impl<B: Backend> LWESwitchingKeyCompressedAlloc for Module<B> where Self: GLWESwitchingKeyCompressedAlloc {}
|
||||
|
||||
impl LWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_lwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self
|
||||
where
|
||||
M: LWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_lwe_switching_key_compressed(base2k, k, dnum)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize
|
||||
where
|
||||
M: LWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_switching_key_compressed(base2k, k, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &LWESwitchingKeyCompressed<DR>) {
|
||||
self.0.decompress(module, &other.0);
|
||||
fn decompress_lwe_switching_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: LWESwitchingKeyToMut,
|
||||
O: LWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
self.decompress_glwe_switching_key(&mut res.to_mut().0, &other.to_ref().0);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
|
||||
|
||||
impl<D: DataMut> LWESwitchingKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: LWESwitchingKeyCompressedToRef,
|
||||
M: LWESwitchingKeyDecompress,
|
||||
{
|
||||
module.decompress_lwe_switching_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyCompressedToRef {
|
||||
fn to_ref(&self) -> LWESwitchingKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWESwitchingKeyCompressedToRef for LWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> LWESwitchingKeyCompressed<&[u8]> {
|
||||
LWESwitchingKeyCompressed(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> LWESwitchingKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWESwitchingKeyCompressedToMut for LWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> LWESwitchingKeyCompressed<&mut [u8]> {
|
||||
LWESwitchingKeyCompressed(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxCopy, VecZnxFillUniform},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, TorusPrecision,
|
||||
compressed::{Decompress, GGLWESwitchingKeyCompressed},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyToMut, Rank, RingDegree,
|
||||
TorusPrecision,
|
||||
compressed::{
|
||||
GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut,
|
||||
GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress,
|
||||
},
|
||||
};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>);
|
||||
pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
@@ -83,63 +86,138 @@ impl<D: DataRef> WriterTo for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub trait LWEToGLWESwitchingKeyCompressedAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
fn alloc_lwe_to_glwe_switching_key_compressed(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
) -> LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
LWEToGLWESwitchingKeyCompressed(self.alloc_glwe_switching_key_compressed(base2k, k, Rank(1), rank_out, dnum, Dsize(1)))
|
||||
}
|
||||
|
||||
fn alloc_lwe_to_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> LWEToGLWESwitchingKeyCompressed<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKeyCompressed"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKeyCompressed"
|
||||
);
|
||||
Self(GGLWESwitchingKeyCompressed::alloc(infos))
|
||||
self.alloc_lwe_to_glwe_switching_key_compressed(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self {
|
||||
Self(GGLWESwitchingKeyCompressed::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
rank_out,
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
fn bytes_of_lwe_to_glwe_switching_key_compressed(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_switching_key_compressed(base2k, k, Rank(1), dnum, Dsize(1))
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn bytes_of_lwe_to_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKeyCompressed"
|
||||
);
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
|
||||
GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, Dsize(1))
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKeyCompressed"
|
||||
);
|
||||
self.bytes_of_lwe_to_glwe_switching_key_compressed(infos.base2k(), infos.k(), infos.dnum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, LWEToGLWESwitchingKeyCompressed<DR>> for LWEToGLWESwitchingKey<D>
|
||||
impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_lwe_to_glwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
M: LWEToGLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.alloc_lwe_to_glwe_switching_key_compressed(base2k, k, rank_out, dnum)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_to_glwe_switching_key_compressed_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize
|
||||
where
|
||||
M: LWEToGLWESwitchingKeyCompressedAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_to_glwe_switching_key_compressed(base2k, k, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyDecompress
|
||||
where
|
||||
Module<B>: VecZnxFillUniform + VecZnxCopy,
|
||||
Self: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
fn decompress(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKeyCompressed<DR>) {
|
||||
self.0.decompress(module, &other.0);
|
||||
fn decompress_lwe_to_glwe_switching_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: LWEToGLWESwitchingKeyToMut,
|
||||
O: LWEToGLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
self.decompress_glwe_switching_key(&mut res.to_mut().0, &other.to_ref().0);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
|
||||
|
||||
impl<D: DataMut> LWEToGLWESwitchingKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: LWEToGLWESwitchingKeyCompressedToRef,
|
||||
M: LWEToGLWESwitchingKeyDecompress,
|
||||
{
|
||||
module.decompress_lwe_to_glwe_switching_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyCompressedToRef {
|
||||
fn to_ref(&self) -> LWEToGLWESwitchingKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWEToGLWESwitchingKeyCompressedToRef for LWEToGLWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> LWEToGLWESwitchingKeyCompressed<&[u8]> {
|
||||
LWEToGLWESwitchingKeyCompressed(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> LWEToGLWESwitchingKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWEToGLWESwitchingKeyCompressedToMut for LWEToGLWESwitchingKeyCompressed<D>
|
||||
where
|
||||
GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> LWEToGLWESwitchingKeyCompressed<&mut [u8]> {
|
||||
LWEToGLWESwitchingKeyCompressed(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,3 @@ pub use glwe_to_lwe_ksk::*;
|
||||
pub use lwe_ct::*;
|
||||
pub use lwe_ksk::*;
|
||||
pub use lwe_to_glwe_ksk::*;
|
||||
|
||||
use poulpy_hal::layouts::{Backend, Module};
|
||||
|
||||
pub trait Decompress<B: Backend, C> {
|
||||
fn decompress(&mut self, module: &Module<B>, other: &C);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWE, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut,
|
||||
GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGLWEAutomorphismKeyLayout {
|
||||
pub n: Degree,
|
||||
pub struct AutomorphismKeyLayout {
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank: Rank,
|
||||
@@ -21,19 +22,19 @@ pub struct GGLWEAutomorphismKeyLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWEAutomorphismKey<D: Data> {
|
||||
pub(crate) key: GGLWESwitchingKey<D>,
|
||||
pub struct AutomorphismKey<D: Data> {
|
||||
pub(crate) key: GLWESwitchingKey<D>,
|
||||
pub(crate) p: i64,
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEAutomorphismKey<D> {
|
||||
impl<D: Data> AutomorphismKey<D> {
|
||||
pub fn p(&self) -> i64 {
|
||||
self.p
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWEAutomorphismKey<D> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: Data> LWEInfos for AutomorphismKey<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.key.n()
|
||||
}
|
||||
|
||||
@@ -50,13 +51,13 @@ impl<D: Data> LWEInfos for GGLWEAutomorphismKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GGLWEAutomorphismKey<D> {
|
||||
impl<D: Data> GLWEInfos for AutomorphismKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWEAutomorphismKey<D> {
|
||||
impl<D: Data> GGLWEInfos for AutomorphismKey<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.key.rank_in()
|
||||
}
|
||||
@@ -74,7 +75,7 @@ impl<D: Data> GGLWEInfos for GGLWEAutomorphismKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEInfos for GGLWEAutomorphismKeyLayout {
|
||||
impl LWEInfos for AutomorphismKeyLayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -83,18 +84,18 @@ impl LWEInfos for GGLWEAutomorphismKeyLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for GGLWEAutomorphismKeyLayout {
|
||||
impl GLWEInfos for AutomorphismKeyLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEInfos for GGLWEAutomorphismKeyLayout {
|
||||
impl GGLWEInfos for AutomorphismKeyLayout {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
@@ -112,84 +113,164 @@ impl GGLWEInfos for GGLWEAutomorphismKeyLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWEAutomorphismKey<D> {
|
||||
impl<D: DataRef> fmt::Debug for AutomorphismKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWEAutomorphismKey<D> {
|
||||
impl<D: DataMut> FillUniform for AutomorphismKey<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.key.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWEAutomorphismKey<D> {
|
||||
impl<D: DataRef> fmt::Display for AutomorphismKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(AutomorphismKey: p={}) {}", self.p, self.key)
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEAutomorphismKey<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
impl<B: Backend> AutomorphismKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {}
|
||||
|
||||
pub trait AutomorphismKeyAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
fn alloc_automorphism_key(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> AutomorphismKey<Vec<u8>> {
|
||||
AutomorphismKey {
|
||||
key: self.alloc_glwe_switching_key(base2k, k, rank, rank, dnum, dsize),
|
||||
p: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_automorphism_key_from_infos<A>(&self, infos: &A) -> AutomorphismKey<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.alloc_automorphism_key(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_automorphism_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
self.bytes_of_glwe_switching_key(base2k, k, rank, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
fn bytes_of_automorphism_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEAutomorphismKey"
|
||||
"rank_in != rank_out is not supported for AutomorphismKey"
|
||||
);
|
||||
GGLWEAutomorphismKey {
|
||||
key: GGLWESwitchingKey::alloc(infos),
|
||||
p: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
GGLWEAutomorphismKey {
|
||||
key: GGLWESwitchingKey::alloc_with(n, base2k, k, rank, rank, dnum, dsize),
|
||||
p: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEAutomorphismKey"
|
||||
);
|
||||
GGLWESwitchingKey::alloc_bytes(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rank, rank, dnum, dsize)
|
||||
self.bytes_of_automorphism_key(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEAutomorphismKey<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
|
||||
impl AutomorphismKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: AutomorphismKeyAlloc,
|
||||
{
|
||||
module.alloc_automorphism_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
M: AutomorphismKeyAlloc,
|
||||
{
|
||||
module.alloc_automorphism_key(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: AutomorphismKeyAlloc,
|
||||
{
|
||||
module.bytes_of_automorphism_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: AutomorphismKeyAlloc,
|
||||
{
|
||||
module.bytes_of_automorphism_key(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AutomorphismKeyToMut {
|
||||
fn to_mut(&mut self) -> AutomorphismKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> AutomorphismKeyToMut for AutomorphismKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> AutomorphismKey<&mut [u8]> {
|
||||
AutomorphismKey {
|
||||
key: self.key.to_mut(),
|
||||
p: self.p,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AutomorphismKeyToRef {
|
||||
fn to_ref(&self) -> AutomorphismKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> AutomorphismKeyToRef for AutomorphismKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToRef,
|
||||
{
|
||||
fn to_ref(&self) -> AutomorphismKey<&[u8]> {
|
||||
AutomorphismKey {
|
||||
p: self.p,
|
||||
key: self.key.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> AutomorphismKey<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> {
|
||||
self.key.at(row, col)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEAutomorphismKey<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
|
||||
impl<D: DataMut> AutomorphismKey<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> {
|
||||
self.key.at_mut(row, col)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWEAutomorphismKey<D> {
|
||||
impl<D: DataMut> ReaderFrom for AutomorphismKey<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.p = reader.read_u64::<LittleEndian>()? as i64;
|
||||
self.key.read_from(reader)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWEAutomorphismKey<D> {
|
||||
impl<D: DataRef> WriterTo for AutomorphismKey<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u64::<LittleEndian>(self.p as u64)?;
|
||||
self.key.write_to(writer)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, MatZnx, ReaderFrom, WriterTo, ZnxInfos},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, BuildError, Degree, Dnum, Dsize, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision};
|
||||
use crate::layouts::{Base2K, Dnum, Dsize, GLWE, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
@@ -16,8 +18,8 @@ where
|
||||
fn dsize(&self) -> Dsize;
|
||||
fn rank_in(&self) -> Rank;
|
||||
fn rank_out(&self) -> Rank;
|
||||
fn layout(&self) -> GGLWECiphertextLayout {
|
||||
GGLWECiphertextLayout {
|
||||
fn gglwe_layout(&self) -> GGLWELayout {
|
||||
GGLWELayout {
|
||||
n: self.n(),
|
||||
base2k: self.base2k(),
|
||||
k: self.k(),
|
||||
@@ -29,9 +31,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SetGGLWEInfos {
|
||||
fn set_dsize(&mut self, dsize: usize);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGLWECiphertextLayout {
|
||||
pub n: Degree,
|
||||
pub struct GGLWELayout {
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank_in: Rank,
|
||||
@@ -40,7 +46,7 @@ pub struct GGLWECiphertextLayout {
|
||||
pub dsize: Dsize,
|
||||
}
|
||||
|
||||
impl LWEInfos for GGLWECiphertextLayout {
|
||||
impl LWEInfos for GGLWELayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -49,18 +55,18 @@ impl LWEInfos for GGLWECiphertextLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for GGLWECiphertextLayout {
|
||||
impl GLWEInfos for GGLWELayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEInfos for GGLWECiphertextLayout {
|
||||
impl GGLWEInfos for GGLWELayout {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_in
|
||||
}
|
||||
@@ -79,14 +85,14 @@ impl GGLWEInfos for GGLWECiphertextLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWECiphertext<D: Data> {
|
||||
pub struct GGLWE<D: Data> {
|
||||
pub(crate) data: MatZnx<D>,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) dsize: Dsize,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWECiphertext<D> {
|
||||
impl<D: Data> LWEInfos for GGLWE<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -95,8 +101,8 @@ impl<D: Data> LWEInfos for GGLWECiphertext<D> {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -104,13 +110,13 @@ impl<D: Data> LWEInfos for GGLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GGLWECiphertext<D> {
|
||||
impl<D: Data> GLWEInfos for GGLWE<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWECiphertext<D> {
|
||||
impl<D: Data> GGLWEInfos for GGLWE<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
Rank(self.data.cols_in() as u32)
|
||||
}
|
||||
@@ -128,136 +134,35 @@ impl<D: Data> GGLWEInfos for GGLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GGLWECiphertextBuilder<D: Data> {
|
||||
data: Option<MatZnx<D>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
dsize: Option<Dsize>,
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWECiphertext<D> {
|
||||
#[inline]
|
||||
pub fn builder() -> GGLWECiphertextBuilder<D> {
|
||||
GGLWECiphertextBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
dsize: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWECiphertextBuilder<Vec<u8>> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.data = Some(MatZnx::alloc(
|
||||
infos.n().into(),
|
||||
infos.dnum().into(),
|
||||
infos.rank_in().into(),
|
||||
(infos.rank_out() + 1).into(),
|
||||
infos.size(),
|
||||
));
|
||||
self.base2k = Some(infos.base2k());
|
||||
self.k = Some(infos.k());
|
||||
self.dsize = Some(infos.dsize());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWECiphertextBuilder<D> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: MatZnx<D>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dsize(mut self, dsize: Dsize) -> Self {
|
||||
self.dsize = Some(dsize);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GGLWECiphertext<D>, BuildError> {
|
||||
let data: MatZnx<D> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
|
||||
|
||||
if base2k == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if dsize == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k == 0_u32 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GGLWECiphertext {
|
||||
data,
|
||||
base2k,
|
||||
k,
|
||||
dsize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWECiphertext<D> {
|
||||
impl<D: DataRef> GGLWE<D> {
|
||||
pub fn data(&self) -> &MatZnx<D> {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWECiphertext<D> {
|
||||
impl<D: DataMut> GGLWE<D> {
|
||||
pub fn data_mut(&mut self) -> &mut MatZnx<D> {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWECiphertext<D> {
|
||||
impl<D: DataRef> fmt::Debug for GGLWE<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWECiphertext<D> {
|
||||
impl<D: DataMut> FillUniform for GGLWE<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.data.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWECiphertext<D> {
|
||||
impl<D: DataRef> fmt::Display for GGLWE<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"(GGLWECiphertext: k={} base2k={} dsize={}) {}",
|
||||
"(GGLWE: k={} base2k={} dsize={}) {}",
|
||||
self.k().0,
|
||||
self.base2k().0,
|
||||
self.dsize().0,
|
||||
@@ -266,53 +171,39 @@ impl<D: DataRef> fmt::Display for GGLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWECiphertext<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.data(self.data.at(row, col))
|
||||
.base2k(self.base2k())
|
||||
.k(self.k())
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<D: DataRef> GGLWE<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.at(row, col),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWECiphertext<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.base2k(self.base2k())
|
||||
.k(self.k())
|
||||
.data(self.data.at_mut(row, col))
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<D: DataMut> GGLWE<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.at_mut(row, col),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWECiphertext<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
Self::alloc_with(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(
|
||||
n: Degree,
|
||||
pub trait GGLWEAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_gglwe(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self {
|
||||
) -> GGLWE<Vec<u8>> {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
@@ -327,9 +218,9 @@ impl GGLWECiphertext<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
GGLWE {
|
||||
data: MatZnx::alloc(
|
||||
n.into(),
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
rank_in.into(),
|
||||
(rank_out + 1).into(),
|
||||
@@ -341,12 +232,11 @@ impl GGLWECiphertext<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_glwe_from_infos<A>(&self, infos: &A) -> GGLWE<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(
|
||||
infos.n(),
|
||||
self.alloc_gglwe(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
@@ -356,8 +246,8 @@ impl GGLWECiphertext<Vec<u8>> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(
|
||||
n: Degree,
|
||||
fn bytes_of_gglwe(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
@@ -379,17 +269,111 @@ impl GGLWECiphertext<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
MatZnx::alloc_bytes(
|
||||
n.into(),
|
||||
MatZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
rank_in.into(),
|
||||
(rank_out + 1).into(),
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_gglwe_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.bytes_of_gglwe(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> {
|
||||
impl<B: Backend> GGLWEAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
impl GGLWE<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GGLWEAlloc,
|
||||
{
|
||||
module.alloc_glwe_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self
|
||||
where
|
||||
M: GGLWEAlloc,
|
||||
{
|
||||
module.alloc_gglwe(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GGLWEAlloc,
|
||||
{
|
||||
module.bytes_of_gglwe_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize
|
||||
where
|
||||
M: GGLWEAlloc,
|
||||
{
|
||||
module.bytes_of_gglwe(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToMut {
|
||||
fn to_mut(&mut self) -> GGLWE<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToMut for GGLWE<D> {
|
||||
fn to_mut(&mut self) -> GGLWE<&mut [u8]> {
|
||||
GGLWE {
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
dsize: self.dsize(),
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToRef {
|
||||
fn to_ref(&self) -> GGLWE<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEToRef for GGLWE<D> {
|
||||
fn to_ref(&self) -> GGLWE<&[u8]> {
|
||||
GGLWE {
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
dsize: self.dsize(),
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWE<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -398,7 +382,7 @@ impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWECiphertext<D> {
|
||||
impl<D: DataRef> WriterTo for GGLWE<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.0)?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.0)?;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
Base2K, Dnum, Dsize, GGLWE, GGLWEAlloc, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWE, GLWEInfos, LWEInfos, Rank, RingDegree,
|
||||
TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGLWESwitchingKeyLayout {
|
||||
pub n: Degree,
|
||||
pub struct GLWESwitchingKeyLayout {
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank_in: Rank,
|
||||
@@ -21,8 +22,8 @@ pub struct GGLWESwitchingKeyLayout {
|
||||
pub dsize: Dsize,
|
||||
}
|
||||
|
||||
impl LWEInfos for GGLWESwitchingKeyLayout {
|
||||
fn n(&self) -> Degree {
|
||||
impl LWEInfos for GLWESwitchingKeyLayout {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
|
||||
@@ -35,13 +36,13 @@ impl LWEInfos for GGLWESwitchingKeyLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for GGLWESwitchingKeyLayout {
|
||||
impl GLWEInfos for GLWESwitchingKeyLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEInfos for GGLWESwitchingKeyLayout {
|
||||
impl GGLWEInfos for GLWESwitchingKeyLayout {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_in
|
||||
}
|
||||
@@ -60,14 +61,44 @@ impl GGLWEInfos for GGLWESwitchingKeyLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWESwitchingKey<D: Data> {
|
||||
pub(crate) key: GGLWECiphertext<D>,
|
||||
pub struct GLWESwitchingKey<D: Data> {
|
||||
pub(crate) key: GGLWE<D>,
|
||||
pub(crate) sk_in_n: usize, // Degree of sk_in
|
||||
pub(crate) sk_out_n: usize, // Degree of sk_out
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWESwitchingKey<D> {
|
||||
fn n(&self) -> Degree {
|
||||
pub(crate) trait GLWESwitchingKeySetMetaData {
|
||||
fn set_sk_in_n(&mut self, sk_in_n: usize);
|
||||
fn set_sk_out_n(&mut self, sk_out_n: usize);
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESwitchingKeySetMetaData for GLWESwitchingKey<D> {
|
||||
fn set_sk_in_n(&mut self, sk_in_n: usize) {
|
||||
self.sk_in_n = sk_in_n
|
||||
}
|
||||
|
||||
fn set_sk_out_n(&mut self, sk_out_n: usize) {
|
||||
self.sk_out_n = sk_out_n
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait GLWESwtichingKeyGetMetaData {
|
||||
fn sk_in_n(&self) -> usize;
|
||||
fn sk_out_n(&self) -> usize;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESwtichingKeyGetMetaData for GLWESwitchingKey<D> {
|
||||
fn sk_in_n(&self) -> usize {
|
||||
self.sk_in_n
|
||||
}
|
||||
|
||||
fn sk_out_n(&self) -> usize {
|
||||
self.sk_out_n
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GLWESwitchingKey<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.key.n()
|
||||
}
|
||||
|
||||
@@ -84,13 +115,13 @@ impl<D: Data> LWEInfos for GGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GGLWESwitchingKey<D> {
|
||||
impl<D: Data> GLWEInfos for GLWESwitchingKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWESwitchingKey<D> {
|
||||
impl<D: Data> GGLWEInfos for GLWESwitchingKey<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.key.rank_in()
|
||||
}
|
||||
@@ -108,13 +139,13 @@ impl<D: Data> GGLWEInfos for GGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> fmt::Debug for GLWESwitchingKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> fmt::Display for GLWESwitchingKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
@@ -126,49 +157,48 @@ impl<D: DataRef> fmt::Display for GGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWESwitchingKey<D> {
|
||||
impl<D: DataMut> FillUniform for GLWESwitchingKey<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.key.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWESwitchingKey<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
GGLWESwitchingKey {
|
||||
key: GGLWECiphertext::alloc(infos),
|
||||
sk_in_n: 0,
|
||||
sk_out_n: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_with(
|
||||
n: Degree,
|
||||
pub trait GLWESwitchingKeyAlloc
|
||||
where
|
||||
Self: GGLWEAlloc,
|
||||
{
|
||||
fn alloc_glwe_switching_key(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self {
|
||||
GGLWESwitchingKey {
|
||||
key: GGLWECiphertext::alloc_with(n, base2k, k, rank_in, rank_out, dnum, dsize),
|
||||
) -> GLWESwitchingKey<Vec<u8>> {
|
||||
GLWESwitchingKey {
|
||||
key: self.alloc_gglwe(base2k, k, rank_in, rank_out, dnum, dsize),
|
||||
sk_in_n: 0,
|
||||
sk_out_n: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_glwe_switching_key_from_infos<A>(&self, infos: &A) -> GLWESwitchingKey<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
GGLWECiphertext::alloc_bytes(infos)
|
||||
self.alloc_glwe_switching_key(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(
|
||||
n: Degree,
|
||||
fn bytes_of_glwe_switching_key(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
@@ -176,23 +206,121 @@ impl GGLWESwitchingKey<Vec<u8>> {
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize {
|
||||
GGLWECiphertext::alloc_bytes_with(n, base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
self.bytes_of_gglwe(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_switching_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe_switching_key(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWESwitchingKey<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
|
||||
impl<B: Backend> GLWESwitchingKeyAlloc for Module<B> where Self: GGLWEAlloc {}
|
||||
|
||||
impl GLWESwitchingKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.alloc_glwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> Self
|
||||
where
|
||||
M: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.alloc_glwe_switching_key(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize
|
||||
where
|
||||
M: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_switching_key(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESwitchingKeyToMut {
|
||||
fn to_mut(&mut self) -> GLWESwitchingKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESwitchingKeyToMut for GLWESwitchingKey<D>
|
||||
where
|
||||
GGLWE<D>: GGLWEToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWESwitchingKey<&mut [u8]> {
|
||||
GLWESwitchingKey {
|
||||
key: self.key.to_mut(),
|
||||
sk_in_n: self.sk_in_n,
|
||||
sk_out_n: self.sk_out_n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESwitchingKeyToRef {
|
||||
fn to_ref(&self) -> GLWESwitchingKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESwitchingKeyToRef for GLWESwitchingKey<D>
|
||||
where
|
||||
GGLWE<D>: GGLWEToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GLWESwitchingKey<&[u8]> {
|
||||
GLWESwitchingKey {
|
||||
key: self.key.to_ref(),
|
||||
sk_in_n: self.sk_in_n,
|
||||
sk_out_n: self.sk_out_n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESwitchingKey<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> {
|
||||
self.key.at(row, col)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWESwitchingKey<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
|
||||
impl<D: DataMut> GLWESwitchingKey<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> {
|
||||
self.key.at_mut(row, col)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWESwitchingKey<D> {
|
||||
impl<D: DataMut> ReaderFrom for GLWESwitchingKey<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize;
|
||||
self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize;
|
||||
@@ -200,7 +328,7 @@ impl<D: DataMut> ReaderFrom for GGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> WriterTo for GLWESwitchingKey<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?;
|
||||
writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?;
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
|
||||
use crate::layouts::{
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut,
|
||||
GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGLWETensorKeyLayout {
|
||||
pub n: Degree,
|
||||
pub struct TensorKeyLayout {
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank: Rank,
|
||||
@@ -19,12 +22,12 @@ pub struct GGLWETensorKeyLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWETensorKey<D: Data> {
|
||||
pub(crate) keys: Vec<GGLWESwitchingKey<D>>,
|
||||
pub struct TensorKey<D: Data> {
|
||||
pub(crate) keys: Vec<GLWESwitchingKey<D>>,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWETensorKey<D> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: Data> LWEInfos for TensorKey<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
@@ -41,13 +44,13 @@ impl<D: Data> LWEInfos for GGLWETensorKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GGLWETensorKey<D> {
|
||||
impl<D: Data> GLWEInfos for TensorKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWETensorKey<D> {
|
||||
impl<D: Data> GGLWEInfos for TensorKey<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
@@ -65,8 +68,8 @@ impl<D: Data> GGLWEInfos for GGLWETensorKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEInfos for GGLWETensorKeyLayout {
|
||||
fn n(&self) -> Degree {
|
||||
impl LWEInfos for TensorKeyLayout {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
|
||||
@@ -79,13 +82,13 @@ impl LWEInfos for GGLWETensorKeyLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for GGLWETensorKeyLayout {
|
||||
impl GLWEInfos for TensorKeyLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEInfos for GGLWETensorKeyLayout {
|
||||
impl GGLWEInfos for TensorKeyLayout {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
@@ -103,21 +106,21 @@ impl GGLWEInfos for GGLWETensorKeyLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWETensorKey<D> {
|
||||
impl<D: DataRef> fmt::Debug for TensorKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWETensorKey<D> {
|
||||
impl<D: DataMut> FillUniform for TensorKey<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.for_each(|key: &mut GGLWESwitchingKey<D>| key.fill_uniform(log_bound, source))
|
||||
.for_each(|key: &mut GLWESwitchingKey<D>| key.fill_uniform(log_bound, source))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWETensorKey<D> {
|
||||
impl<D: DataRef> fmt::Display for TensorKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "(GLWETensorKey)",)?;
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
@@ -127,8 +130,20 @@ impl<D: DataRef> fmt::Display for GGLWETensorKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWETensorKey<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub trait TensorKeyAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
fn alloc_tensor_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> TensorKey<Vec<u8>> {
|
||||
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
|
||||
TensorKey {
|
||||
keys: (0..pairs)
|
||||
.map(|_| self.alloc_glwe_switching_key(base2k, k, Rank(1), rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_tensor_key_from_infos<A>(&self, infos: &A) -> TensorKey<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
@@ -137,34 +152,21 @@ impl GGLWETensorKey<Vec<u8>> {
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWETensorKey"
|
||||
);
|
||||
Self::alloc_with(
|
||||
infos.n(),
|
||||
self.alloc_tensor_key(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_out(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
let mut keys: Vec<GGLWESwitchingKey<Vec<u8>>> = Vec::new();
|
||||
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
|
||||
(0..pairs).for_each(|_| {
|
||||
keys.push(GGLWESwitchingKey::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
rank,
|
||||
dnum,
|
||||
dsize,
|
||||
));
|
||||
});
|
||||
Self { keys }
|
||||
fn bytes_of_tensor_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
|
||||
pairs * self.bytes_of_glwe_switching_key(base2k, k, Rank(1), rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn bytes_of_tensor_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
@@ -173,29 +175,53 @@ impl GGLWETensorKey<Vec<u8>> {
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWETensorKey"
|
||||
);
|
||||
let rank_out: usize = infos.rank_out().into();
|
||||
let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1);
|
||||
pairs
|
||||
* GGLWESwitchingKey::alloc_bytes_with(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
Rank(1),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
|
||||
pairs * GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), rank, dnum, dsize)
|
||||
self.bytes_of_tensor_key(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWETensorKey<D> {
|
||||
impl<B: Backend> TensorKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {}
|
||||
|
||||
impl TensorKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: TensorKeyAlloc,
|
||||
{
|
||||
module.alloc_tensor_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
M: TensorKeyAlloc,
|
||||
{
|
||||
module.alloc_tensor_key(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: TensorKeyAlloc,
|
||||
{
|
||||
module.bytes_of_tensor_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: TensorKeyAlloc,
|
||||
{
|
||||
module.bytes_of_tensor_key(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> TensorKey<D> {
|
||||
// Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
|
||||
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKey<D> {
|
||||
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKey<D> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
@@ -204,9 +230,9 @@ impl<D: DataMut> GGLWETensorKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWETensorKey<D> {
|
||||
impl<D: DataRef> TensorKey<D> {
|
||||
// Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
|
||||
pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKey<D> {
|
||||
pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKey<D> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
@@ -215,7 +241,7 @@ impl<D: DataRef> GGLWETensorKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWETensorKey<D> {
|
||||
impl<D: DataMut> ReaderFrom for TensorKey<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
let len: usize = reader.read_u64::<LittleEndian>()? as usize;
|
||||
if self.keys.len() != len {
|
||||
@@ -231,7 +257,7 @@ impl<D: DataMut> ReaderFrom for GGLWETensorKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWETensorKey<D> {
|
||||
impl<D: DataRef> WriterTo for TensorKey<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u64::<LittleEndian>(self.keys.len() as u64)?;
|
||||
for key in &self.keys {
|
||||
@@ -240,3 +266,33 @@ impl<D: DataRef> WriterTo for GGLWETensorKey<D> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TensorKeyToRef {
|
||||
fn to_ref(&self) -> TensorKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> TensorKeyToRef for TensorKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToRef,
|
||||
{
|
||||
fn to_ref(&self) -> TensorKey<&[u8]> {
|
||||
TensorKey {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TensorKeyToMut {
|
||||
fn to_mut(&mut self) -> TensorKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> TensorKeyToMut for TensorKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> TensorKey<&mut [u8]> {
|
||||
TensorKey {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, MatZnx, ReaderFrom, WriterTo, ZnxInfos},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
use std::fmt;
|
||||
|
||||
use crate::layouts::{Base2K, BuildError, Degree, Dnum, Dsize, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision};
|
||||
use crate::layouts::{Base2K, Dnum, Dsize, GLWE, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision};
|
||||
|
||||
pub trait GGSWInfos
|
||||
where
|
||||
@@ -12,8 +14,8 @@ where
|
||||
{
|
||||
fn dnum(&self) -> Dnum;
|
||||
fn dsize(&self) -> Dsize;
|
||||
fn ggsw_layout(&self) -> GGSWCiphertextLayout {
|
||||
GGSWCiphertextLayout {
|
||||
fn ggsw_layout(&self) -> GGSWLayout {
|
||||
GGSWLayout {
|
||||
n: self.n(),
|
||||
base2k: self.base2k(),
|
||||
k: self.k(),
|
||||
@@ -25,8 +27,8 @@ where
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGSWCiphertextLayout {
|
||||
pub n: Degree,
|
||||
pub struct GGSWLayout {
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank: Rank,
|
||||
@@ -34,7 +36,7 @@ pub struct GGSWCiphertextLayout {
|
||||
pub dsize: Dsize,
|
||||
}
|
||||
|
||||
impl LWEInfos for GGSWCiphertextLayout {
|
||||
impl LWEInfos for GGSWLayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -43,17 +45,17 @@ impl LWEInfos for GGSWCiphertextLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
impl GLWEInfos for GGSWCiphertextLayout {
|
||||
impl GLWEInfos for GGSWLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
impl GGSWInfos for GGSWCiphertextLayout {
|
||||
impl GGSWInfos for GGSWLayout {
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.dsize
|
||||
}
|
||||
@@ -64,16 +66,16 @@ impl GGSWInfos for GGSWCiphertextLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGSWCiphertext<D: Data> {
|
||||
pub struct GGSW<D: Data> {
|
||||
pub(crate) data: MatZnx<D>,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) dsize: Dsize,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGSWCiphertext<D> {
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
impl<D: Data> LWEInfos for GGSW<D> {
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -89,13 +91,13 @@ impl<D: Data> LWEInfos for GGSWCiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GGSWCiphertext<D> {
|
||||
impl<D: Data> GLWEInfos for GGSW<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
Rank(self.data.cols_out() as u32 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGSWInfos for GGSWCiphertext<D> {
|
||||
impl<D: Data> GGSWInfos for GGSW<D> {
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.dsize
|
||||
}
|
||||
@@ -105,133 +107,17 @@ impl<D: Data> GGSWInfos for GGSWCiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GGSWCiphertextBuilder<D: Data> {
|
||||
data: Option<MatZnx<D>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
dsize: Option<Dsize>,
|
||||
}
|
||||
|
||||
impl<D: Data> GGSWCiphertext<D> {
|
||||
#[inline]
|
||||
pub fn builder() -> GGSWCiphertextBuilder<D> {
|
||||
GGSWCiphertextBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
dsize: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GGSWCiphertextBuilder<Vec<u8>> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
debug_assert!(
|
||||
infos.size() as u32 > infos.dsize().0,
|
||||
"invalid ggsw: ceil(k/base2k): {} <= dsize: {}",
|
||||
infos.size(),
|
||||
infos.dsize()
|
||||
);
|
||||
|
||||
assert!(
|
||||
infos.dnum().0 * infos.dsize().0 <= infos.size() as u32,
|
||||
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {}",
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
infos.size(),
|
||||
);
|
||||
|
||||
self.data = Some(MatZnx::alloc(
|
||||
infos.n().into(),
|
||||
infos.dnum().into(),
|
||||
(infos.rank() + 1).into(),
|
||||
(infos.rank() + 1).into(),
|
||||
infos.size(),
|
||||
));
|
||||
self.base2k = Some(infos.base2k());
|
||||
self.k = Some(infos.k());
|
||||
self.dsize = Some(infos.dsize());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGSWCiphertextBuilder<D> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: MatZnx<D>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dsize(mut self, dsize: Dsize) -> Self {
|
||||
self.dsize = Some(dsize);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GGSWCiphertext<D>, BuildError> {
|
||||
let data: MatZnx<D> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
|
||||
|
||||
if base2k == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if dsize == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k == 0_u32 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GGSWCiphertext {
|
||||
data,
|
||||
base2k,
|
||||
k,
|
||||
dsize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGSWCiphertext<D> {
|
||||
impl<D: DataRef> fmt::Debug for GGSW<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGSWCiphertext<D> {
|
||||
impl<D: DataRef> fmt::Display for GGSW<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"(GGSWCiphertext: k: {} base2k: {} dsize: {}) {}",
|
||||
"(GGSW: k: {} base2k: {} dsize: {}) {}",
|
||||
self.k().0,
|
||||
self.base2k().0,
|
||||
self.dsize().0,
|
||||
@@ -240,50 +126,39 @@ impl<D: DataRef> fmt::Display for GGSWCiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGSWCiphertext<D> {
|
||||
impl<D: DataMut> FillUniform for GGSW<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.data.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGSWCiphertext<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.data(self.data.at(row, col))
|
||||
.base2k(self.base2k())
|
||||
.k(self.k())
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<D: DataRef> GGSW<D> {
|
||||
pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.at(row, col),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGSWCiphertext<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.base2k(self.base2k())
|
||||
.k(self.k())
|
||||
.data(self.data.at_mut(row, col))
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<D: DataMut> GGSW<D> {
|
||||
pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.at_mut(row, col),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GGSWCiphertext<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
Self::alloc_with(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
impl<B: Backend> GGSWAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
pub trait GGSWAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> GGSW<Vec<u8>> {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
@@ -298,9 +173,9 @@ impl GGSWCiphertext<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
GGSW {
|
||||
data: MatZnx::alloc(
|
||||
n.into(),
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
(rank + 1).into(),
|
||||
(rank + 1).into(),
|
||||
@@ -312,12 +187,11 @@ impl GGSWCiphertext<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_ggsw_from_infos<A>(&self, infos: &A) -> GGSW<Vec<u8>>
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(
|
||||
infos.n(),
|
||||
self.alloc_ggsw(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
@@ -326,7 +200,7 @@ impl GGSWCiphertext<Vec<u8>> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
fn bytes_of_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
@@ -341,19 +215,64 @@ impl GGSWCiphertext<Vec<u8>> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
MatZnx::alloc_bytes(
|
||||
n.into(),
|
||||
MatZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
dnum.into(),
|
||||
(rank + 1).into(),
|
||||
(rank + 1).into(),
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_ggsw_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
self.bytes_of_ggsw(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl GGSW<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: GGSWAlloc,
|
||||
{
|
||||
module.alloc_ggsw_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
M: GGSWAlloc,
|
||||
{
|
||||
module.alloc_ggsw(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: GGSWAlloc,
|
||||
{
|
||||
module.bytes_of_ggsw_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: GGSWAlloc,
|
||||
{
|
||||
module.bytes_of_ggsw(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGSWCiphertext<D> {
|
||||
impl<D: DataMut> ReaderFrom for GGSW<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -362,7 +281,7 @@ impl<D: DataMut> ReaderFrom for GGSWCiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGSWCiphertext<D> {
|
||||
impl<D: DataRef> WriterTo for GGSW<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.into())?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.into())?;
|
||||
@@ -370,3 +289,33 @@ impl<D: DataRef> WriterTo for GGSWCiphertext<D> {
|
||||
self.data.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGSWToMut {
|
||||
fn to_mut(&mut self) -> GGSW<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGSWToMut for GGSW<D> {
|
||||
fn to_mut(&mut self) -> GGSW<&mut [u8]> {
|
||||
GGSW {
|
||||
dsize: self.dsize,
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGSWToRef {
|
||||
fn to_ref(&self) -> GGSW<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGSWToRef for GGSW<D> {
|
||||
fn to_ref(&self) -> GGSW<&[u8]> {
|
||||
GGSW {
|
||||
dsize: self.dsize,
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{
|
||||
Data, DataMut, DataRef, FillUniform, ReaderFrom, ToOwnedDeep, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo, ZnxInfos,
|
||||
Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, ToOwnedDeep, VecZnx, VecZnxToMut, VecZnxToRef,
|
||||
WriterTo, ZnxInfos,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, BuildError, Degree, LWEInfos, Rank, TorusPrecision};
|
||||
use crate::layouts::{Base2K, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
@@ -14,8 +15,8 @@ where
|
||||
Self: LWEInfos,
|
||||
{
|
||||
fn rank(&self) -> Rank;
|
||||
fn glwe_layout(&self) -> GLWECiphertextLayout {
|
||||
GLWECiphertextLayout {
|
||||
fn glwe_layout(&self) -> GLWELayout {
|
||||
GLWELayout {
|
||||
n: self.n(),
|
||||
base2k: self.base2k(),
|
||||
k: self.k(),
|
||||
@@ -24,21 +25,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWELayoutSet {
|
||||
pub trait SetGLWEInfos {
|
||||
fn set_k(&mut self, k: TorusPrecision);
|
||||
fn set_basek(&mut self, base2k: Base2K);
|
||||
fn set_base2k(&mut self, base2k: Base2K);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GLWECiphertextLayout {
|
||||
pub n: Degree,
|
||||
pub struct GLWELayout {
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank: Rank,
|
||||
}
|
||||
|
||||
impl LWEInfos for GLWECiphertextLayout {
|
||||
fn n(&self) -> Degree {
|
||||
impl LWEInfos for GLWELayout {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
|
||||
@@ -51,21 +52,21 @@ impl LWEInfos for GLWECiphertextLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for GLWECiphertextLayout {
|
||||
impl GLWEInfos for GLWELayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GLWECiphertext<D: Data> {
|
||||
pub struct GLWE<D: Data> {
|
||||
pub(crate) data: VecZnx<D>,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) k: TorusPrecision,
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWELayoutSet for GLWECiphertext<D> {
|
||||
fn set_basek(&mut self, base2k: Base2K) {
|
||||
impl<D: DataMut> SetGLWEInfos for GLWE<D> {
|
||||
fn set_base2k(&mut self, base2k: Base2K) {
|
||||
self.base2k = base2k
|
||||
}
|
||||
|
||||
@@ -74,99 +75,19 @@ impl<D: DataMut> GLWELayoutSet for GLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWECiphertext<D> {
|
||||
impl<D: DataRef> GLWE<D> {
|
||||
pub fn data(&self) -> &VecZnx<D> {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWECiphertext<D> {
|
||||
impl<D: DataMut> GLWE<D> {
|
||||
pub fn data_mut(&mut self) -> &mut VecZnx<D> {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GLWECiphertextBuilder<D: Data> {
|
||||
data: Option<VecZnx<D>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
}
|
||||
|
||||
impl<D: Data> GLWECiphertext<D> {
|
||||
#[inline]
|
||||
pub fn builder() -> GLWECiphertextBuilder<D> {
|
||||
GLWECiphertextBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWECiphertextBuilder<Vec<u8>> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, layout: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.data = Some(VecZnx::alloc(
|
||||
layout.n().into(),
|
||||
(layout.rank() + 1).into(),
|
||||
layout.size(),
|
||||
));
|
||||
self.base2k = Some(layout.base2k());
|
||||
self.k = Some(layout.k());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWECiphertextBuilder<D> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: VecZnx<D>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GLWECiphertext<D>, BuildError> {
|
||||
let data: VecZnx<D> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
|
||||
if base2k == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k == 0_u32 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GLWECiphertext { data, base2k, k })
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GLWECiphertext<D> {
|
||||
impl<D: Data> LWEInfos for GLWE<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -175,8 +96,8 @@ impl<D: Data> LWEInfos for GLWECiphertext<D> {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -184,16 +105,16 @@ impl<D: Data> LWEInfos for GLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GLWECiphertext<D> {
|
||||
impl<D: Data> GLWEInfos for GLWE<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
Rank(self.data.cols() as u32 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> ToOwnedDeep for GLWECiphertext<D> {
|
||||
type Owned = GLWECiphertext<Vec<u8>>;
|
||||
impl<D: DataRef> ToOwnedDeep for GLWE<D> {
|
||||
type Owned = GLWE<Vec<u8>>;
|
||||
fn to_owned_deep(&self) -> Self::Owned {
|
||||
GLWECiphertext {
|
||||
GLWE {
|
||||
data: self.data.to_owned_deep(),
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
@@ -201,17 +122,17 @@ impl<D: DataRef> ToOwnedDeep for GLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GLWECiphertext<D> {
|
||||
impl<D: DataRef> fmt::Debug for GLWE<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GLWECiphertext<D> {
|
||||
impl<D: DataRef> fmt::Display for GLWE<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"GLWECiphertext: base2k={} k={}: {}",
|
||||
"GLWE: base2k={} k={}: {}",
|
||||
self.base2k().0,
|
||||
self.k().0,
|
||||
self.data
|
||||
@@ -219,71 +140,86 @@ impl<D: DataRef> fmt::Display for GLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GLWECiphertext<D> {
|
||||
impl<D: DataMut> FillUniform for GLWE<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.data.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWECiphertext<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_with(infos.n(), infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
|
||||
Self {
|
||||
data: VecZnx::alloc(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
|
||||
pub trait GLWEAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_glwe(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWE<Vec<u8>> {
|
||||
GLWE {
|
||||
data: VecZnx::alloc(
|
||||
self.ring_degree().into(),
|
||||
(rank + 1).into(),
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
),
|
||||
base2k,
|
||||
k,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_glwe_from_infos<A>(&self, infos: &A) -> GLWE<Vec<u8>>
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k(), infos.rank())
|
||||
self.alloc_glwe(infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
|
||||
VecZnx::alloc_bytes(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
|
||||
fn bytes_of_glwe(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
|
||||
VecZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
(rank + 1).into(),
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe(infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWECiphertextToRef {
|
||||
fn to_ref(&self) -> GLWECiphertext<&[u8]>;
|
||||
}
|
||||
impl<B: Backend> GLWEAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
impl<D: DataRef> GLWECiphertextToRef for GLWECiphertext<D> {
|
||||
fn to_ref(&self) -> GLWECiphertext<&[u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.k(self.k())
|
||||
.base2k(self.base2k())
|
||||
.data(self.data.to_ref())
|
||||
.build()
|
||||
.unwrap()
|
||||
impl GLWE<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWEAlloc,
|
||||
{
|
||||
module.alloc_glwe_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
|
||||
where
|
||||
M: GLWEAlloc,
|
||||
{
|
||||
module.alloc_glwe(base2k, k, rank)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWEAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize
|
||||
where
|
||||
M: GLWEAlloc,
|
||||
{
|
||||
module.bytes_of_glwe(base2k, k, rank)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWECiphertextToMut {
|
||||
fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWECiphertextToMut for GLWECiphertext<D> {
|
||||
fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.k(self.k())
|
||||
.base2k(self.base2k())
|
||||
.data(self.data.to_mut())
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWECiphertext<D> {
|
||||
impl<D: DataMut> ReaderFrom for GLWE<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -291,10 +227,38 @@ impl<D: DataMut> ReaderFrom for GLWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GLWECiphertext<D> {
|
||||
impl<D: DataRef> WriterTo for GLWE<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.0)?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.0)?;
|
||||
self.data.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToRef {
|
||||
fn to_ref(&self) -> GLWE<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWEToRef for GLWE<D> {
|
||||
fn to_ref(&self) -> GLWE<&[u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToMut {
|
||||
fn to_mut(&mut self) -> GLWE<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWEToMut for GLWE<D> {
|
||||
fn to_mut(&mut self) -> GLWE<&mut [u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use poulpy_hal::layouts::{Data, DataMut, DataRef, ReaderFrom, VecZnx, WriterTo, ZnxInfos};
|
||||
use poulpy_hal::layouts::{
|
||||
Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo, ZnxInfos,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
dist::Distribution,
|
||||
layouts::{Base2K, BuildError, Degree, GLWEInfos, LWEInfos, Rank, TorusPrecision},
|
||||
layouts::{Base2K, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision},
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
@@ -16,12 +18,22 @@ pub struct GLWEPublicKey<D: Data> {
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GLWEPublicKeyLayout {
|
||||
pub n: Degree,
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank: Rank,
|
||||
}
|
||||
|
||||
pub trait GetDist {
|
||||
fn get_dist(&self) -> Distribution;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GetDist for GLWEPublicKey<D> {
|
||||
fn get_dist(&self) -> Distribution {
|
||||
self.dist
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GLWEPublicKey<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
@@ -31,8 +43,8 @@ impl<D: Data> LWEInfos for GLWEPublicKey<D> {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -55,7 +67,7 @@ impl LWEInfos for GLWEPublicKeyLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
|
||||
@@ -70,117 +82,77 @@ impl GLWEInfos for GLWEPublicKeyLayout {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GLWEPublicKeyBuilder<D: Data> {
|
||||
data: Option<VecZnx<D>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEPublicKey<D> {
|
||||
#[inline]
|
||||
pub fn builder() -> GLWEPublicKeyBuilder<D> {
|
||||
GLWEPublicKeyBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEPublicKeyBuilder<Vec<u8>> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, layout: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.data = Some(VecZnx::alloc(
|
||||
layout.n().into(),
|
||||
(layout.rank() + 1).into(),
|
||||
layout.size(),
|
||||
));
|
||||
self.base2k = Some(layout.base2k());
|
||||
self.k = Some(layout.k());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEPublicKeyBuilder<D> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: VecZnx<D>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GLWEPublicKey<D>, BuildError> {
|
||||
let data: VecZnx<D> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
|
||||
if base2k == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k == 0_u32 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GLWEPublicKey {
|
||||
data,
|
||||
pub trait GLWEPublicKeyAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_glwe_public_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKey<Vec<u8>> {
|
||||
GLWEPublicKey {
|
||||
data: VecZnx::alloc(
|
||||
self.ring_degree().into(),
|
||||
(rank + 1).into(),
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
),
|
||||
base2k,
|
||||
k,
|
||||
dist: Distribution::NONE,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_glwe_public_key_from_infos<A>(&self, infos: &A) -> GLWEPublicKey<Vec<u8>>
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.alloc_glwe_public_key(infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_public_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
|
||||
VecZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
(rank + 1).into(),
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_public_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe_public_key(infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEPublicKeyAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
impl GLWEPublicKey<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWEPublicKeyAlloc,
|
||||
{
|
||||
Self::alloc_with(infos.n(), infos.base2k(), infos.k(), infos.rank())
|
||||
module.alloc_glwe_public_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
|
||||
Self {
|
||||
data: VecZnx::alloc(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
|
||||
base2k,
|
||||
k,
|
||||
dist: Distribution::NONE,
|
||||
}
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
|
||||
where
|
||||
M: GLWEPublicKeyAlloc,
|
||||
{
|
||||
module.alloc_glwe_public_key(base2k, k, rank)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWEPublicKeyAlloc,
|
||||
{
|
||||
Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k(), infos.rank())
|
||||
module.bytes_of_glwe_public_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
|
||||
VecZnx::alloc_bytes(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize
|
||||
where
|
||||
M: GLWEPublicKeyAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_public_key(base2k, k, rank)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,3 +179,33 @@ impl<D: DataRef> WriterTo for GLWEPublicKey<D> {
|
||||
self.data.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEPublicKeyToRef {
|
||||
fn to_ref(&self) -> GLWEPublicKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWEPublicKeyToRef for GLWEPublicKey<D> {
|
||||
fn to_ref(&self) -> GLWEPublicKey<&[u8]> {
|
||||
GLWEPublicKey {
|
||||
data: self.data.to_ref(),
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
dist: self.dist,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEPublicKeyToMut {
|
||||
fn to_mut(&mut self) -> GLWEPublicKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWEPublicKeyToMut for GLWEPublicKey<D> {
|
||||
fn to_mut(&mut self) -> GLWEPublicKey<&mut [u8]> {
|
||||
GLWEPublicKey {
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
dist: self.dist,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
use std::fmt;
|
||||
|
||||
use poulpy_hal::layouts::{Data, DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, BuildError, Degree, GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEInfos, GLWELayoutSet, LWEInfos,
|
||||
Rank, TorusPrecision,
|
||||
Base2K, GLWE, GLWEInfos, GLWEToMut, GLWEToRef, GetRingDegree, LWEInfos, Rank, RingDegree, SetGLWEInfos, TorusPrecision,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GLWEPlaintextLayout {
|
||||
pub n: Degree,
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
}
|
||||
@@ -23,7 +22,7 @@ impl LWEInfos for GLWEPlaintextLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
@@ -40,8 +39,8 @@ pub struct GLWEPlaintext<D: Data> {
|
||||
pub k: TorusPrecision,
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWELayoutSet for GLWEPlaintext<D> {
|
||||
fn set_basek(&mut self, base2k: Base2K) {
|
||||
impl<D: DataMut> SetGLWEInfos for GLWEPlaintext<D> {
|
||||
fn set_base2k(&mut self, base2k: Base2K) {
|
||||
self.base2k = base2k
|
||||
}
|
||||
|
||||
@@ -63,8 +62,8 @@ impl<D: Data> LWEInfos for GLWEPlaintext<D> {
|
||||
self.data.size()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,69 +73,6 @@ impl<D: Data> GLWEInfos for GLWEPlaintext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GLWEPlaintextBuilder<D: Data> {
|
||||
data: Option<VecZnx<D>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEPlaintext<D> {
|
||||
#[inline]
|
||||
pub fn builder() -> GLWEPlaintextBuilder<D> {
|
||||
GLWEPlaintextBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEPlaintextBuilder<D> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: VecZnx<D>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GLWEPlaintext<D>, BuildError> {
|
||||
let data: VecZnx<D> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
|
||||
if base2k.0 == 0 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k.0 == 0 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() != 1 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GLWEPlaintext { data, base2k, k })
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GLWEPlaintext<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
@@ -149,54 +85,123 @@ impl<D: DataRef> fmt::Display for GLWEPlaintext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEPlaintext<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_with(infos.n(), infos.base2k(), infos.k(), Rank(0))
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
|
||||
debug_assert!(rank.0 == 0);
|
||||
Self {
|
||||
data: VecZnx::alloc(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
|
||||
pub trait GLWEPlaintextAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_glwe_plaintext(&self, base2k: Base2K, k: TorusPrecision) -> GLWEPlaintext<Vec<u8>> {
|
||||
GLWEPlaintext {
|
||||
data: VecZnx::alloc(
|
||||
self.ring_degree().into(),
|
||||
1,
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
),
|
||||
base2k,
|
||||
k,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_glwe_plaintext_from_infos<A>(&self, infos: &A) -> GLWEPlaintext<Vec<u8>>
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k(), Rank(0))
|
||||
self.alloc_glwe_plaintext(infos.base2k(), infos.k())
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
|
||||
debug_assert!(rank.0 == 0);
|
||||
VecZnx::alloc_bytes(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
|
||||
fn bytes_of_glwe_plaintext(&self, base2k: Base2K, k: TorusPrecision) -> usize {
|
||||
VecZnx::bytes_of(
|
||||
self.ring_degree().into(),
|
||||
1,
|
||||
k.0.div_ceil(base2k.0) as usize,
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_plaintext_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe_plaintext(infos.base2k(), infos.k())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWECiphertextToRef for GLWEPlaintext<D> {
|
||||
fn to_ref(&self) -> GLWECiphertext<&[u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.data(self.data.to_ref())
|
||||
.k(self.k())
|
||||
.base2k(self.base2k())
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<B: Backend> GLWEPlaintextAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
impl GLWEPlaintext<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWEPlaintextAlloc,
|
||||
{
|
||||
module.alloc_glwe_plaintext_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> Self
|
||||
where
|
||||
M: GLWEPlaintextAlloc,
|
||||
{
|
||||
module.alloc_glwe_plaintext(base2k, k)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWEPlaintextAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_plaintext_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> usize
|
||||
where
|
||||
M: GLWEPlaintextAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_plaintext(base2k, k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWECiphertextToMut for GLWEPlaintext<D> {
|
||||
fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> {
|
||||
GLWECiphertext::builder()
|
||||
.k(self.k())
|
||||
.base2k(self.base2k())
|
||||
.data(self.data.to_mut())
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<D: DataRef> GLWEToRef for GLWEPlaintext<D> {
|
||||
fn to_ref(&self) -> GLWE<&[u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWEToMut for GLWEPlaintext<D> {
|
||||
fn to_mut(&mut self) -> GLWE<&mut [u8]> {
|
||||
GLWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEPlaintextToRef {
|
||||
fn to_ref(&self) -> GLWEPlaintext<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWEPlaintextToRef for GLWEPlaintext<D> {
|
||||
fn to_ref(&self) -> GLWEPlaintext<&[u8]> {
|
||||
GLWEPlaintext {
|
||||
data: self.data.to_ref(),
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEPlaintextToMut {
|
||||
fn to_ref(&mut self) -> GLWEPlaintext<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWEPlaintextToMut for GLWEPlaintext<D> {
|
||||
fn to_ref(&mut self) -> GLWEPlaintext<&mut [u8]> {
|
||||
GLWEPlaintext {
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, ReaderFrom, ScalarZnx, WriterTo, ZnxInfos, ZnxZero},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, ScalarZnxToMut, ScalarZnxToRef, WriterTo, ZnxInfos,
|
||||
ZnxZero,
|
||||
},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
dist::Distribution,
|
||||
layouts::{Base2K, Degree, GLWEInfos, LWEInfos, Rank, TorusPrecision},
|
||||
layouts::{Base2K, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GLWESecretLayout {
|
||||
pub n: Degree,
|
||||
pub n: RingDegree,
|
||||
pub rank: Rank,
|
||||
}
|
||||
|
||||
@@ -23,7 +26,7 @@ impl LWEInfos for GLWESecretLayout {
|
||||
TorusPrecision(0)
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
|
||||
@@ -52,8 +55,8 @@ impl<D: Data> LWEInfos for GLWESecret<D> {
|
||||
TorusPrecision(0)
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -67,30 +70,67 @@ impl<D: Data> GLWEInfos for GLWESecret<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWESecret<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_with(infos.n(), infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, rank: Rank) -> Self {
|
||||
Self {
|
||||
data: ScalarZnx::alloc(n.into(), rank.into()),
|
||||
pub trait GLWESecretAlloc
|
||||
where
|
||||
Self: GetRingDegree,
|
||||
{
|
||||
fn alloc_glwe_secret(&self, rank: Rank) -> GLWESecret<Vec<u8>> {
|
||||
GLWESecret {
|
||||
data: ScalarZnx::alloc(self.ring_degree().into(), rank.into()),
|
||||
dist: Distribution::NONE,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_glwe_secret_from_infos<A>(&self, infos: &A) -> GLWESecret<Vec<u8>>
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(infos.n(), infos.rank())
|
||||
self.alloc_glwe_secret(infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, rank: Rank) -> usize {
|
||||
ScalarZnx::alloc_bytes(n.into(), rank.into())
|
||||
fn bytes_of_glwe_secret(&self, rank: Rank) -> usize {
|
||||
ScalarZnx::bytes_of(self.ring_degree().into(), rank.into())
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_secret_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe_secret(infos.rank())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWESecretAlloc for Module<B> where Self: GetRingDegree {}
|
||||
|
||||
impl GLWESecret<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWESecretAlloc,
|
||||
{
|
||||
module.alloc_glwe_secret_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, rank: Rank) -> Self
|
||||
where
|
||||
M: GLWESecretAlloc,
|
||||
{
|
||||
module.alloc_glwe_secret(rank)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWESecretAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_secret_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, rank: Rank) -> usize
|
||||
where
|
||||
M: GLWESecretAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_secret(rank)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +176,32 @@ impl<D: DataMut> GLWESecret<D> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESecretToMut {
|
||||
fn to_mut(&mut self) -> GLWESecret<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESecretToMut for GLWESecret<D> {
|
||||
fn to_mut(&mut self) -> GLWESecret<&mut [u8]> {
|
||||
GLWESecret {
|
||||
dist: self.dist,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESecretToRef {
|
||||
fn to_ref(&self) -> GLWESecret<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESecretToRef for GLWESecret<D> {
|
||||
fn to_ref(&self) -> GLWESecret<&[u8]> {
|
||||
GLWESecret {
|
||||
data: self.data.to_ref(),
|
||||
dist: self.dist,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWESecret<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
match Distribution::read_from(reader) {
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
|
||||
use crate::layouts::{
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut,
|
||||
GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GLWEToLWEKeyLayout {
|
||||
pub n: Degree,
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank_in: Rank,
|
||||
@@ -17,7 +20,7 @@ pub struct GLWEToLWEKeyLayout {
|
||||
}
|
||||
|
||||
impl LWEInfos for GLWEToLWEKeyLayout {
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
|
||||
@@ -54,11 +57,11 @@ impl GGLWEInfos for GLWEToLWEKeyLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/// A special [GLWESwitchingKey] required to for the conversion from [GLWECiphertext] to [LWECiphertext].
|
||||
/// A special [GLWESwitchingKey] required to for the conversion from [GLWE] to [LWE].
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GLWEToLWEKey<D: Data>(pub(crate) GGLWESwitchingKey<D>);
|
||||
pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for GLWEToLWEKey<D> {
|
||||
impl<D: Data> LWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.0.base2k()
|
||||
}
|
||||
@@ -67,7 +70,7 @@ impl<D: Data> LWEInfos for GLWEToLWEKey<D> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
@@ -76,12 +79,12 @@ impl<D: Data> LWEInfos for GLWEToLWEKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GLWEToLWEKey<D> {
|
||||
impl<D: Data> GLWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GGLWEInfos for GLWEToLWEKey<D> {
|
||||
impl<D: Data> GGLWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.0.rank_in()
|
||||
}
|
||||
@@ -99,84 +102,145 @@ impl<D: Data> GGLWEInfos for GLWEToLWEKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GLWEToLWEKey<D> {
|
||||
impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GLWEToLWEKey<D> {
|
||||
impl<D: DataMut> FillUniform for GLWEToLWESwitchingKey<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.0.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GLWEToLWEKey<D> {
|
||||
impl<D: DataRef> fmt::Display for GLWEToLWESwitchingKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(GLWEToLWESwitchingKey) {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWEToLWEKey<D> {
|
||||
impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKey<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.0.read_from(reader)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GLWEToLWEKey<D> {
|
||||
impl<D: DataRef> WriterTo for GLWEToLWESwitchingKey<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
self.0.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEToLWEKey<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub trait GLWEToLWESwitchingKeyAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
fn alloc_glwe_to_lwe_switching_key(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
dnum: Dnum,
|
||||
) -> GLWEToLWESwitchingKey<Vec<u8>> {
|
||||
GLWEToLWESwitchingKey(self.alloc_glwe_switching_key(base2k, k, rank_in, Rank(1), dnum, Dsize(1)))
|
||||
}
|
||||
|
||||
fn alloc_glwe_to_lwe_switching_key_from_infos<A>(&self, infos: &A) -> GLWEToLWESwitchingKey<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKey"
|
||||
);
|
||||
Self(GGLWESwitchingKey::alloc(infos))
|
||||
self.alloc_glwe_to_lwe_switching_key(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self {
|
||||
Self(GGLWESwitchingKey::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
rank_in,
|
||||
Rank(1),
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
fn bytes_of_glwe_to_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_switching_key(base2k, k, rank_in, Rank(1), dnum, Dsize(1))
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn bytes_of_glwe_to_lwe_switching_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKey"
|
||||
);
|
||||
GGLWESwitchingKey::alloc_bytes(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize {
|
||||
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rank_in, Rank(1), dnum, Dsize(1))
|
||||
self.bytes_of_glwe_to_lwe_switching_key(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {}
|
||||
|
||||
impl GLWEToLWESwitchingKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.alloc_glwe_to_lwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
M: GLWEToLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.alloc_glwe_to_lwe_switching_key(base2k, k, rank_in, dnum)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_to_lwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize
|
||||
where
|
||||
M: GLWEToLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.bytes_of_glwe_to_lwe_switching_key(base2k, k, rank_in, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyToRef {
|
||||
fn to_ref(&self) -> GLWEToLWESwitchingKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWEToLWESwitchingKeyToRef for GLWEToLWESwitchingKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GLWEToLWESwitchingKey<&[u8]> {
|
||||
GLWEToLWESwitchingKey(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyToMut {
|
||||
fn to_mut(&mut self) -> GLWEToLWESwitchingKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWEToLWESwitchingKeyToMut for GLWEToLWESwitchingKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWEToLWESwitchingKey<&mut [u8]> {
|
||||
GLWEToLWESwitchingKey(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use std::fmt;
|
||||
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo, Zn, ZnToMut, ZnToRef, ZnxInfos},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo, Zn, ZnToMut, ZnToRef, ZnxInfos},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, BuildError, Degree, TorusPrecision};
|
||||
use crate::layouts::{Base2K, RingDegree, TorusPrecision};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
pub trait LWEInfos {
|
||||
fn n(&self) -> Degree;
|
||||
fn n(&self) -> RingDegree;
|
||||
fn k(&self) -> TorusPrecision;
|
||||
fn max_k(&self) -> TorusPrecision {
|
||||
TorusPrecision(self.k().0 * self.size() as u32)
|
||||
@@ -18,8 +18,8 @@ pub trait LWEInfos {
|
||||
fn size(&self) -> usize {
|
||||
self.k().0.div_ceil(self.base2k().0) as usize
|
||||
}
|
||||
fn lwe_layout(&self) -> LWECiphertextLayout {
|
||||
LWECiphertextLayout {
|
||||
fn lwe_layout(&self) -> LWELayout {
|
||||
LWELayout {
|
||||
n: self.n(),
|
||||
k: self.k(),
|
||||
base2k: self.base2k(),
|
||||
@@ -27,14 +27,19 @@ pub trait LWEInfos {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SetLWEInfos {
|
||||
fn set_k(&mut self, k: TorusPrecision);
|
||||
fn set_base2k(&mut self, base2k: Base2K);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct LWECiphertextLayout {
|
||||
pub n: Degree,
|
||||
pub struct LWELayout {
|
||||
pub n: RingDegree,
|
||||
pub k: TorusPrecision,
|
||||
pub base2k: Base2K,
|
||||
}
|
||||
|
||||
impl LWEInfos for LWECiphertextLayout {
|
||||
impl LWEInfos for LWELayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -43,19 +48,18 @@ impl LWEInfos for LWECiphertextLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWECiphertext<D: Data> {
|
||||
pub struct LWE<D: Data> {
|
||||
pub(crate) data: Zn<D>,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) base2k: Base2K,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for LWECiphertext<D> {
|
||||
impl<D: Data> LWEInfos for LWE<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -63,8 +67,8 @@ impl<D: Data> LWEInfos for LWECiphertext<D> {
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.k
|
||||
}
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32 - 1)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32 - 1)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -72,29 +76,39 @@ impl<D: Data> LWEInfos for LWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWECiphertext<D> {
|
||||
impl<D: Data> SetLWEInfos for LWE<D> {
|
||||
fn set_base2k(&mut self, base2k: Base2K) {
|
||||
self.base2k = base2k
|
||||
}
|
||||
|
||||
fn set_k(&mut self, k: TorusPrecision) {
|
||||
self.k = k
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWE<D> {
|
||||
pub fn data(&self) -> &Zn<D> {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWECiphertext<D> {
|
||||
impl<D: DataMut> LWE<D> {
|
||||
pub fn data_mut(&mut self) -> &Zn<D> {
|
||||
&mut self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for LWECiphertext<D> {
|
||||
impl<D: DataRef> fmt::Debug for LWE<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for LWECiphertext<D> {
|
||||
impl<D: DataRef> fmt::Display for LWE<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"LWECiphertext: base2k={} k={}: {}",
|
||||
"LWE: base2k={} k={}: {}",
|
||||
self.base2k().0,
|
||||
self.k().0,
|
||||
self.data
|
||||
@@ -102,7 +116,7 @@ impl<D: DataRef> fmt::Display for LWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for LWECiphertext<D>
|
||||
impl<D: DataMut> FillUniform for LWE<D>
|
||||
where
|
||||
Zn<D>: FillUniform,
|
||||
{
|
||||
@@ -111,142 +125,98 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl LWECiphertext<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
Self::alloc_with(infos.n(), infos.base2k(), infos.k())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision) -> Self {
|
||||
Self {
|
||||
pub trait LWEAlloc {
|
||||
fn alloc_lwe(&self, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> LWE<Vec<u8>> {
|
||||
LWE {
|
||||
data: Zn::alloc((n + 1).into(), 1, k.0.div_ceil(base2k.0) as usize),
|
||||
k,
|
||||
base2k,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn alloc_lwe_from_infos<A>(&self, infos: &A) -> LWE<Vec<u8>>
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k())
|
||||
self.alloc_lwe(infos.n(), infos.base2k(), infos.k())
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision) -> usize {
|
||||
Zn::alloc_bytes((n + 1).into(), 1, k.0.div_ceil(base2k.0) as usize)
|
||||
fn bytes_of_lwe(&self, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> usize {
|
||||
Zn::bytes_of((n + 1).into(), 1, k.0.div_ceil(base2k.0) as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl LWECiphertextBuilder<Vec<u8>> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, layout: A) -> Self
|
||||
fn bytes_of_lwe_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
self.data = Some(Zn::alloc((layout.n() + 1).into(), 1, layout.size()));
|
||||
self.base2k = Some(layout.base2k());
|
||||
self.k = Some(layout.k());
|
||||
self
|
||||
self.bytes_of_lwe(infos.n(), infos.base2k(), infos.k())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LWECiphertextBuilder<D: Data> {
|
||||
data: Option<Zn<D>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
impl<B: Backend> LWEAlloc for Module<B> {}
|
||||
|
||||
impl LWE<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: LWEInfos,
|
||||
M: LWEAlloc,
|
||||
{
|
||||
module.alloc_lwe_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> Self
|
||||
where
|
||||
M: LWEAlloc,
|
||||
{
|
||||
module.alloc_lwe(n, base2k, k)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: LWEInfos,
|
||||
M: LWEAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> usize
|
||||
where
|
||||
M: LWEAlloc,
|
||||
{
|
||||
module.bytes_of_lwe(n, base2k, k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWECiphertext<D> {
|
||||
#[inline]
|
||||
pub fn builder() -> LWECiphertextBuilder<D> {
|
||||
LWECiphertextBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
pub trait LWEToRef {
|
||||
fn to_ref(&self) -> LWE<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWEToRef for LWE<D> {
|
||||
fn to_ref(&self) -> LWE<&[u8]> {
|
||||
LWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWECiphertextBuilder<D> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: Zn<D>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<LWECiphertext<D>, BuildError> {
|
||||
let data: Zn<D> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
|
||||
if base2k.0 == 0 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k.0 == 0 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(LWECiphertext { data, base2k, k })
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWECiphertextToRef {
|
||||
fn to_ref(&self) -> LWECiphertext<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWECiphertextToRef for LWECiphertext<D> {
|
||||
fn to_ref(&self) -> LWECiphertext<&[u8]> {
|
||||
LWECiphertext::builder()
|
||||
.base2k(self.base2k())
|
||||
.k(self.k())
|
||||
.data(self.data.to_ref())
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWECiphertextToMut {
|
||||
pub trait LWEToMut {
|
||||
#[allow(dead_code)]
|
||||
fn to_mut(&mut self) -> LWECiphertext<&mut [u8]>;
|
||||
fn to_mut(&mut self) -> LWE<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWECiphertextToMut for LWECiphertext<D> {
|
||||
fn to_mut(&mut self) -> LWECiphertext<&mut [u8]> {
|
||||
LWECiphertext::builder()
|
||||
.base2k(self.base2k())
|
||||
.k(self.k())
|
||||
.data(self.data.to_mut())
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<D: DataMut> LWEToMut for LWE<D> {
|
||||
fn to_mut(&mut self) -> LWE<&mut [u8]> {
|
||||
LWE {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for LWECiphertext<D> {
|
||||
impl<D: DataMut> ReaderFrom for LWE<D> {
|
||||
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
|
||||
self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?);
|
||||
self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);
|
||||
@@ -254,7 +224,7 @@ impl<D: DataMut> ReaderFrom for LWECiphertext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for LWECiphertext<D> {
|
||||
impl<D: DataRef> WriterTo for LWE<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
writer.write_u32::<LittleEndian>(self.k.into())?;
|
||||
writer.write_u32::<LittleEndian>(self.base2k.into())?;
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
use std::fmt;
|
||||
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
|
||||
use crate::layouts::{
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut,
|
||||
GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct LWESwitchingKeyLayout {
|
||||
pub n: Degree,
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub dnum: Dnum,
|
||||
}
|
||||
|
||||
impl LWEInfos for LWESwitchingKeyLayout {
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
|
||||
@@ -54,7 +57,7 @@ impl GGLWEInfos for LWESwitchingKeyLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>);
|
||||
pub struct LWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for LWESwitchingKey<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -65,7 +68,7 @@ impl<D: Data> LWEInfos for LWESwitchingKey<D> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
@@ -98,65 +101,94 @@ impl<D: Data> GGLWEInfos for LWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
fn alloc_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> LWESwitchingKey<Vec<u8>> {
|
||||
LWESwitchingKey(self.alloc_glwe_switching_key(base2k, k, Rank(1), Rank(1), dnum, Dsize(1)))
|
||||
}
|
||||
|
||||
fn alloc_lwe_switching_key_from_infos<A>(&self, infos: &A) -> LWESwitchingKey<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
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"
|
||||
);
|
||||
self.alloc_lwe_switching_key(infos.base2k(), infos.k(), infos.dnum())
|
||||
}
|
||||
|
||||
fn bytes_of_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_switching_key(base2k, k, Rank(1), Rank(1), dnum, Dsize(1))
|
||||
}
|
||||
|
||||
fn bytes_of_lwe_switching_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
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"
|
||||
);
|
||||
self.bytes_of_lwe_switching_key(infos.base2k(), infos.k(), infos.dnum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWESwitchingKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {}
|
||||
|
||||
impl LWESwitchingKey<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWESwitchingKeyAlloc,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
Self(GGLWESwitchingKey::alloc(infos))
|
||||
module.alloc_lwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self {
|
||||
Self(GGLWESwitchingKey::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
Rank(1),
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self
|
||||
where
|
||||
M: LWESwitchingKeyAlloc,
|
||||
{
|
||||
module.alloc_lwe_switching_key(base2k, k, dnum)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWESwitchingKeyAlloc,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
GGLWESwitchingKey::alloc_bytes(infos)
|
||||
module.bytes_of_glwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
|
||||
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), Rank(1), dnum, Dsize(1))
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize
|
||||
where
|
||||
M: LWESwitchingKeyAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_switching_key(base2k, k, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,3 +221,29 @@ impl<D: DataRef> WriterTo for LWESwitchingKey<D> {
|
||||
self.0.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyToRef {
|
||||
fn to_ref(&self) -> LWESwitchingKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWESwitchingKeyToRef for LWESwitchingKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToRef,
|
||||
{
|
||||
fn to_ref(&self) -> LWESwitchingKey<&[u8]> {
|
||||
LWESwitchingKey(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyToMut {
|
||||
fn to_mut(&mut self) -> LWESwitchingKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWESwitchingKeyToMut for LWESwitchingKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> LWESwitchingKey<&mut [u8]> {
|
||||
LWESwitchingKey(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::fmt;
|
||||
|
||||
use poulpy_hal::layouts::{Data, DataMut, DataRef, Zn, ZnToMut, ZnToRef, ZnxInfos};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Zn, ZnToMut, ZnToRef, ZnxInfos};
|
||||
|
||||
use crate::layouts::{Base2K, Degree, LWEInfos, TorusPrecision};
|
||||
use crate::layouts::{Base2K, LWEInfos, RingDegree, TorusPrecision};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct LWEPlaintextLayout {
|
||||
@@ -19,8 +19,8 @@ impl LWEInfos for LWEPlaintextLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(0)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(0)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -43,8 +43,8 @@ impl<D: Data> LWEInfos for LWEPlaintext<D> {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32 - 1)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32 - 1)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -52,21 +52,40 @@ impl<D: Data> LWEInfos for LWEPlaintext<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEPlaintext<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
Self::alloc_with(infos.base2k(), infos.k())
|
||||
}
|
||||
|
||||
pub fn alloc_with(base2k: Base2K, k: TorusPrecision) -> Self {
|
||||
Self {
|
||||
pub trait LWEPlaintextAlloc {
|
||||
fn alloc_lwe_plaintext(&self, base2k: Base2K, k: TorusPrecision) -> LWEPlaintext<Vec<u8>> {
|
||||
LWEPlaintext {
|
||||
data: Zn::alloc(1, 1, k.0.div_ceil(base2k.0) as usize),
|
||||
k,
|
||||
base2k,
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_lwe_plaintext_from_infos<A>(&self, infos: &A) -> LWEPlaintext<Vec<u8>>
|
||||
where
|
||||
A: LWEInfos,
|
||||
{
|
||||
self.alloc_lwe_plaintext(infos.base2k(), infos.k())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEPlaintextAlloc for Module<B> {}
|
||||
|
||||
impl LWEPlaintext<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: LWEInfos,
|
||||
M: LWEPlaintextAlloc,
|
||||
{
|
||||
module.alloc_lwe_plaintext_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> Self
|
||||
where
|
||||
M: LWEPlaintextAlloc,
|
||||
{
|
||||
module.alloc_lwe_plaintext(base2k, k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for LWEPlaintext<D> {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, ScalarZnx, ZnxInfos, ZnxView, ZnxZero},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToMut, ScalarZnxToRef, ZnxInfos, ZnxView, ZnxZero},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
dist::Distribution,
|
||||
layouts::{Base2K, Degree, LWEInfos, TorusPrecision},
|
||||
layouts::{Base2K, LWEInfos, RingDegree, TorusPrecision},
|
||||
};
|
||||
|
||||
pub struct LWESecret<D: Data> {
|
||||
@@ -13,15 +13,26 @@ pub struct LWESecret<D: Data> {
|
||||
pub(crate) dist: Distribution,
|
||||
}
|
||||
|
||||
impl LWESecret<Vec<u8>> {
|
||||
pub fn alloc(n: Degree) -> Self {
|
||||
Self {
|
||||
pub trait LWESecretAlloc {
|
||||
fn alloc_lwe_secret(&self, n: RingDegree) -> LWESecret<Vec<u8>> {
|
||||
LWESecret {
|
||||
data: ScalarZnx::alloc(n.into(), 1),
|
||||
dist: Distribution::NONE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWESecretAlloc for Module<B> {}
|
||||
|
||||
impl LWESecret<Vec<u8>> {
|
||||
pub fn alloc<M>(module: &M, n: RingDegree) -> Self
|
||||
where
|
||||
M: LWESecretAlloc,
|
||||
{
|
||||
module.alloc_lwe_secret(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWESecret<D> {
|
||||
pub fn raw(&self) -> &[i64] {
|
||||
self.data.at(0, 0)
|
||||
@@ -44,8 +55,8 @@ impl<D: Data> LWEInfos for LWESecret<D> {
|
||||
TorusPrecision(0)
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -84,3 +95,29 @@ impl<D: DataMut> LWESecret<D> {
|
||||
self.dist = Distribution::ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESecretToRef {
|
||||
fn to_ref(&self) -> LWESecret<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWESecretToRef for LWESecret<D> {
|
||||
fn to_ref(&self) -> LWESecret<&[u8]> {
|
||||
LWESecret {
|
||||
dist: self.dist,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESecretToMut {
|
||||
fn to_mut(&mut self) -> LWESecret<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWESecretToMut for LWESecret<D> {
|
||||
fn to_mut(&mut self) -> LWESecret<&mut [u8]> {
|
||||
LWESecret {
|
||||
dist: self.dist,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
use std::fmt;
|
||||
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision};
|
||||
use crate::layouts::{
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut,
|
||||
GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct LWEToGLWESwitchingKeyLayout {
|
||||
pub n: Degree,
|
||||
pub n: RingDegree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank_out: Rank,
|
||||
@@ -25,7 +28,7 @@ impl LWEInfos for LWEToGLWESwitchingKeyLayout {
|
||||
self.k
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.n
|
||||
}
|
||||
}
|
||||
@@ -55,7 +58,7 @@ impl GGLWEInfos for LWEToGLWESwitchingKeyLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWEToGLWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>);
|
||||
pub struct LWEToGLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for LWEToGLWESwitchingKey<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -66,7 +69,7 @@ impl<D: Data> LWEInfos for LWEToGLWESwitchingKey<D> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
@@ -128,54 +131,116 @@ impl<D: DataRef> WriterTo for LWEToGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
pub fn alloc<A>(infos: &A) -> Self
|
||||
pub trait LWEToGLWESwitchingKeyAlloc
|
||||
where
|
||||
Self: GLWESwitchingKeyAlloc,
|
||||
{
|
||||
fn alloc_lwe_to_glwe_switching_key(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
) -> LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
LWEToGLWESwitchingKey(self.alloc_glwe_switching_key(base2k, k, Rank(1), rank_out, dnum, Dsize(1)))
|
||||
}
|
||||
|
||||
fn alloc_lwe_to_glwe_switching_key_from_infos<A>(&self, infos: &A) -> LWEToGLWESwitchingKey<Vec<u8>>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
Self(GGLWESwitchingKey::alloc(infos))
|
||||
|
||||
self.alloc_lwe_to_glwe_switching_key(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
}
|
||||
|
||||
pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self {
|
||||
Self(GGLWESwitchingKey::alloc_with(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
rank_out,
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
fn bytes_of_lwe_to_glwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_switching_key(base2k, k, Rank(1), rank_out, dnum, Dsize(1))
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(infos: &A) -> usize
|
||||
fn bytes_of_lwe_to_glwe_switching_key_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
GGLWESwitchingKey::alloc_bytes(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize {
|
||||
GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), rank_out, dnum, Dsize(1))
|
||||
self.bytes_of_lwe_to_glwe_switching_key(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {}
|
||||
|
||||
impl LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.alloc_lwe_to_glwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
M: LWEToGLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.alloc_lwe_to_glwe_switching_key(base2k, k, rank_out, dnum)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_to_glwe_switching_key_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize
|
||||
where
|
||||
M: LWEToGLWESwitchingKeyAlloc,
|
||||
{
|
||||
module.bytes_of_lwe_to_glwe_switching_key(base2k, k, rank_out, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyToRef {
|
||||
fn to_ref(&self) -> LWEToGLWESwitchingKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> LWEToGLWESwitchingKeyToRef for LWEToGLWESwitchingKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToRef,
|
||||
{
|
||||
fn to_ref(&self) -> LWEToGLWESwitchingKey<&[u8]> {
|
||||
LWEToGLWESwitchingKey(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyToMut {
|
||||
fn to_mut(&mut self) -> LWEToGLWESwitchingKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> LWEToGLWESwitchingKeyToMut for LWEToGLWESwitchingKey<D>
|
||||
where
|
||||
GLWESwitchingKey<D>: GLWESwitchingKeyToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> LWEToGLWESwitchingKey<&mut [u8]> {
|
||||
LWEToGLWESwitchingKey(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,20 +33,16 @@ pub use lwe_pt::*;
|
||||
pub use lwe_sk::*;
|
||||
pub use lwe_to_glwe_ksk::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BuildError {
|
||||
MissingData,
|
||||
MissingBase2K,
|
||||
MissingK,
|
||||
MissingDigits,
|
||||
ZeroDegree,
|
||||
NonPowerOfTwoDegree,
|
||||
ZeroBase2K,
|
||||
ZeroTorusPrecision,
|
||||
ZeroCols,
|
||||
ZeroLimbs,
|
||||
ZeroRank,
|
||||
ZeroDigits,
|
||||
use poulpy_hal::layouts::{Backend, Module};
|
||||
|
||||
pub trait GetRingDegree {
|
||||
fn ring_degree(&self) -> RingDegree;
|
||||
}
|
||||
|
||||
impl<B: Backend> GetRingDegree for Module<B> {
|
||||
fn ring_degree(&self) -> RingDegree {
|
||||
Self::n(&self).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Newtype over `u32` with arithmetic and comparisons against same type and `u32`.
|
||||
@@ -206,14 +202,14 @@ macro_rules! newtype_u32 {
|
||||
};
|
||||
}
|
||||
|
||||
newtype_u32!(Degree);
|
||||
newtype_u32!(RingDegree);
|
||||
newtype_u32!(TorusPrecision);
|
||||
newtype_u32!(Base2K);
|
||||
newtype_u32!(Dnum);
|
||||
newtype_u32!(Rank);
|
||||
newtype_u32!(Dsize);
|
||||
|
||||
impl Degree {
|
||||
impl RingDegree {
|
||||
pub fn log2(&self) -> usize {
|
||||
let n: usize = self.0 as usize;
|
||||
(usize::BITS - (n - 1).leading_zeros()) as _
|
||||
|
||||
@@ -1,27 +1,21 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
AutomorphismKeyToRef, Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
prepared::{
|
||||
GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut,
|
||||
GLWESwitchingKeyPreparedToRef,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGLWEAutomorphismKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) key: GGLWESwitchingKeyPrepared<D, B>,
|
||||
pub struct AutomorphismKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) key: GLWESwitchingKeyPrepared<D, B>,
|
||||
pub(crate) p: i64,
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWEAutomorphismKeyPrepared<D, B> {
|
||||
pub fn p(&self) -> i64 {
|
||||
self.p
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GGLWEAutomorphismKeyPrepared<D, B> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: Data, B: Backend> LWEInfos for AutomorphismKeyPrepared<D, B> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.key.n()
|
||||
}
|
||||
|
||||
@@ -38,13 +32,33 @@ impl<D: Data, B: Backend> LWEInfos for GGLWEAutomorphismKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for GGLWEAutomorphismKeyPrepared<D, B> {
|
||||
pub trait GetAutomorphismGaloisElement {
|
||||
fn p(&self) -> i64;
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GetAutomorphismGaloisElement for AutomorphismKeyPrepared<D, B> {
|
||||
fn p(&self) -> i64 {
|
||||
self.p
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SetAutomorphismGaloisElement {
|
||||
fn set_p(&mut self, p: i64);
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> SetAutomorphismGaloisElement for AutomorphismKeyPrepared<D, B> {
|
||||
fn set_p(&mut self, p: i64) {
|
||||
self.p = p
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for AutomorphismKeyPrepared<D, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GGLWEAutomorphismKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GGLWEInfos for AutomorphismKeyPrepared<D, B> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.key.rank_in()
|
||||
}
|
||||
@@ -62,80 +76,170 @@ impl<D: Data, B: Backend> GGLWEInfos for GGLWEAutomorphismKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
pub trait AutomorphismKeyPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
fn alloc_automorphism_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> AutomorphismKeyPrepared<Vec<u8>, B> {
|
||||
AutomorphismKeyPrepared::<Vec<u8>, B> {
|
||||
key: self.alloc_glwe_switching_key_prepared(base2k, k, rank, rank, dnum, dsize),
|
||||
p: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> AutomorphismKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for AutomorphismKeyPrepared"
|
||||
);
|
||||
self.alloc_automorphism_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_automorphism_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize {
|
||||
self.bytes_of_glwe_switching_key_prepared(base2k, k, rank, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
fn bytes_of_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEAutomorphismKeyPrepared"
|
||||
);
|
||||
GGLWEAutomorphismKeyPrepared::<Vec<u8>, B> {
|
||||
key: GGLWESwitchingKeyPrepared::alloc(module, infos),
|
||||
p: 0,
|
||||
}
|
||||
self.bytes_of_automorphism_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
GGLWEAutomorphismKeyPrepared {
|
||||
key: GGLWESwitchingKeyPrepared::alloc_with(module, base2k, k, rank, rank, dnum, dsize),
|
||||
p: 0,
|
||||
}
|
||||
}
|
||||
impl<B: Backend> AutomorphismKeyPreparedAlloc<B> for Module<B> where Module<B>: GLWESwitchingKeyPreparedAlloc<B> {}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
impl<B: Backend> AutomorphismKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: AutomorphismKeyPreparedAlloc<B>,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEAutomorphismKeyPrepared"
|
||||
);
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
|
||||
module.alloc_automorphism_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: AutomorphismKeyPreparedAlloc<B>,
|
||||
{
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rank, rank, dnum, dsize)
|
||||
module.alloc_automorphism_key_prepared(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: AutomorphismKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_automorphism_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: AutomorphismKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_automorphism_key_prepared(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWEAutomorphismKeyPrepared<Vec<u8>, B>
|
||||
pub trait PrepareAutomorphismKey<B: Backend>
|
||||
where
|
||||
GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>,
|
||||
Self: GLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos)
|
||||
fn prepare_automorphism_key_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.prepare_glwe_switching_key_tmp_bytes(infos)
|
||||
}
|
||||
|
||||
fn prepare_automorphism_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: AutomorphismKeyPreparedToMut<B> + SetAutomorphismGaloisElement,
|
||||
O: AutomorphismKeyToRef + GetAutomorphismGaloisElement,
|
||||
{
|
||||
self.prepare_glwe_switching(&mut res.to_mut().key, &other.to_ref().key, scratch);
|
||||
res.set_p(other.p());
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWEAutomorphismKey<DR>> for GGLWEAutomorphismKeyPrepared<D, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<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<B: Backend> PrepareAutomorphismKey<B> for Module<B> where Module<B>: GLWESwitchingKeyPrepare<B> {}
|
||||
|
||||
impl<B: Backend> AutomorphismKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<M>(&self, module: &M) -> usize
|
||||
where
|
||||
M: PrepareAutomorphismKey<B>,
|
||||
{
|
||||
module.prepare_automorphism_key_tmp_bytes(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> for GGLWEAutomorphismKey<D>
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<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);
|
||||
atk_prepared.prepare(module, self, scratch);
|
||||
atk_prepared
|
||||
impl<D: DataMut, B: Backend> AutomorphismKeyPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: AutomorphismKeyToRef + GetAutomorphismGaloisElement,
|
||||
M: PrepareAutomorphismKey<B>,
|
||||
{
|
||||
module.prepare_automorphism_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AutomorphismKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> AutomorphismKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> AutomorphismKeyPreparedToMut<B> for AutomorphismKeyPrepared<D, B> {
|
||||
fn to_mut(&mut self) -> AutomorphismKeyPrepared<&mut [u8], B> {
|
||||
AutomorphismKeyPrepared {
|
||||
p: self.p,
|
||||
key: self.key.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AutomorphismKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> AutomorphismKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> AutomorphismKeyPreparedToRef<B> for AutomorphismKeyPrepared<D, B> {
|
||||
fn to_ref(&self) -> AutomorphismKeyPrepared<&[u8], B> {
|
||||
AutomorphismKeyPrepared {
|
||||
p: self.p,
|
||||
key: self.key.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare, VmpPrepareTmpBytes},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, ZnxInfos},
|
||||
oep::VmpPMatAllocBytesImpl,
|
||||
api::{VmpPMatAlloc, VmpPMatBytesOf, VmpPrepare, VmpPrepareTmpBytes},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToMut, VmpPMatToRef, ZnxInfos},
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, BuildError, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, Dnum, Dsize, GGLWE, GGLWEInfos, GGLWEToRef, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGLWECiphertextPrepared<D: Data, B: Backend> {
|
||||
pub struct GGLWEPrepared<D: Data, B: Backend> {
|
||||
pub(crate) data: VmpPMat<D, B>,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) dsize: Dsize,
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GGLWECiphertextPrepared<D, B> {
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
impl<D: Data, B: Backend> LWEInfos for GGLWEPrepared<D, B> {
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -35,13 +33,13 @@ impl<D: Data, B: Backend> LWEInfos for GGLWECiphertextPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for GGLWECiphertextPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GLWEInfos for GGLWEPrepared<D, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GGLWECiphertextPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GGLWEPrepared<D, B> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
Rank(self.data.cols_in() as u32)
|
||||
}
|
||||
@@ -59,117 +57,47 @@ impl<D: Data, B: Backend> GGLWEInfos for GGLWECiphertextPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GGLWECiphertextPreparedBuilder<D: Data, B: Backend> {
|
||||
data: Option<VmpPMat<D, B>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
dsize: Option<Dsize>,
|
||||
}
|
||||
pub trait GGLWEPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf,
|
||||
{
|
||||
fn alloc_gglwe_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> GGLWEPrepared<Vec<u8>, B> {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
|
||||
dsize.0
|
||||
);
|
||||
|
||||
impl<D: Data, B: Backend> GGLWECiphertextPrepared<D, B> {
|
||||
#[inline]
|
||||
pub fn builder() -> GGLWECiphertextPreparedBuilder<D, B> {
|
||||
GGLWECiphertextPreparedBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
dsize: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
dnum.0 * dsize.0 <= size as u32,
|
||||
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
|
||||
dnum.0,
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
impl<B: Backend> GGLWECiphertextPreparedBuilder<Vec<u8>, B> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
B: VmpPMatAllocBytesImpl<B>,
|
||||
{
|
||||
self.data = Some(VmpPMat::alloc(
|
||||
infos.n().into(),
|
||||
infos.dnum().into(),
|
||||
infos.rank_in().into(),
|
||||
(infos.rank_out() + 1).into(),
|
||||
infos.size(),
|
||||
));
|
||||
self.base2k = Some(infos.base2k());
|
||||
self.k = Some(infos.k());
|
||||
self.dsize = Some(infos.dsize());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWECiphertextPreparedBuilder<D, B> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: VmpPMat<D, B>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dsize(mut self, dsize: Dsize) -> Self {
|
||||
self.dsize = Some(dsize);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GGLWECiphertextPrepared<D, B>, BuildError> {
|
||||
let data: VmpPMat<D, B> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
|
||||
|
||||
if base2k == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if dsize == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k == 0_u32 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GGLWECiphertextPrepared {
|
||||
data,
|
||||
base2k,
|
||||
GGLWEPrepared {
|
||||
data: self.vmp_pmat_alloc(dnum.into(), rank_in.into(), (rank_out + 1).into(), size),
|
||||
k,
|
||||
base2k,
|
||||
dsize,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
fn alloc_gglwe_prepared_from_infos<A>(&self, infos: &A) -> GGLWEPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
|
||||
Self::alloc_with(
|
||||
module,
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.alloc_gglwe_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
@@ -179,8 +107,61 @@ impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(
|
||||
module: &Module<B>,
|
||||
fn bytes_of_gglwe_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
|
||||
dsize.0
|
||||
);
|
||||
|
||||
assert!(
|
||||
dnum.0 * dsize.0 <= size as u32,
|
||||
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
|
||||
dnum.0,
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
self.bytes_of_vmp_pmat(dnum.into(), rank_in.into(), (rank_out + 1).into(), size)
|
||||
}
|
||||
|
||||
fn bytes_of_gglwe_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.bytes_of_gglwe_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGLWEPreparedAlloc<B> for Module<B> where Module<B>: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf {}
|
||||
|
||||
impl<B: Backend> GGLWEPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GGLWEPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_gglwe_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
@@ -189,49 +170,21 @@ impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
|
||||
dsize: Dsize,
|
||||
) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: GGLWEPreparedAlloc<B>,
|
||||
{
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
|
||||
dsize.0
|
||||
);
|
||||
|
||||
assert!(
|
||||
dnum.0 * dsize.0 <= size as u32,
|
||||
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
|
||||
dnum.0,
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
data: module.vmp_pmat_alloc(dnum.into(), rank_in.into(), (rank_out + 1).into(), size),
|
||||
k,
|
||||
base2k,
|
||||
dsize,
|
||||
}
|
||||
module.alloc_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: GGLWEPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
|
||||
Self::alloc_bytes_with(
|
||||
module,
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
module.bytes_of_gglwe_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(
|
||||
module: &Module<B>,
|
||||
pub fn bytes_of<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
@@ -240,59 +193,93 @@ impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> {
|
||||
dsize: Dsize,
|
||||
) -> usize
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: GGLWEPreparedAlloc<B>,
|
||||
{
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
"invalid gglwe: ceil(k/base2k): {size} <= dsize: {}",
|
||||
dsize.0
|
||||
);
|
||||
|
||||
assert!(
|
||||
dnum.0 * dsize.0 <= size as u32,
|
||||
"invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}",
|
||||
dnum.0,
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
module.vmp_pmat_alloc_bytes(dnum.into(), rank_in.into(), (rank_out + 1).into(), size)
|
||||
module.bytes_of_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWECiphertextPrepared<Vec<u8>, B>
|
||||
pub trait GGLWEPrepare<B: Backend>
|
||||
where
|
||||
Module<B>: VmpPrepareTmpBytes,
|
||||
Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
module.vmp_prepare_tmp_bytes(
|
||||
fn prepare_gglwe_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.vmp_prepare_tmp_bytes(
|
||||
infos.dnum().into(),
|
||||
infos.rank_in().into(),
|
||||
(infos.rank() + 1).into(),
|
||||
infos.size(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWECiphertext<DR>> for GGLWECiphertextPrepared<D, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<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.k = other.k;
|
||||
self.base2k = other.base2k;
|
||||
self.dsize = other.dsize;
|
||||
fn prepare_gglwe<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: GGLWEPreparedToMut<B>,
|
||||
O: GGLWEToRef,
|
||||
{
|
||||
let mut res: GGLWEPrepared<&mut [u8], B> = res.to_mut();
|
||||
let other: GGLWE<&[u8]> = other.to_ref();
|
||||
|
||||
assert_eq!(res.n(), self.ring_degree());
|
||||
assert_eq!(other.n(), self.ring_degree());
|
||||
assert_eq!(res.base2k, other.base2k);
|
||||
assert_eq!(res.k, other.k);
|
||||
assert_eq!(res.dsize, other.dsize);
|
||||
|
||||
self.vmp_prepare(&mut res.data, &other.data, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWECiphertextPrepared<Vec<u8>, B>> for GGLWECiphertext<D>
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<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);
|
||||
atk_prepared.prepare(module, self, scratch);
|
||||
atk_prepared
|
||||
impl<B: Backend> GGLWEPrepare<B> for Module<B> where Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B> {}
|
||||
|
||||
impl<D: DataMut, B: Backend> GGLWEPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: GGLWEToRef,
|
||||
M: GGLWEPrepare<B>,
|
||||
{
|
||||
module.prepare_gglwe(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGLWEPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<M>(&self, module: &M) -> usize
|
||||
where
|
||||
M: GGLWEPrepare<B>,
|
||||
{
|
||||
module.prepare_gglwe_tmp_bytes(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> GGLWEPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GGLWEPreparedToMut<B> for GGLWEPrepared<D, B> {
|
||||
fn to_mut(&mut self) -> GGLWEPrepared<&mut [u8], B> {
|
||||
GGLWEPrepared {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
dsize: self.dsize,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GGLWEPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGLWEPreparedToRef<B> for GGLWEPrepared<D, B> {
|
||||
fn to_ref(&self) -> GGLWEPrepared<&[u8], B> {
|
||||
GGLWEPrepared {
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
dsize: self.dsize,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,40 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{GGLWECiphertextPrepared, Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKeySetMetaData, GLWESwitchingKeyToRef, GLWESwtichingKeyGetMetaData,
|
||||
LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
prepared::{GGLWEPrepare, GGLWEPrepared, GGLWEPreparedAlloc, GGLWEPreparedToMut, GGLWEPreparedToRef},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGLWESwitchingKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) key: GGLWECiphertextPrepared<D, B>,
|
||||
pub struct GLWESwitchingKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) key: GGLWEPrepared<D, B>,
|
||||
pub(crate) sk_in_n: usize, // Degree of sk_in
|
||||
pub(crate) sk_out_n: usize, // Degree of sk_out
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GGLWESwitchingKeyPrepared<D, B> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: DataMut, B: Backend> GLWESwitchingKeySetMetaData for GLWESwitchingKeyPrepared<D, B> {
|
||||
fn set_sk_in_n(&mut self, sk_in_n: usize) {
|
||||
self.sk_in_n = sk_in_n
|
||||
}
|
||||
|
||||
fn set_sk_out_n(&mut self, sk_out_n: usize) {
|
||||
self.sk_out_n = sk_out_n
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWESwtichingKeyGetMetaData for GLWESwitchingKeyPrepared<D, B> {
|
||||
fn sk_in_n(&self) -> usize {
|
||||
self.sk_in_n
|
||||
}
|
||||
|
||||
fn sk_out_n(&self) -> usize {
|
||||
self.sk_out_n
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GLWESwitchingKeyPrepared<D, B> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.key.n()
|
||||
}
|
||||
|
||||
@@ -33,13 +51,13 @@ impl<D: Data, B: Backend> LWEInfos for GGLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for GGLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GLWEInfos for GLWESwitchingKeyPrepared<D, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GGLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GLWESwitchingKeyPrepared<D, B> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.key.rank_in()
|
||||
}
|
||||
@@ -57,22 +75,80 @@ impl<D: Data, B: Backend> GGLWEInfos for GGLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()");
|
||||
GGLWESwitchingKeyPrepared::<Vec<u8>, B> {
|
||||
key: GGLWECiphertextPrepared::alloc(module, infos),
|
||||
pub trait GLWESwitchingKeyPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GGLWEPreparedAlloc<B>,
|
||||
{
|
||||
fn alloc_glwe_switching_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> GLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
GLWESwitchingKeyPrepared::<Vec<u8>, B> {
|
||||
key: self.alloc_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize),
|
||||
sk_in_n: 0,
|
||||
sk_out_n: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_with(
|
||||
module: &Module<B>,
|
||||
fn alloc_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> GLWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.alloc_glwe_switching_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_switching_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> usize {
|
||||
self.bytes_of_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe_switching_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GGLWEPreparedAlloc<B> {}
|
||||
|
||||
impl<B: Backend> GLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_glwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
@@ -81,26 +157,21 @@ impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
dsize: Dsize,
|
||||
) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
GGLWESwitchingKeyPrepared::<Vec<u8>, B> {
|
||||
key: GGLWECiphertextPrepared::alloc_with(module, base2k, k, rank_in, rank_out, dnum, dsize),
|
||||
sk_in_n: 0,
|
||||
sk_out_n: 0,
|
||||
}
|
||||
module.alloc_glwe_switching_key_prepared(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()");
|
||||
GGLWECiphertextPrepared::alloc_bytes(module, infos)
|
||||
module.bytes_of_glwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(
|
||||
module: &Module<B>,
|
||||
pub fn bytes_of<M>(
|
||||
module: &M,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
@@ -109,39 +180,79 @@ impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
dsize: Dsize,
|
||||
) -> usize
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
GGLWECiphertextPrepared::alloc_bytes_with(module, base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
module.bytes_of_glwe_switching_key_prepared(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
pub trait GLWESwitchingKeyPrepare<B: Backend>
|
||||
where
|
||||
GGLWECiphertextPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>,
|
||||
Self: GGLWEPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
GGLWECiphertextPrepared::prepare_scratch_space(module, infos)
|
||||
fn prepare_glwe_switching_key_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.prepare_gglwe_tmp_bytes(infos)
|
||||
}
|
||||
|
||||
fn prepare_glwe_switching<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: GLWESwitchingKeyPreparedToMut<B> + GLWESwitchingKeySetMetaData,
|
||||
O: GLWESwitchingKeyToRef + GLWESwtichingKeyGetMetaData,
|
||||
{
|
||||
self.prepare_gglwe(&mut res.to_mut().key, &other.to_ref().key, scratch);
|
||||
res.set_sk_in_n(other.sk_in_n());
|
||||
res.set_sk_out_n(other.sk_out_n());
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWESwitchingKey<DR>> for GGLWESwitchingKeyPrepared<D, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<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<B: Backend> GLWESwitchingKeyPrepare<B> for Module<B> where Self: GGLWEPrepare<B> {}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWESwitchingKeyPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: GLWESwitchingKeyToRef + GLWESwtichingKeyGetMetaData,
|
||||
M: GLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_glwe_switching(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWESwitchingKeyPrepared<Vec<u8>, B>> for GGLWESwitchingKey<D>
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<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);
|
||||
atk_prepared.prepare(module, self, scratch);
|
||||
atk_prepared
|
||||
impl<B: Backend> GLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<M>(&self, module: &M) -> usize
|
||||
where
|
||||
M: GLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_glwe_switching_key_tmp_bytes(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESwitchingKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> GLWESwitchingKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWESwitchingKeyPreparedToMut<B> for GLWESwitchingKeyPrepared<D, B> {
|
||||
fn to_mut(&mut self) -> GLWESwitchingKeyPrepared<&mut [u8], B> {
|
||||
GLWESwitchingKeyPrepared {
|
||||
sk_in_n: self.sk_in_n,
|
||||
sk_out_n: self.sk_out_n,
|
||||
key: self.key.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESwitchingKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GLWESwitchingKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWESwitchingKeyPreparedToRef<B> for GLWESwitchingKeyPrepared<D, B> {
|
||||
fn to_ref(&self) -> GLWESwitchingKeyPrepared<&[u8], B> {
|
||||
GLWESwitchingKeyPrepared {
|
||||
sk_in_n: self.sk_in_n,
|
||||
sk_out_n: self.sk_out_n,
|
||||
key: self.key.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree, TensorKey, TensorKeyToRef, TorusPrecision,
|
||||
prepared::{
|
||||
GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut,
|
||||
GLWESwitchingKeyPreparedToRef,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGLWETensorKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) keys: Vec<GGLWESwitchingKeyPrepared<D, B>>,
|
||||
pub struct TensorKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) keys: Vec<GLWESwitchingKeyPrepared<D, B>>,
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GGLWETensorKeyPrepared<D, B> {
|
||||
fn n(&self) -> Degree {
|
||||
impl<D: Data, B: Backend> LWEInfos for TensorKeyPrepared<D, B> {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
@@ -31,13 +31,13 @@ impl<D: Data, B: Backend> LWEInfos for GGLWETensorKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for GGLWETensorKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GLWEInfos for TensorKeyPrepared<D, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GGLWETensorKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GGLWEInfos for TensorKeyPrepared<D, B> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
@@ -55,19 +55,36 @@ impl<D: Data, B: Backend> GGLWEInfos for GGLWETensorKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
pub trait TensorKeyPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
fn alloc_tensor_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
rank: Rank,
|
||||
) -> TensorKeyPrepared<Vec<u8>, B> {
|
||||
let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
|
||||
TensorKeyPrepared {
|
||||
keys: (0..pairs)
|
||||
.map(|_| self.alloc_glwe_switching_key_prepared(base2k, k, Rank(1), rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> TensorKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWETensorKeyPrepared"
|
||||
);
|
||||
Self::alloc_with(
|
||||
module,
|
||||
self.alloc_tensor_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.dnum(),
|
||||
@@ -76,62 +93,62 @@ impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
let mut keys: Vec<GGLWESwitchingKeyPrepared<Vec<u8>, B>> = Vec::new();
|
||||
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
|
||||
(0..pairs).for_each(|_| {
|
||||
keys.push(GGLWESwitchingKeyPrepared::alloc_with(
|
||||
module,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
rank,
|
||||
dnum,
|
||||
dsize,
|
||||
));
|
||||
});
|
||||
Self { keys }
|
||||
fn bytes_of_tensor_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
|
||||
pairs * self.bytes_of_glwe_switching_key_prepared(base2k, k, Rank(1), rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
fn bytes_of_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWETensorKey"
|
||||
);
|
||||
let rank_out: usize = infos.rank_out().into();
|
||||
let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1);
|
||||
pairs
|
||||
* GGLWESwitchingKeyPrepared::alloc_bytes_with(
|
||||
module,
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
Rank(1),
|
||||
infos.rank_out(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
{
|
||||
let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
|
||||
pairs * GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank, dnum, dsize)
|
||||
self.bytes_of_tensor_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GGLWETensorKeyPrepared<D, B> {
|
||||
impl<B: Backend> TensorKeyPreparedAlloc<B> for Module<B> where Module<B>: GLWESwitchingKeyPreparedAlloc<B> {}
|
||||
|
||||
impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: TensorKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_tensor_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
|
||||
where
|
||||
M: TensorKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_tensor_key_prepared(base2k, k, dnum, dsize, rank)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: TensorKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_tensor_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: TensorKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_tensor_key_prepared(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> TensorKeyPrepared<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 GGLWESwitchingKeyPrepared<D, B> {
|
||||
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyPrepared<D, B> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
@@ -140,9 +157,9 @@ impl<D: DataMut, B: Backend> GGLWETensorKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGLWETensorKeyPrepared<D, B> {
|
||||
impl<D: DataRef, B: Backend> TensorKeyPrepared<D, B> {
|
||||
// Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
|
||||
pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyPrepared<D, B> {
|
||||
pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyPrepared<D, B> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
@@ -151,40 +168,81 @@ impl<D: DataRef, B: Backend> GGLWETensorKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWETensorKeyPrepared<Vec<u8>, B>
|
||||
pub trait TensorKeyPrepare<B: Backend>
|
||||
where
|
||||
GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>,
|
||||
Self: GLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos)
|
||||
fn prepare_tensor_key_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.prepare_glwe_switching_key_tmp_bytes(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWETensorKey<DR>> for GGLWETensorKeyPrepared<D, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<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());
|
||||
fn prepare_tensor_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: TensorKeyPreparedToMut<B>,
|
||||
O: TensorKeyToRef,
|
||||
{
|
||||
let mut res: TensorKeyPrepared<&mut [u8], B> = res.to_mut();
|
||||
let other: TensorKey<&[u8]> = other.to_ref();
|
||||
|
||||
assert_eq!(res.keys.len(), other.keys.len());
|
||||
|
||||
for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) {
|
||||
self.prepare_glwe_switching(a, b, scratch);
|
||||
}
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.zip(other.keys.iter())
|
||||
.for_each(|(a, b)| {
|
||||
a.prepare(module, b, scratch);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>> for GGLWETensorKey<D>
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<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);
|
||||
tsk_prepared.prepare(module, self, scratch);
|
||||
tsk_prepared
|
||||
impl<B: Backend> TensorKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {}
|
||||
|
||||
impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> {
|
||||
fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: TensorKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_tensor_key_tmp_bytes(infos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> {
|
||||
fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: TensorKeyToRef,
|
||||
M: TensorKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_tensor_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TensorKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> TensorKeyPreparedToMut<B> for TensorKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>,
|
||||
{
|
||||
fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B> {
|
||||
TensorKeyPrepared {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TensorKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> TensorKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> TensorKeyPreparedToRef<B> for TensorKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>,
|
||||
{
|
||||
fn to_ref(&self) -> TensorKeyPrepared<&[u8], B> {
|
||||
TensorKeyPrepared {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare, VmpPrepareTmpBytes},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToRef, ZnxInfos},
|
||||
oep::VmpPMatAllocBytesImpl,
|
||||
api::{VmpPMatAlloc, VmpPMatBytesOf, VmpPrepare, VmpPrepareTmpBytes},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToMut, VmpPMatToRef, ZnxInfos},
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, BuildError, Degree, Dnum, Dsize, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, Dnum, Dsize, GGSW, GGSWInfos, GGSWToRef, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GGSWCiphertextPrepared<D: Data, B: Backend> {
|
||||
pub struct GGSWPrepared<D: Data, B: Backend> {
|
||||
pub(crate) data: VmpPMat<D, B>,
|
||||
pub(crate) k: TorusPrecision,
|
||||
pub(crate) base2k: Base2K,
|
||||
pub(crate) dsize: Dsize,
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GGSWCiphertextPrepared<D, B> {
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
impl<D: Data, B: Backend> LWEInfos for GGSWPrepared<D, B> {
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -35,13 +33,13 @@ impl<D: Data, B: Backend> LWEInfos for GGSWCiphertextPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for GGSWCiphertextPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GLWEInfos for GGSWPrepared<D, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
Rank(self.data.cols_out() as u32 - 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGSWInfos for GGSWCiphertextPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GGSWInfos for GGSWPrepared<D, B> {
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.dsize
|
||||
}
|
||||
@@ -51,143 +49,18 @@ impl<D: Data, B: Backend> GGSWInfos for GGSWCiphertextPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GGSWCiphertextPreparedBuilder<D: Data, B: Backend> {
|
||||
data: Option<VmpPMat<D, B>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
dsize: Option<Dsize>,
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGSWCiphertextPrepared<D, B> {
|
||||
#[inline]
|
||||
pub fn builder() -> GGSWCiphertextPreparedBuilder<D, B> {
|
||||
GGSWCiphertextPreparedBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
dsize: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGSWCiphertextPreparedBuilder<Vec<u8>, B> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
B: VmpPMatAllocBytesImpl<B>,
|
||||
{
|
||||
debug_assert!(
|
||||
infos.size() as u32 > infos.dsize().0,
|
||||
"invalid ggsw: ceil(k/base2k): {} <= dsize: {}",
|
||||
infos.size(),
|
||||
infos.dsize()
|
||||
);
|
||||
|
||||
assert!(
|
||||
infos.dnum().0 * infos.dsize().0 <= infos.size() as u32,
|
||||
"invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {}",
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
infos.size(),
|
||||
);
|
||||
|
||||
self.data = Some(VmpPMat::alloc(
|
||||
infos.n().into(),
|
||||
infos.dnum().into(),
|
||||
(infos.rank() + 1).into(),
|
||||
(infos.rank() + 1).into(),
|
||||
infos.size(),
|
||||
));
|
||||
self.base2k = Some(infos.base2k());
|
||||
self.k = Some(infos.k());
|
||||
self.dsize = Some(infos.dsize());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGSWCiphertextPreparedBuilder<D, B> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: VmpPMat<D, B>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dsize(mut self, dsize: Dsize) -> Self {
|
||||
self.dsize = Some(dsize);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GGSWCiphertextPrepared<D, B>, BuildError> {
|
||||
let data: VmpPMat<D, B> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?;
|
||||
|
||||
if base2k == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if dsize == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k == 0_u32 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GGSWCiphertextPrepared {
|
||||
data,
|
||||
base2k,
|
||||
k,
|
||||
dsize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
Self::alloc_with(
|
||||
module,
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
infos.rank(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
{
|
||||
pub trait GGSWPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf,
|
||||
{
|
||||
fn alloc_ggsw_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
rank: Rank,
|
||||
) -> GGSWPrepared<Vec<u8>, B> {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
@@ -202,8 +75,8 @@ impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
Self {
|
||||
data: module.vmp_pmat_alloc(
|
||||
GGSWPrepared {
|
||||
data: self.vmp_pmat_alloc(
|
||||
dnum.into(),
|
||||
(rank + 1).into(),
|
||||
(rank + 1).into(),
|
||||
@@ -215,13 +88,12 @@ impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
fn alloc_ggsw_prepared_from_infos<A>(&self, infos: &A) -> GGSWPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGSWInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
{
|
||||
Self::alloc_bytes_with(
|
||||
module,
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.alloc_ggsw_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.dnum(),
|
||||
@@ -230,10 +102,7 @@ impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
{
|
||||
fn bytes_of_ggsw_prepared(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize {
|
||||
let size: usize = k.0.div_ceil(base2k.0) as usize;
|
||||
debug_assert!(
|
||||
size as u32 > dsize.0,
|
||||
@@ -248,65 +117,144 @@ impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> {
|
||||
dsize.0,
|
||||
);
|
||||
|
||||
module.vmp_pmat_alloc_bytes(dnum.into(), (rank + 1).into(), (rank + 1).into(), size)
|
||||
self.bytes_of_vmp_pmat(dnum.into(), (rank + 1).into(), (rank + 1).into(), size)
|
||||
}
|
||||
|
||||
fn bytes_of_ggsw_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.bytes_of_ggsw_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
infos.rank(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGSWCiphertextPrepared<D, B> {
|
||||
impl<B: Backend> GGSWPreparedAlloc<B> for Module<B> where Self: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf {}
|
||||
|
||||
impl<B: Backend> GGSWPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: GGSWPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_ggsw_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
|
||||
where
|
||||
M: GGSWPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_ggsw_prepared(base2k, k, dnum, dsize, rank)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: GGSWPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_ggsw_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize
|
||||
where
|
||||
M: GGSWPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_ggsw_prepared(base2k, k, dnum, dsize, rank)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGSWPrepared<D, B> {
|
||||
pub fn data(&self) -> &VmpPMat<D, B> {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGSWInfos> PrepareScratchSpace<B, A> for GGSWCiphertextPrepared<Vec<u8>, B>
|
||||
pub trait GGSWPrepare<B: Backend>
|
||||
where
|
||||
Module<B>: VmpPrepareTmpBytes,
|
||||
Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
module.vmp_prepare_tmp_bytes(
|
||||
fn ggsw_prepare_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
{
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.vmp_prepare_tmp_bytes(
|
||||
infos.dnum().into(),
|
||||
(infos.rank() + 1).into(),
|
||||
(infos.rank() + 1).into(),
|
||||
infos.size(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGSWCiphertext<DR>> for GGSWCiphertextPrepared<D, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<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.base2k = other.base2k;
|
||||
self.dsize = other.dsize;
|
||||
fn ggsw_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: GGSWPreparedToMut<B>,
|
||||
O: GGSWToRef,
|
||||
{
|
||||
let mut res: GGSWPrepared<&mut [u8], B> = res.to_mut();
|
||||
let other: GGSW<&[u8]> = other.to_ref();
|
||||
assert_eq!(res.n(), self.ring_degree());
|
||||
assert_eq!(other.n(), self.ring_degree());
|
||||
assert_eq!(res.k, other.k);
|
||||
assert_eq!(res.base2k, other.base2k);
|
||||
assert_eq!(res.dsize, other.dsize);
|
||||
self.vmp_prepare(&mut res.data, &other.data, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GGSWCiphertextPrepared<Vec<u8>, B>> for GGSWCiphertext<D>
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B> + VmpPrepare<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);
|
||||
ggsw_prepared.prepare(module, self, scratch);
|
||||
ggsw_prepared
|
||||
impl<B: Backend> GGSWPrepare<B> for Module<B> where Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B> {}
|
||||
|
||||
impl<B: Backend> GGSWPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGSWInfos,
|
||||
M: GGSWPrepare<B>,
|
||||
{
|
||||
module.ggsw_prepare_tmp_bytes(infos)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGSWCiphertextPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GGSWCiphertextPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGSWCiphertextPreparedToRef<B> for GGSWCiphertextPrepared<D, B> {
|
||||
fn to_ref(&self) -> GGSWCiphertextPrepared<&[u8], B> {
|
||||
GGSWCiphertextPrepared::builder()
|
||||
.base2k(self.base2k())
|
||||
.dsize(self.dsize())
|
||||
.k(self.k())
|
||||
.data(self.data.to_ref())
|
||||
.build()
|
||||
.unwrap()
|
||||
impl<D: DataMut, B: Backend> GGSWPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: GGSWToRef,
|
||||
M: GGSWPrepare<B>,
|
||||
{
|
||||
module.ggsw_prepare(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGSWPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GGSWPreparedToMut<B> for GGSWPrepared<D, B> {
|
||||
fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B> {
|
||||
GGSWPrepared {
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
dsize: self.dsize,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGSWPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GGSWPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGSWPreparedToRef<B> for GGSWPrepared<D, B> {
|
||||
fn to_ref(&self) -> GGSWPrepared<&[u8], B> {
|
||||
GGSWPrepared {
|
||||
base2k: self.base2k,
|
||||
k: self.k,
|
||||
dsize: self.dsize,
|
||||
data: self.data.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
use poulpy_hal::{
|
||||
api::{VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VecZnxDft, ZnxInfos},
|
||||
oep::VecZnxDftAllocBytesImpl,
|
||||
api::{VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, VecZnxDft, VecZnxDftToMut, VecZnxDftToRef, ZnxInfos},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
dist::Distribution,
|
||||
layouts::{
|
||||
Base2K, BuildError, Degree, GLWEInfos, GLWEPublicKey, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, GLWEInfos, GLWEPublicKey, GLWEPublicKeyToRef, GetDist, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -20,6 +18,16 @@ pub struct GLWEPublicKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) dist: Distribution,
|
||||
}
|
||||
|
||||
pub(crate) trait SetDist {
|
||||
fn set_dist(&mut self, dist: Distribution);
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> SetDist for GLWEPublicKeyPrepared<D, B> {
|
||||
fn set_dist(&mut self, dist: Distribution) {
|
||||
self.dist = dist
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GLWEPublicKeyPrepared<D, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
@@ -33,8 +41,8 @@ impl<D: Data, B: Backend> LWEInfos for GLWEPublicKeyPrepared<D, B> {
|
||||
self.data.size()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,164 +52,138 @@ impl<D: Data, B: Backend> GLWEInfos for GLWEPublicKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GLWEPublicKeyPreparedBuilder<D: Data, B: Backend> {
|
||||
data: Option<VecZnxDft<D, B>>,
|
||||
base2k: Option<Base2K>,
|
||||
k: Option<TorusPrecision>,
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEPublicKeyPrepared<D, B> {
|
||||
#[inline]
|
||||
pub fn builder() -> GLWEPublicKeyPreparedBuilder<D, B> {
|
||||
GLWEPublicKeyPreparedBuilder {
|
||||
data: None,
|
||||
base2k: None,
|
||||
k: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEPublicKeyPreparedBuilder<Vec<u8>, B> {
|
||||
#[inline]
|
||||
pub fn layout<A>(mut self, layout: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
B: VecZnxDftAllocBytesImpl<B>,
|
||||
{
|
||||
self.data = Some(VecZnxDft::alloc(
|
||||
layout.n().into(),
|
||||
(layout.rank() + 1).into(),
|
||||
layout.size(),
|
||||
));
|
||||
self.base2k = Some(layout.base2k());
|
||||
self.k = Some(layout.k());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEPublicKeyPreparedBuilder<D, B> {
|
||||
#[inline]
|
||||
pub fn data(mut self, data: VecZnxDft<D, B>) -> Self {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn base2k(mut self, base2k: Base2K) -> Self {
|
||||
self.base2k = Some(base2k);
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
pub fn k(mut self, k: TorusPrecision) -> Self {
|
||||
self.k = Some(k);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<GLWEPublicKeyPrepared<D, B>, BuildError> {
|
||||
let data: VecZnxDft<D, B> = self.data.ok_or(BuildError::MissingData)?;
|
||||
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
|
||||
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
|
||||
|
||||
if base2k == 0_u32 {
|
||||
return Err(BuildError::ZeroBase2K);
|
||||
}
|
||||
|
||||
if k == 0_u32 {
|
||||
return Err(BuildError::ZeroTorusPrecision);
|
||||
}
|
||||
|
||||
if data.n() == 0 {
|
||||
return Err(BuildError::ZeroDegree);
|
||||
}
|
||||
|
||||
if data.cols() == 0 {
|
||||
return Err(BuildError::ZeroCols);
|
||||
}
|
||||
|
||||
if data.size() == 0 {
|
||||
return Err(BuildError::ZeroLimbs);
|
||||
}
|
||||
|
||||
Ok(GLWEPublicKeyPrepared {
|
||||
data,
|
||||
pub trait GLWEPublicKeyPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GetRingDegree + VecZnxDftAlloc<B> + VecZnxDftBytesOf,
|
||||
{
|
||||
fn alloc_glwe_public_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKeyPrepared<Vec<u8>, B> {
|
||||
GLWEPublicKeyPrepared {
|
||||
data: self.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
|
||||
base2k,
|
||||
k,
|
||||
dist: Distribution::NONE,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_glwe_public_key_prepared_from_infos<A>(&self, infos: &A) -> GLWEPublicKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.alloc_glwe_public_key_prepared(infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_public_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
|
||||
self.bytes_of_vec_znx_dft((rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_public_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe_public_key_prepared(infos.base2k(), infos.k(), infos.rank())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEPublicKeyPreparedAlloc<B> for Module<B> where Self: VecZnxDftAlloc<B> + VecZnxDftBytesOf {}
|
||||
|
||||
impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
Module<B>: VecZnxDftAlloc<B>,
|
||||
M: GLWEPublicKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
|
||||
Self::alloc_with(module, infos.base2k(), infos.k(), infos.rank())
|
||||
module.alloc_glwe_public_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
|
||||
where
|
||||
Module<B>: VecZnxDftAlloc<B>,
|
||||
M: GLWEPublicKeyPreparedAlloc<B>,
|
||||
{
|
||||
Self {
|
||||
data: module.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
|
||||
base2k,
|
||||
k,
|
||||
dist: Distribution::NONE,
|
||||
}
|
||||
module.alloc_glwe_public_key_prepared(base2k, k, rank)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
Module<B>: VecZnxDftAllocBytes,
|
||||
M: GLWEPublicKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
|
||||
Self::alloc_bytes_with(module, infos.base2k(), infos.k(), infos.rank())
|
||||
module.bytes_of_glwe_public_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize
|
||||
where
|
||||
Module<B>: VecZnxDftAllocBytes,
|
||||
M: GLWEPublicKeyPreparedAlloc<B>,
|
||||
{
|
||||
module.vec_znx_dft_alloc_bytes((rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
|
||||
module.bytes_of_glwe_public_key_prepared(base2k, k, rank)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEPublicKeyPrepared<Vec<u8>, B>> for GLWEPublicKey<D>
|
||||
pub trait GLWEPublicKeyPrepare<B: Backend>
|
||||
where
|
||||
Module<B>: VecZnxDftAlloc<B> + VecZnxDftApply<B>,
|
||||
Self: GetRingDegree + VecZnxDftApply<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);
|
||||
pk_prepared.prepare(module, self, scratch);
|
||||
pk_prepared
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GLWEInfos> PrepareScratchSpace<B, A> for GLWEPublicKeyPrepared<Vec<u8>, B> {
|
||||
fn prepare_scratch_space(_module: &Module<B>, _infos: &A) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEPublicKey<DR>> for GLWEPublicKeyPrepared<DM, B>
|
||||
where
|
||||
Module<B>: VecZnxDftApply<B>,
|
||||
{
|
||||
fn prepare(&mut self, module: &Module<B>, other: &GLWEPublicKey<DR>, _scratch: &mut Scratch<B>) {
|
||||
#[cfg(debug_assertions)]
|
||||
fn prepare_glwe_public_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GLWEPublicKeyPreparedToMut<B> + SetDist,
|
||||
O: GLWEPublicKeyToRef + GetDist,
|
||||
{
|
||||
{
|
||||
assert_eq!(self.n(), other.n());
|
||||
assert_eq!(self.size(), other.size());
|
||||
let mut res: GLWEPublicKeyPrepared<&mut [u8], B> = res.to_mut();
|
||||
let other: GLWEPublicKey<&[u8]> = other.to_ref();
|
||||
|
||||
assert_eq!(res.n(), self.ring_degree());
|
||||
assert_eq!(other.n(), self.ring_degree());
|
||||
assert_eq!(res.size(), other.size());
|
||||
assert_eq!(res.k(), other.k());
|
||||
assert_eq!(res.base2k(), other.base2k());
|
||||
|
||||
for i in 0..(res.rank() + 1).into() {
|
||||
self.vec_znx_dft_apply(1, 0, &mut res.data, i, &other.data, i);
|
||||
}
|
||||
}
|
||||
|
||||
(0..(self.rank() + 1).into()).for_each(|i| {
|
||||
module.vec_znx_dft_apply(1, 0, &mut self.data, i, &other.data, i);
|
||||
});
|
||||
self.k = other.k();
|
||||
self.base2k = other.base2k();
|
||||
self.dist = other.dist;
|
||||
res.set_dist(other.get_dist());
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEPublicKeyPrepare<B> for Module<B> where Self: GetRingDegree + VecZnxDftApply<B> {}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWEPublicKeyPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GLWEPublicKeyToRef + GetDist,
|
||||
M: GLWEPublicKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_glwe_public_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEPublicKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWEPublicKeyPreparedToMut<B> for GLWEPublicKeyPrepared<D, B> {
|
||||
fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B> {
|
||||
GLWEPublicKeyPrepared {
|
||||
dist: self.dist,
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEPublicKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWEPublicKeyPreparedToRef<B> for GLWEPublicKeyPrepared<D, B> {
|
||||
fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B> {
|
||||
GLWEPublicKeyPrepared {
|
||||
data: self.data.to_ref(),
|
||||
dist: self.dist,
|
||||
k: self.k,
|
||||
base2k: self.base2k,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use poulpy_hal::{
|
||||
api::{SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, SvpPPol, ZnxInfos},
|
||||
api::{SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, SvpPPol, SvpPPolToMut, SvpPPolToRef, ZnxInfos},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
dist::Distribution,
|
||||
layouts::{
|
||||
Base2K, Degree, GLWEInfos, GLWESecret, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, GLWEInfos, GLWESecret, GLWESecretToRef, GetDist, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
prepared::SetDist,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -16,6 +16,12 @@ pub struct GLWESecretPrepared<D: Data, B: Backend> {
|
||||
pub(crate) dist: Distribution,
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> SetDist for GLWESecretPrepared<D, B> {
|
||||
fn set_dist(&mut self, dist: Distribution) {
|
||||
self.dist = dist
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GLWESecretPrepared<D, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
Base2K(0)
|
||||
@@ -25,8 +31,8 @@ impl<D: Data, B: Backend> LWEInfos for GLWESecretPrepared<D, B> {
|
||||
TorusPrecision(0)
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
@@ -38,46 +44,74 @@ impl<D: Data, B: Backend> GLWEInfos for GLWESecretPrepared<D, B> {
|
||||
Rank(self.data.cols() as u32)
|
||||
}
|
||||
}
|
||||
impl<B: Backend> GLWESecretPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
Module<B>: SvpPPolAlloc<B>,
|
||||
{
|
||||
assert_eq!(module.n() as u32, infos.n());
|
||||
Self::alloc_with(module, infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, rank: Rank) -> Self
|
||||
where
|
||||
Module<B>: SvpPPolAlloc<B>,
|
||||
{
|
||||
Self {
|
||||
data: module.svp_ppol_alloc(rank.into()),
|
||||
pub trait GLWESecretPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GetRingDegree + SvpPPolBytesOf + SvpPPolAlloc<B>,
|
||||
{
|
||||
fn alloc_glwe_secret_prepared(&self, rank: Rank) -> GLWESecretPrepared<Vec<u8>, B> {
|
||||
GLWESecretPrepared {
|
||||
data: self.svp_ppol_alloc(rank.into()),
|
||||
dist: Distribution::NONE,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
fn alloc_glwe_secret_prepared_from_infos<A>(&self, infos: &A) -> GLWESecretPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GLWEInfos,
|
||||
Module<B>: SvpPPolAllocBytes,
|
||||
{
|
||||
assert_eq!(module.n() as u32, infos.n());
|
||||
Self::alloc_bytes_with(module, infos.rank())
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.alloc_glwe_secret_prepared(infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, rank: Rank) -> usize
|
||||
fn bytes_of_glwe_secret(&self, rank: Rank) -> usize {
|
||||
self.bytes_of_svp_ppol(rank.into())
|
||||
}
|
||||
fn bytes_of_glwe_secret_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
Module<B>: SvpPPolAllocBytes,
|
||||
A: GLWEInfos,
|
||||
{
|
||||
module.svp_ppol_alloc_bytes(rank.into())
|
||||
assert_eq!(self.ring_degree(), infos.n());
|
||||
self.bytes_of_glwe_secret(infos.rank())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWESecretPreparedAlloc<B> for Module<B> where Self: GetRingDegree + SvpPPolBytesOf + SvpPPolAlloc<B> {}
|
||||
|
||||
impl<B: Backend> GLWESecretPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWESecretPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_glwe_secret_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, rank: Rank) -> Self
|
||||
where
|
||||
M: GLWESecretPreparedAlloc<B>,
|
||||
{
|
||||
module.alloc_glwe_secret_prepared(rank)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
M: GLWESecretPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_glwe_secret_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, rank: Rank) -> usize
|
||||
where
|
||||
M: GLWESecretPreparedAlloc<B>,
|
||||
{
|
||||
module.bytes_of_glwe_secret(rank)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWESecretPrepared<D, B> {
|
||||
pub fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
pub fn n(&self) -> RingDegree {
|
||||
RingDegree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
pub fn rank(&self) -> Rank {
|
||||
@@ -85,31 +119,62 @@ impl<D: Data, B: Backend> GLWESecretPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GLWEInfos> PrepareScratchSpace<B, A> for GLWESecretPrepared<Vec<u8>, B> {
|
||||
fn prepare_scratch_space(_module: &Module<B>, _infos: &A) -> usize {
|
||||
0
|
||||
pub trait GLWESecretPrepare<B: Backend>
|
||||
where
|
||||
Self: SvpPrepare<B>,
|
||||
{
|
||||
fn prepare_glwe_secret<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GLWESecretPreparedToMut<B> + SetDist,
|
||||
O: GLWESecretToRef + GetDist,
|
||||
{
|
||||
{
|
||||
let mut res: GLWESecretPrepared<&mut [u8], _> = res.to_mut();
|
||||
let other: GLWESecret<&[u8]> = other.to_ref();
|
||||
|
||||
for i in 0..res.rank().into() {
|
||||
self.svp_prepare(&mut res.data, i, &other.data, i);
|
||||
}
|
||||
}
|
||||
|
||||
res.set_dist(other.get_dist());
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWESecretPrepared<Vec<u8>, B>> for GLWESecret<D>
|
||||
where
|
||||
Module<B>: SvpPrepare<B> + SvpPPolAlloc<B>,
|
||||
{
|
||||
fn prepare_alloc(&self, module: &Module<B>, _scratch: &mut Scratch<B>) -> GLWESecretPrepared<Vec<u8>, B> {
|
||||
let mut sk_dft: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, self);
|
||||
sk_dft.prepare(module, self, _scratch);
|
||||
sk_dft
|
||||
impl<B: Backend> GLWESecretPrepare<B> for Module<B> where Self: SvpPrepare<B> {}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWESecretPrepared<D, B> {
|
||||
pub fn prepare<M, O>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
M: GLWESecretPrepare<B>,
|
||||
O: GLWESecretToRef + GetDist,
|
||||
{
|
||||
module.prepare_glwe_secret(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
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 Scratch<B>) {
|
||||
(0..self.rank().into()).for_each(|i| {
|
||||
module.svp_prepare(&mut self.data, i, &other.data, i);
|
||||
});
|
||||
self.dist = other.dist
|
||||
pub trait GLWESecretPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GLWESecretPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWESecretPreparedToRef<B> for GLWESecretPrepared<D, B> {
|
||||
fn to_ref(&self) -> GLWESecretPrepared<&[u8], B> {
|
||||
GLWESecretPrepared {
|
||||
data: self.data.to_ref(),
|
||||
dist: self.dist,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESecretPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> GLWESecretPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWESecretPreparedToMut<B> for GLWESecretPrepared<D, B> {
|
||||
fn to_mut(&mut self) -> GLWESecretPrepared<&mut [u8], B> {
|
||||
GLWESecretPrepared {
|
||||
dist: self.dist,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWEToLWEKey, LWEInfos, Rank, TorusPrecision,
|
||||
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWEToLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision,
|
||||
prepared::{
|
||||
GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut,
|
||||
GLWESwitchingKeyPreparedToRef,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GLWEToLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>);
|
||||
pub struct GLWEToLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -20,7 +20,7 @@ impl<D: Data, B: Backend> LWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
@@ -53,91 +53,156 @@ impl<D: Data, B: Backend> GGLWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
fn alloc_glwe_to_lwe_switching_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_in: Rank,
|
||||
dnum: Dnum,
|
||||
) -> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
GLWEToLWESwitchingKeyPrepared(self.alloc_glwe_switching_key_prepared(base2k, k, rank_in, Rank(1), dnum, Dsize(1)))
|
||||
}
|
||||
fn alloc_glwe_to_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
self.alloc_glwe_to_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_to_lwe_switching_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_switching_key_prepared(base2k, k, rank_in, Rank(1), dnum, Dsize(1))
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_to_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
self.bytes_of_glwe_to_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GLWESwitchingKeyPreparedAlloc<B> {}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: GLWEToLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
Self(GGLWESwitchingKeyPrepared::alloc(module, infos))
|
||||
module.alloc_glwe_to_lwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: GLWEToLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
Self(GGLWESwitchingKeyPrepared::alloc_with(
|
||||
module,
|
||||
base2k,
|
||||
k,
|
||||
rank_in,
|
||||
Rank(1),
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
module.alloc_glwe_to_lwe_switching_key_prepared(base2k, k, rank_in, dnum)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: GLWEToLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
);
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
|
||||
module.bytes_of_glwe_to_lwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: GLWEToLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rank_in, Rank(1), dnum, Dsize(1))
|
||||
module.bytes_of_glwe_to_lwe_switching_key_prepared(base2k, k, rank_in, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
pub trait GLWEToLWESwitchingKeyPrepare<B: Backend>
|
||||
where
|
||||
GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>,
|
||||
Self: GLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos)
|
||||
fn prepare_glwe_to_lwe_switching_key_tmp_bytes<A>(&self, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.prepare_glwe_switching_key_tmp_bytes(infos);
|
||||
}
|
||||
|
||||
fn prepare_glwe_to_lwe_switching_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: GLWEToLWESwitchingKeyPreparedToMut<B>,
|
||||
O: GLWEToLWESwitchingKeyToRef,
|
||||
{
|
||||
self.prepare_glwe_switching(&mut res.to_mut().0, &other.to_ref().0, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>> for GLWEToLWEKey<D>
|
||||
where
|
||||
Module<B>: VmpPrepare<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);
|
||||
ksk_prepared.prepare(module, self, scratch);
|
||||
ksk_prepared
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_glwe_to_lwe_switching_key_tmp_bytes(infos);
|
||||
}
|
||||
}
|
||||
|
||||
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEToLWEKey<DR>> for GLWEToLWESwitchingKeyPrepared<DM, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<B>,
|
||||
{
|
||||
fn prepare(&mut self, module: &Module<B>, other: &GLWEToLWEKey<DR>, scratch: &mut Scratch<B>) {
|
||||
self.0.prepare(module, &other.0, scratch);
|
||||
impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: GLWEToLWESwitchingKeyToRef,
|
||||
M: GLWEToLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_glwe_to_lwe_switching_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GLWEToLWESwitchingKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWEToLWESwitchingKeyPreparedToRef<B> for GLWEToLWESwitchingKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>,
|
||||
{
|
||||
fn to_ref(&self) -> GLWEToLWESwitchingKeyPrepared<&[u8], B> {
|
||||
GLWEToLWESwitchingKeyPrepared(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> GLWEToLWESwitchingKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyPreparedToMut<B> for GLWEToLWESwitchingKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWEToLWESwitchingKeyPrepared<&mut [u8], B> {
|
||||
GLWEToLWESwitchingKeyPrepared(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, TorusPrecision,
|
||||
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKeyToRef, Rank, RingDegree, TorusPrecision,
|
||||
prepared::{
|
||||
GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut,
|
||||
GLWESwitchingKeyPreparedToRef,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct LWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>);
|
||||
pub struct LWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for LWESwitchingKeyPrepared<D, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -20,7 +20,7 @@ impl<D: Data, B: Backend> LWEInfos for LWESwitchingKeyPrepared<D, B> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
@@ -52,101 +52,165 @@ impl<D: Data, B: Backend> GGLWEInfos for LWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
fn alloc_lwe_switching_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
dnum: Dnum,
|
||||
) -> LWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
LWESwitchingKeyPrepared(self.alloc_glwe_switching_key_prepared(base2k, k, Rank(1), Rank(1), dnum, Dsize(1)))
|
||||
}
|
||||
|
||||
fn alloc_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> LWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
self.alloc_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.dnum())
|
||||
}
|
||||
|
||||
fn bytes_of_lwe_switching_key_prepared(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_switching_key_prepared(base2k, k, Rank(1), Rank(1), dnum, Dsize(1))
|
||||
}
|
||||
|
||||
fn bytes_of_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
self.bytes_of_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.dnum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GLWESwitchingKeyPreparedAlloc<B> {}
|
||||
|
||||
impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: LWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
Self(GGLWESwitchingKeyPrepared::alloc(module, infos))
|
||||
module.alloc_lwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: LWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
Self(GGLWESwitchingKeyPrepared::alloc_with(
|
||||
module,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
Rank(1),
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
module.alloc_lwe_switching_key_prepared(base2k, k, dnum)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: LWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for LWESwitchingKey"
|
||||
);
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
|
||||
module.bytes_of_lwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: LWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), Rank(1), dnum, Dsize(1))
|
||||
module.bytes_of_lwe_switching_key_prepared(base2k, k, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for LWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
pub trait LWESwitchingKeyPrepare<B: Backend>
|
||||
where
|
||||
GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>,
|
||||
Self: GLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos)
|
||||
fn prepare_lwe_switching_key_tmp_bytes<A>(&self, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.prepare_glwe_switching_key_tmp_bytes(infos);
|
||||
}
|
||||
fn prepare_lwe_switching_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: LWESwitchingKeyPreparedToMut<B>,
|
||||
O: LWESwitchingKeyToRef,
|
||||
{
|
||||
self.prepare_glwe_switching(&mut res.to_mut().0, &other.to_ref().0, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, LWESwitchingKeyPrepared<Vec<u8>, B>> for LWESwitchingKey<D>
|
||||
where
|
||||
Module<B>: VmpPrepare<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);
|
||||
ksk_prepared.prepare(module, self, scratch);
|
||||
ksk_prepared
|
||||
impl<B: Backend> LWESwitchingKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {}
|
||||
|
||||
impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_lwe_switching_key_tmp_bytes(infos);
|
||||
}
|
||||
}
|
||||
|
||||
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWESwitchingKey<DR>> for LWESwitchingKeyPrepared<DM, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<B>,
|
||||
{
|
||||
fn prepare(&mut self, module: &Module<B>, other: &LWESwitchingKey<DR>, scratch: &mut Scratch<B>) {
|
||||
self.0.prepare(module, &other.0, scratch);
|
||||
impl<D: DataMut, B: Backend> LWESwitchingKeyPrepared<D, B> {
|
||||
fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: LWESwitchingKeyToRef,
|
||||
M: LWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_lwe_switching_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> LWESwitchingKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> LWESwitchingKeyPreparedToRef<B> for LWESwitchingKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>,
|
||||
{
|
||||
fn to_ref(&self) -> LWESwitchingKeyPrepared<&[u8], B> {
|
||||
LWESwitchingKeyPrepared(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWESwitchingKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> LWESwitchingKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> LWESwitchingKeyPreparedToMut<B> for LWESwitchingKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>,
|
||||
{
|
||||
fn to_mut(&mut self) -> LWESwitchingKeyPrepared<&mut [u8], B> {
|
||||
LWESwitchingKeyPrepared(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use poulpy_hal::{
|
||||
api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
|
||||
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
|
||||
};
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, TorusPrecision,
|
||||
prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace},
|
||||
Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKeyToRef, Rank, RingDegree, TorusPrecision,
|
||||
prepared::{
|
||||
GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut,
|
||||
GLWESwitchingKeyPreparedToRef,
|
||||
},
|
||||
};
|
||||
|
||||
/// A special [GLWESwitchingKey] required to for the conversion from [LWECiphertext] to [GLWECiphertext].
|
||||
/// A special [GLWESwitchingKey] required to for the conversion from [LWE] to [GLWE].
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>);
|
||||
pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
@@ -21,7 +21,7 @@ impl<D: Data, B: Backend> LWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
fn n(&self) -> RingDegree {
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
@@ -54,91 +54,162 @@ impl<D: Data, B: Backend> GGLWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyPreparedAlloc<B: Backend>
|
||||
where
|
||||
Self: GLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
fn alloc_lwe_to_glwe_switching_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
) -> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
LWEToGLWESwitchingKeyPrepared(self.alloc_glwe_switching_key_prepared(base2k, k, Rank(1), rank_out, dnum, Dsize(1)))
|
||||
}
|
||||
fn alloc_lwe_to_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
self.alloc_lwe_to_glwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
}
|
||||
|
||||
fn bytes_of_lwe_to_glwe_switching_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank_out: Rank,
|
||||
dnum: Dnum,
|
||||
) -> usize {
|
||||
self.bytes_of_glwe_switching_key_prepared(base2k, k, Rank(1), rank_out, dnum, Dsize(1))
|
||||
}
|
||||
|
||||
fn bytes_of_lwe_to_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
self.bytes_of_lwe_to_glwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GLWESwitchingKeyPreparedAlloc<B> {}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: LWEToGLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
Self(GGLWESwitchingKeyPrepared::alloc(module, infos))
|
||||
module.alloc_lwe_to_glwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
Module<B>: VmpPMatAlloc<B>,
|
||||
M: LWEToGLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
Self(GGLWESwitchingKeyPrepared::alloc_with(
|
||||
module,
|
||||
base2k,
|
||||
k,
|
||||
Rank(1),
|
||||
rank_out,
|
||||
dnum,
|
||||
Dsize(1),
|
||||
))
|
||||
module.alloc_lwe_to_glwe_switching_key_prepared(base2k, k, rank_out, dnum)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: LWEToGLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
);
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes(module, infos)
|
||||
module.bytes_of_lwe_to_glwe_switching_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> usize
|
||||
where
|
||||
Module<B>: VmpPMatAllocBytes,
|
||||
M: LWEToGLWESwitchingKeyPreparedAlloc<B>,
|
||||
{
|
||||
GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank_out, dnum, Dsize(1))
|
||||
module.bytes_of_lwe_to_glwe_switching_key_prepared(base2k, k, rank_out, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for LWEToGLWESwitchingKeyPrepared<Vec<u8>, B>
|
||||
pub trait LWEToGLWESwitchingKeyPrepare<B: Backend>
|
||||
where
|
||||
GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>,
|
||||
Self: GLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
|
||||
GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos)
|
||||
fn prepare_lwe_to_glwe_switching_key_tmp_bytes<A>(&self, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.prepare_glwe_switching_key_tmp_bytes(infos);
|
||||
}
|
||||
|
||||
fn prepare_lwe_to_glwe_switching_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: LWEToGLWESwitchingKeyPreparedToMut<B>,
|
||||
O: LWEToGLWESwitchingKeyToRef,
|
||||
{
|
||||
self.prepare_glwe_switching(&mut res.to_mut().0, &other.to_ref().0, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> PrepareAlloc<B, LWEToGLWESwitchingKeyPrepared<Vec<u8>, B>> for LWEToGLWESwitchingKey<D>
|
||||
where
|
||||
Module<B>: VmpPrepare<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);
|
||||
ksk_prepared.prepare(module, self, scratch);
|
||||
ksk_prepared
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_lwe_to_glwe_switching_key_tmp_bytes(infos);
|
||||
}
|
||||
}
|
||||
|
||||
impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWEToGLWESwitchingKey<DR>> for LWEToGLWESwitchingKeyPrepared<DM, B>
|
||||
where
|
||||
Module<B>: VmpPrepare<B>,
|
||||
{
|
||||
fn prepare(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DR>, scratch: &mut Scratch<B>) {
|
||||
self.0.prepare(module, &other.0, scratch);
|
||||
impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: LWEToGLWESwitchingKeyToRef,
|
||||
M: LWEToGLWESwitchingKeyPrepare<B>,
|
||||
{
|
||||
module.prepare_lwe_to_glwe_switching_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> LWEToGLWESwitchingKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> LWEToGLWESwitchingKeyPreparedToRef<B> for LWEToGLWESwitchingKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>,
|
||||
{
|
||||
fn to_ref(&self) -> LWEToGLWESwitchingKeyPrepared<&[u8], B> {
|
||||
LWEToGLWESwitchingKeyPrepared(self.0.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> LWEToGLWESwitchingKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyPreparedToMut<B> for LWEToGLWESwitchingKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>,
|
||||
{
|
||||
fn to_mut(&mut self) -> LWEToGLWESwitchingKeyPrepared<&mut [u8], B> {
|
||||
LWEToGLWESwitchingKeyPrepared(self.0.to_mut())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,3 @@ pub use glwe_sk::*;
|
||||
pub use glwe_to_lwe_ksk::*;
|
||||
pub use lwe_ksk::*;
|
||||
pub use lwe_to_glwe_ksk::*;
|
||||
use poulpy_hal::layouts::{Backend, Module, Scratch};
|
||||
|
||||
pub trait PrepareScratchSpace<B: Backend, T> {
|
||||
fn prepare_scratch_space(module: &Module<B>, infos: &T) -> usize;
|
||||
}
|
||||
|
||||
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>);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user