mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 13:16:44 +01:00
Distinguish between gglwe_to_ggsw key and tensor_key + update key repreentation
This commit is contained in:
237
poulpy-core/src/layouts/compressed/gglwe_to_ggsw_key.rs
Normal file
237
poulpy-core/src/layouts/compressed/gglwe_to_ggsw_key.rs
Normal file
@@ -0,0 +1,237 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWECompressed, GGLWECompressedToMut, GGLWECompressedToRef, GGLWEDecompress, GGLWEInfos,
|
||||
GGLWEToGGSWKey, GGLWEToGGSWKeyToMut, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWEToGGSWKeyCompressed<D: Data> {
|
||||
pub(crate) keys: Vec<GGLWECompressed<D>>,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWEToGGSWKeyCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GGLWEToGGSWKeyCompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWEToGGSWKeyCompressed<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
|
||||
fn rank_out(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
}
|
||||
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.keys[0].dsize()
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.keys[0].dnum()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWEToGGSWKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWEToGGSWKeyCompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.for_each(|key: &mut GGLWECompressed<D>| key.fill_uniform(log_bound, source))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWEToGGSWKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "(GGLWEToGGSWKeyCompressed)",)?;
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
write!(f, "{i}: {key}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEToGGSWKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEToGGSWKeyCompressed"
|
||||
);
|
||||
Self::alloc(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
GGLWEToGGSWKeyCompressed {
|
||||
keys: (0..rank.as_usize())
|
||||
.map(|_| GGLWECompressed::alloc(n, base2k, k, rank, rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A>(infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEToGGSWKeyCompressed"
|
||||
);
|
||||
Self::bytes_of(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
rank.as_usize() * GGLWECompressed::bytes_of(n, base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToGGSWKeyCompressed<D> {
|
||||
// Returns a mutable reference to GGLWE_{s}([s[i]*s[0], s[i]*s[1], ..., s[i]*s[rank]])
|
||||
pub fn at_mut(&mut self, i: usize) -> &mut GGLWECompressed<D> {
|
||||
assert!((i as u32) < self.rank());
|
||||
&mut self.keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEToGGSWKeyCompressed<D> {
|
||||
// Returns a reference to GGLWE_{s}(s[i] * s[j])
|
||||
pub fn at(&self, i: usize) -> &GGLWECompressed<D> {
|
||||
assert!((i as u32) < self.rank());
|
||||
&self.keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWEToGGSWKeyCompressed<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 {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("self.keys.len()={} != read len={}", self.keys.len(), len),
|
||||
));
|
||||
}
|
||||
for key in &mut self.keys {
|
||||
key.read_from(reader)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWEToGGSWKeyCompressed<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 {
|
||||
key.write_to(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyDecompress
|
||||
where
|
||||
Self: GGLWEDecompress,
|
||||
{
|
||||
fn decompress_gglwe_to_ggsw_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GGLWEToGGSWKeyToMut,
|
||||
O: GGLWEToGGSWKeyCompressedToRef,
|
||||
{
|
||||
let res: &mut GGLWEToGGSWKey<&mut [u8]> = &mut res.to_mut();
|
||||
let other: &GGLWEToGGSWKeyCompressed<&[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.decompress_gglwe(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToGGSWKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
M: GGLWEToGGSWKeyDecompress,
|
||||
O: GGLWEToGGSWKeyCompressedToRef,
|
||||
{
|
||||
module.decompress_gglwe_to_ggsw_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyCompressedToRef {
|
||||
fn to_ref(&self) -> GGLWEToGGSWKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEToGGSWKeyCompressedToRef for GGLWEToGGSWKeyCompressed<D>
|
||||
where
|
||||
GGLWECompressed<D>: GGLWECompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GGLWEToGGSWKeyCompressed<&[u8]> {
|
||||
GGLWEToGGSWKeyCompressed {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> GGLWEToGGSWKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToGGSWKeyCompressedToMut for GGLWEToGGSWKeyCompressed<D>
|
||||
where
|
||||
GGLWECompressed<D>: GGLWECompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GGLWEToGGSWKeyCompressed<&mut [u8]> {
|
||||
GGLWEToGGSWKeyCompressed {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,31 +4,34 @@ use poulpy_hal::{
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWECompressed, GGLWECompressedToMut, GGLWECompressedToRef, GGLWEDecompress, GGLWEInfos,
|
||||
GLWEInfos, GLWETensorKey, GLWETensorKeyToMut, LWEInfos, Rank, TorusPrecision,
|
||||
Base2K, Degree, Dnum, Dsize, GGLWECompressed, GGLWECompressedSeedMut, GGLWECompressedToMut, GGLWECompressedToRef,
|
||||
GGLWEDecompress, GGLWEInfos, GGLWEToMut, GLWEInfos, GLWETensorKey, LWEInfos, Rank, TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GLWETensorKeyCompressed<D: Data> {
|
||||
pub(crate) keys: Vec<GGLWECompressed<D>>,
|
||||
pub struct GLWETensorKeyCompressed<D: Data>(pub(crate) GGLWECompressed<D>);
|
||||
|
||||
impl<D: DataMut> GGLWECompressedSeedMut for GLWETensorKeyCompressed<D> {
|
||||
fn seed_mut(&mut self) -> &mut Vec<[u8; 32]> {
|
||||
&mut self.0.seed
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GLWETensorKeyCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
self.0.base2k()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
self.0.k()
|
||||
}
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
self.0.size()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for GLWETensorKeyCompressed<D> {
|
||||
@@ -43,15 +46,15 @@ impl<D: Data> GGLWEInfos for GLWETensorKeyCompressed<D> {
|
||||
}
|
||||
|
||||
fn rank_out(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
self.0.rank_out()
|
||||
}
|
||||
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.keys[0].dsize()
|
||||
self.0.dsize()
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.keys[0].dnum()
|
||||
self.0.dnum()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,18 +66,14 @@ impl<D: DataRef> fmt::Debug for GLWETensorKeyCompressed<D> {
|
||||
|
||||
impl<D: DataMut> FillUniform for GLWETensorKeyCompressed<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.for_each(|key: &mut GGLWECompressed<D>| key.fill_uniform(log_bound, source))
|
||||
self.0.fill_uniform(log_bound, source);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GLWETensorKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "(GLWETensorKeyCompressed)",)?;
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
write!(f, "{i}: {key}")?;
|
||||
}
|
||||
write!(f, "{}", self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -96,11 +95,15 @@ impl GLWETensorKeyCompressed<Vec<u8>> {
|
||||
|
||||
pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
|
||||
GLWETensorKeyCompressed {
|
||||
keys: (0..pairs)
|
||||
.map(|_| GGLWECompressed::alloc(n, base2k, k, Rank(1), rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
GLWETensorKeyCompressed(GGLWECompressed::alloc(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
Rank(pairs),
|
||||
rank,
|
||||
dnum,
|
||||
dsize,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A>(infos: &A) -> usize
|
||||
@@ -118,88 +121,35 @@ impl GLWETensorKeyCompressed<Vec<u8>> {
|
||||
}
|
||||
|
||||
pub fn bytes_of(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 * GGLWECompressed::bytes_of(n, base2k, k, Rank(1), dnum, dsize)
|
||||
let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
|
||||
GGLWECompressed::bytes_of(n, base2k, k, Rank(pairs), dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWETensorKeyCompressed<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 {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("self.keys.len()={} != read len={}", self.keys.len(), len),
|
||||
));
|
||||
}
|
||||
for key in &mut self.keys {
|
||||
key.read_from(reader)?;
|
||||
}
|
||||
self.0.read_from(reader)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GLWETensorKeyCompressed<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 {
|
||||
key.write_to(writer)?;
|
||||
}
|
||||
self.0.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyCompressedAtRef<D: DataRef> {
|
||||
fn at(&self, i: usize, j: usize) -> &GGLWECompressed<D>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWETensorKeyCompressedAtRef<D> for GLWETensorKeyCompressed<D> {
|
||||
fn at(&self, mut i: usize, mut j: usize) -> &GGLWECompressed<D> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank_out().into();
|
||||
&self.keys[i * rank + j - (i * (i + 1) / 2)]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyCompressedAtMut<D: DataMut> {
|
||||
fn at_mut(&mut self, i: usize, j: usize) -> &mut GGLWECompressed<D>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWETensorKeyCompressedAtMut<D> for GLWETensorKeyCompressed<D> {
|
||||
fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWECompressed<D> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank_out().into();
|
||||
&mut self.keys[i * rank + j - (i * (i + 1) / 2)]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyDecompress
|
||||
where
|
||||
Self: GGLWEDecompress,
|
||||
{
|
||||
fn decompress_tensor_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GLWETensorKeyToMut,
|
||||
O: GLWETensorKeyCompressedToRef,
|
||||
R: GGLWEToMut,
|
||||
O: GGLWECompressedToRef,
|
||||
{
|
||||
let res: &mut GLWETensorKey<&mut [u8]> = &mut res.to_mut();
|
||||
let other: &GLWETensorKeyCompressed<&[u8]> = &other.to_ref();
|
||||
|
||||
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_gglwe(a, b);
|
||||
}
|
||||
self.decompress_gglwe(res, other);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,39 +158,27 @@ impl<B: Backend> GLWETensorKeyDecompress for Module<B> where Self: GGLWEDecompre
|
||||
impl<D: DataMut> GLWETensorKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GLWETensorKeyCompressedToRef,
|
||||
O: GGLWECompressedToRef,
|
||||
M: GLWETensorKeyDecompress,
|
||||
{
|
||||
module.decompress_tensor_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyCompressedToMut {
|
||||
fn to_mut(&mut self) -> GLWETensorKeyCompressed<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWETensorKeyCompressedToMut for GLWETensorKeyCompressed<D>
|
||||
impl<D: DataMut> GGLWECompressedToMut for GLWETensorKeyCompressed<D>
|
||||
where
|
||||
GGLWECompressed<D>: GGLWECompressedToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWETensorKeyCompressed<&mut [u8]> {
|
||||
GLWETensorKeyCompressed {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
fn to_mut(&mut self) -> GGLWECompressed<&mut [u8]> {
|
||||
self.0.to_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyCompressedToRef {
|
||||
fn to_ref(&self) -> GLWETensorKeyCompressed<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWETensorKeyCompressedToRef for GLWETensorKeyCompressed<D>
|
||||
impl<D: DataRef> GGLWECompressedToRef for GLWETensorKeyCompressed<D>
|
||||
where
|
||||
GGLWECompressed<D>: GGLWECompressedToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GLWETensorKeyCompressed<&[u8]> {
|
||||
GLWETensorKeyCompressed {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
fn to_ref(&self) -> GGLWECompressed<&[u8]> {
|
||||
self.0.to_ref()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use poulpy_hal::{
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWECompressed, GGLWECompressedToMut, GGLWECompressedToRef, GGLWEInfos, GGLWEToMut, GLWEInfos,
|
||||
GLWESwitchingKeyDegrees, GLWESwitchingKeyDegreesMut, GLWEToLWESwitchingKey, LWEInfos, Rank, TorusPrecision,
|
||||
GLWESwitchingKeyDegrees, GLWESwitchingKeyDegreesMut, GLWEToLWEKey, LWEInfos, Rank, TorusPrecision,
|
||||
compressed::{GLWESwitchingKeyCompressed, GLWESwitchingKeyDecompress},
|
||||
};
|
||||
|
||||
@@ -147,7 +147,7 @@ pub trait GLWEToLWESwitchingKeyDecompress
|
||||
where
|
||||
Self: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
fn decompress_glwe_to_lwe_switching_key<R, O>(&self, res: &mut R, other: &O)
|
||||
fn decompress_glwe_to_lwe_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GGLWEToMut + GLWESwitchingKeyDegreesMut,
|
||||
O: GGLWECompressedToRef + GLWESwitchingKeyDegrees,
|
||||
@@ -158,13 +158,13 @@ where
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
|
||||
|
||||
impl<D: DataMut> GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataMut> GLWEToLWEKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GGLWECompressedToRef + GLWESwitchingKeyDegrees,
|
||||
M: GLWEToLWESwitchingKeyDecompress,
|
||||
{
|
||||
module.decompress_glwe_to_lwe_switching_key(self, other);
|
||||
module.decompress_glwe_to_lwe_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@ use poulpy_hal::{
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWECompressed, GGLWECompressedToMut, GGLWECompressedToRef, GGLWEInfos, GGLWEToMut, GLWEInfos,
|
||||
GLWESwitchingKeyDegrees, GLWESwitchingKeyDegreesMut, LWEInfos, LWEToGLWESwitchingKey, Rank, TorusPrecision,
|
||||
GLWESwitchingKeyDegrees, GLWESwitchingKeyDegreesMut, LWEInfos, LWEToGLWEKey, Rank, TorusPrecision,
|
||||
compressed::{GLWESwitchingKeyCompressed, GLWESwitchingKeyDecompress},
|
||||
};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>);
|
||||
pub struct LWEToGLWEKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: Data> LWEInfos for LWEToGLWEKeyCompressed<D> {
|
||||
fn n(&self) -> Degree {
|
||||
self.0.n()
|
||||
}
|
||||
@@ -29,13 +29,13 @@ impl<D: Data> LWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
self.0.size()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GLWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: Data> GLWEInfos for LWEToGLWEKeyCompressed<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: Data> GGLWEInfos for LWEToGLWEKeyCompressed<D> {
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.0.dsize()
|
||||
}
|
||||
@@ -53,37 +53,37 @@ impl<D: Data> GGLWEInfos for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Debug for LWEToGLWEKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataMut> FillUniform for LWEToGLWEKeyCompressed<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 LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataRef> fmt::Display for LWEToGLWEKeyCompressed<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(LWEToGLWESwitchingKeyCompressed) {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataMut> ReaderFrom for LWEToGLWEKeyCompressed<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 LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataRef> WriterTo for LWEToGLWEKeyCompressed<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
self.0.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
impl LWEToGLWEKeyCompressed<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
@@ -108,7 +108,7 @@ impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
}
|
||||
|
||||
pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self {
|
||||
LWEToGLWESwitchingKeyCompressed(GLWESwitchingKeyCompressed::alloc(
|
||||
LWEToGLWEKeyCompressed(GLWESwitchingKeyCompressed::alloc(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
@@ -141,11 +141,11 @@ impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyDecompress
|
||||
pub trait LWEToGLWEKeyDecompress
|
||||
where
|
||||
Self: GLWESwitchingKeyDecompress,
|
||||
{
|
||||
fn decompress_lwe_to_glwe_switching_key<R, O>(&self, res: &mut R, other: &O)
|
||||
fn decompress_lwe_to_glwe_key<R, O>(&self, res: &mut R, other: &O)
|
||||
where
|
||||
R: GGLWEToMut + GLWESwitchingKeyDegreesMut,
|
||||
O: GGLWECompressedToRef + GLWESwitchingKeyDegrees,
|
||||
@@ -154,25 +154,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
|
||||
impl<B: Backend> LWEToGLWEKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {}
|
||||
|
||||
impl<D: DataMut> LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataMut> LWEToGLWEKey<D> {
|
||||
pub fn decompress<O, M>(&mut self, module: &M, other: &O)
|
||||
where
|
||||
O: GGLWECompressedToRef + GLWESwitchingKeyDegrees,
|
||||
M: LWEToGLWESwitchingKeyDecompress,
|
||||
M: LWEToGLWEKeyDecompress,
|
||||
{
|
||||
module.decompress_lwe_to_glwe_switching_key(self, other);
|
||||
module.decompress_lwe_to_glwe_key(self, other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWECompressedToRef for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataRef> GGLWECompressedToRef for LWEToGLWEKeyCompressed<D> {
|
||||
fn to_ref(&self) -> GGLWECompressed<&[u8]> {
|
||||
self.0.to_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWECompressedToMut for LWEToGLWESwitchingKeyCompressed<D> {
|
||||
impl<D: DataMut> GGLWECompressedToMut for LWEToGLWEKeyCompressed<D> {
|
||||
fn to_mut(&mut self) -> GGLWECompressed<&mut [u8]> {
|
||||
self.0.to_mut()
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
mod gglwe;
|
||||
mod gglwe_to_ggsw_key;
|
||||
mod ggsw;
|
||||
mod glwe;
|
||||
mod glwe_automorphism_key;
|
||||
mod glwe_switching_key;
|
||||
mod glwe_tensor_key;
|
||||
mod glwe_to_lwe_switching_key;
|
||||
mod glwe_to_lwe_key;
|
||||
mod lwe;
|
||||
mod lwe_switching_key;
|
||||
mod lwe_to_glwe_switching_key;
|
||||
mod lwe_to_glwe_key;
|
||||
|
||||
pub use gglwe::*;
|
||||
pub use gglwe_to_ggsw_key::*;
|
||||
pub use ggsw::*;
|
||||
pub use glwe::*;
|
||||
pub use glwe_automorphism_key::*;
|
||||
pub use glwe_switching_key::*;
|
||||
pub use glwe_tensor_key::*;
|
||||
pub use glwe_to_lwe_switching_key::*;
|
||||
pub use glwe_to_lwe_key::*;
|
||||
pub use lwe::*;
|
||||
pub use lwe_switching_key::*;
|
||||
pub use lwe_to_glwe_switching_key::*;
|
||||
pub use lwe_to_glwe_key::*;
|
||||
|
||||
254
poulpy-core/src/layouts/gglwe_to_ggsw_key.rs
Normal file
254
poulpy-core/src/layouts/gglwe_to_ggsw_key.rs
Normal file
@@ -0,0 +1,254 @@
|
||||
use poulpy_hal::{
|
||||
layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo},
|
||||
source::Source,
|
||||
};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWE, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct GGLWEToGGSWKeyLayout {
|
||||
pub n: Degree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
pub rank: Rank,
|
||||
pub dnum: Dnum,
|
||||
pub dsize: Dsize,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GGLWEToGGSWKey<D: Data> {
|
||||
pub(crate) keys: Vec<GGLWE<D>>,
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GGLWEToGGSWKey<D> {
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GGLWEToGGSWKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GGLWEInfos for GGLWEToGGSWKey<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
|
||||
fn rank_out(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
}
|
||||
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.keys[0].dsize()
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.keys[0].dnum()
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEInfos for GGLWEToGGSWKeyLayout {
|
||||
fn n(&self) -> Degree {
|
||||
self.n
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.k
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for GGLWEToGGSWKeyLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEInfos for GGLWEToGGSWKeyLayout {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.dsize
|
||||
}
|
||||
|
||||
fn rank_out(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.dnum
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GGLWEToGGSWKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GGLWEToGGSWKey<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.for_each(|key: &mut GGLWE<D>| key.fill_uniform(log_bound, source))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GGLWEToGGSWKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "(GGLWEToGGSWKey)",)?;
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
write!(f, "{i}: {key}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEToGGSWKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEToGGSWKey"
|
||||
);
|
||||
Self::alloc(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
GGLWEToGGSWKey {
|
||||
keys: (0..rank.as_usize())
|
||||
.map(|_| GGLWE::alloc(n, base2k, k, rank, rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A>(infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEToGGSWKey"
|
||||
);
|
||||
Self::bytes_of(
|
||||
infos.n(),
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
rank.as_usize() * GGLWE::bytes_of(n, base2k, k, rank, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToGGSWKey<D> {
|
||||
// Returns a mutable reference to GGLWE_{s}([s[i]*s[0], s[i]*s[1], ..., s[i]*s[rank]])
|
||||
pub fn at_mut(&mut self, i: usize) -> &mut GGLWE<D> {
|
||||
assert!((i as u32) < self.rank());
|
||||
&mut self.keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEToGGSWKey<D> {
|
||||
// Returns a reference to GGLWE_{s}(s[i] * s[j])
|
||||
pub fn at(&self, i: usize) -> &GGLWE<D> {
|
||||
assert!((i as u32) < self.rank());
|
||||
&self.keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GGLWEToGGSWKey<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 {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("self.keys.len()={} != read len={}", self.keys.len(), len),
|
||||
));
|
||||
}
|
||||
for key in &mut self.keys {
|
||||
key.read_from(reader)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GGLWEToGGSWKey<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 {
|
||||
key.write_to(writer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyToRef {
|
||||
fn to_ref(&self) -> GGLWEToGGSWKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEToGGSWKeyToRef for GGLWEToGGSWKey<D>
|
||||
where
|
||||
GGLWE<D>: GGLWEToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GGLWEToGGSWKey<&[u8]> {
|
||||
GGLWEToGGSWKey {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyToMut {
|
||||
fn to_mut(&mut self) -> GGLWEToGGSWKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToGGSWKeyToMut for GGLWEToGGSWKey<D>
|
||||
where
|
||||
GGLWE<D>: GGLWEToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GGLWEToGGSWKey<&mut [u8]> {
|
||||
GGLWEToGGSWKey {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
221
poulpy-core/src/layouts/glwe_secret_tensor.rs
Normal file
221
poulpy-core/src/layouts/glwe_secret_tensor.rs
Normal file
@@ -0,0 +1,221 @@
|
||||
use poulpy_hal::{
|
||||
api::{
|
||||
ModuleN, ScratchTakeBasic, SvpApplyDftToDft, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
|
||||
VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyTmpA,
|
||||
},
|
||||
layouts::{
|
||||
Backend, Data, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToMut, ScalarZnxToRef, Scratch, ZnxInfos, ZnxView,
|
||||
ZnxViewMut,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ScratchTakeCore,
|
||||
dist::Distribution,
|
||||
layouts::{
|
||||
Base2K, Degree, GLWEInfos, GLWESecret, GLWESecretPreparedFactory, GLWESecretToMut, GLWESecretToRef, LWEInfos, Rank,
|
||||
TorusPrecision,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct GLWESecretTensor<D: Data> {
|
||||
pub(crate) data: ScalarZnx<D>,
|
||||
pub(crate) rank: Rank,
|
||||
pub(crate) dist: Distribution,
|
||||
}
|
||||
|
||||
impl GLWESecretTensor<Vec<u8>> {
|
||||
pub(crate) fn pairs(rank: usize) -> usize {
|
||||
(((rank + 1) * rank) >> 1).max(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> LWEInfos for GLWESecretTensor<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
Base2K(0)
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
TorusPrecision(0)
|
||||
}
|
||||
|
||||
fn n(&self) -> Degree {
|
||||
Degree(self.data.n() as u32)
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESecretTensor<D> {
|
||||
pub fn at(&self, mut i: usize, mut j: usize) -> ScalarZnx<&[u8]> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank().into();
|
||||
ScalarZnx {
|
||||
data: bytemuck::cast_slice(self.data.at(i * rank + j - (i * (i + 1) / 2), 0)),
|
||||
n: self.n().into(),
|
||||
cols: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESecretTensor<D> {
|
||||
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> ScalarZnx<&mut [u8]> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank().into();
|
||||
ScalarZnx {
|
||||
n: self.n().into(),
|
||||
data: bytemuck::cast_slice_mut(self.data.at_mut(i * rank + j - (i * (i + 1) / 2), 0)),
|
||||
cols: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GLWESecretTensor<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESecretToRef for GLWESecretTensor<D> {
|
||||
fn to_ref(&self) -> GLWESecret<&[u8]> {
|
||||
GLWESecret {
|
||||
data: self.data.to_ref(),
|
||||
dist: self.dist,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESecretToMut for GLWESecretTensor<D> {
|
||||
fn to_mut(&mut self) -> GLWESecret<&mut [u8]> {
|
||||
GLWESecret {
|
||||
dist: self.dist,
|
||||
data: self.data.to_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWESecretTensor<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::alloc(infos.n(), infos.rank())
|
||||
}
|
||||
|
||||
pub fn alloc(n: Degree, rank: Rank) -> Self {
|
||||
GLWESecretTensor {
|
||||
data: ScalarZnx::alloc(n.into(), Self::pairs(rank.into())),
|
||||
rank,
|
||||
dist: Distribution::NONE,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A>(infos: &A) -> usize
|
||||
where
|
||||
A: GLWEInfos,
|
||||
{
|
||||
Self::bytes_of(infos.n(), Self::pairs(infos.rank().into()).into())
|
||||
}
|
||||
|
||||
pub fn bytes_of(n: Degree, rank: Rank) -> usize {
|
||||
ScalarZnx::bytes_of(n.into(), Self::pairs(rank.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESecretTensor<D> {
|
||||
pub fn prepare<M, S, BE: Backend>(&mut self, module: &M, other: &S, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
M: GLWESecretTensorFactory<BE>,
|
||||
S: GLWESecretToRef + GLWEInfos,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
module.glwe_secret_tensor_prepare(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWESecretTensorFactory<BE: Backend> {
|
||||
fn glwe_secret_tensor_prepare_tmp_bytes(&self, rank: Rank) -> usize;
|
||||
|
||||
fn glwe_secret_tensor_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
R: GLWESecretToMut + GLWEInfos,
|
||||
O: GLWESecretToRef + GLWEInfos;
|
||||
}
|
||||
|
||||
impl<BE: Backend> GLWESecretTensorFactory<BE> for Module<BE>
|
||||
where
|
||||
Self: ModuleN
|
||||
+ GLWESecretPreparedFactory<BE>
|
||||
+ VecZnxBigNormalize<BE>
|
||||
+ VecZnxDftApply<BE>
|
||||
+ SvpApplyDftToDft<BE>
|
||||
+ VecZnxIdftApplyTmpA<BE>
|
||||
+ VecZnxBigNormalize<BE>
|
||||
+ VecZnxDftBytesOf
|
||||
+ VecZnxBigBytesOf
|
||||
+ VecZnxBigNormalizeTmpBytes,
|
||||
Scratch<BE>: ScratchTakeCore<BE>,
|
||||
{
|
||||
fn glwe_secret_tensor_prepare_tmp_bytes(&self, rank: Rank) -> usize {
|
||||
self.bytes_of_glwe_secret_prepared(rank)
|
||||
+ self.bytes_of_vec_znx_dft(rank.into(), 1)
|
||||
+ self.bytes_of_vec_znx_dft(1, 1)
|
||||
+ self.bytes_of_vec_znx_big(1, 1)
|
||||
+ self.vec_znx_big_normalize_tmp_bytes()
|
||||
}
|
||||
|
||||
fn glwe_secret_tensor_prepare<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
R: GLWESecretToMut + GLWEInfos,
|
||||
A: GLWESecretToRef + GLWEInfos,
|
||||
{
|
||||
let res: &mut GLWESecret<&mut [u8]> = &mut res.to_mut();
|
||||
let a: &GLWESecret<&[u8]> = &a.to_ref();
|
||||
|
||||
println!("res.rank: {} a.rank: {}", res.rank(), a.rank());
|
||||
|
||||
assert_eq!(res.rank(), GLWESecretTensor::pairs(a.rank().into()) as u32);
|
||||
assert_eq!(res.n(), self.n() as u32);
|
||||
assert_eq!(a.n(), self.n() as u32);
|
||||
|
||||
let rank: usize = a.rank().into();
|
||||
|
||||
let (mut a_prepared, scratch_1) = scratch.take_glwe_secret_prepared(self, rank.into());
|
||||
a_prepared.prepare(self, a);
|
||||
|
||||
let base2k: usize = 17;
|
||||
|
||||
let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(self, rank, 1);
|
||||
for i in 0..rank {
|
||||
self.vec_znx_dft_apply(1, 0, &mut a_dft, i, &a.data.as_vec_znx(), i);
|
||||
}
|
||||
|
||||
let (mut a_ij_big, scratch_3) = scratch_2.take_vec_znx_big(self, 1, 1);
|
||||
let (mut a_ij_dft, scratch_4) = scratch_3.take_vec_znx_dft(self, 1, 1);
|
||||
|
||||
// sk_tensor = sk (x) sk
|
||||
// For example: (s0, s1) (x) (s0, s1) = (s0^2, s0s1, s1^2)
|
||||
for i in 0..rank {
|
||||
for j in i..rank {
|
||||
let idx: usize = i * rank + j - (i * (i + 1) / 2);
|
||||
self.svp_apply_dft_to_dft(&mut a_ij_dft, 0, &a_prepared.data, j, &a_dft, i);
|
||||
self.vec_znx_idft_apply_tmpa(&mut a_ij_big, 0, &mut a_ij_dft, 0);
|
||||
self.vec_znx_big_normalize(
|
||||
base2k,
|
||||
&mut res.data.as_vec_znx_mut(),
|
||||
idx,
|
||||
base2k,
|
||||
&a_ij_big,
|
||||
0,
|
||||
scratch_4,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ use poulpy_hal::{
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWE, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@@ -21,31 +20,29 @@ pub struct GLWETensorKeyLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GLWETensorKey<D: Data> {
|
||||
pub(crate) keys: Vec<GGLWE<D>>,
|
||||
}
|
||||
pub struct GLWETensorKey<D: Data>(pub(crate) GGLWE<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for GLWETensorKey<D> {
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
self.0.base2k()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
self.0.size()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GLWETensorKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
self.0.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,15 +52,15 @@ impl<D: Data> GGLWEInfos for GLWETensorKey<D> {
|
||||
}
|
||||
|
||||
fn rank_out(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
self.0.rank_out()
|
||||
}
|
||||
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.keys[0].dsize()
|
||||
self.0.dsize()
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.keys[0].dnum()
|
||||
self.0.dnum()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,18 +110,14 @@ impl<D: DataRef> fmt::Debug for GLWETensorKey<D> {
|
||||
|
||||
impl<D: DataMut> FillUniform for GLWETensorKey<D> {
|
||||
fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) {
|
||||
self.keys
|
||||
.iter_mut()
|
||||
.for_each(|key: &mut GGLWE<D>| key.fill_uniform(log_bound, source))
|
||||
self.0.fill_uniform(log_bound, source)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Display for GLWETensorKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "(GLWETensorKey)",)?;
|
||||
for (i, key) in self.keys.iter().enumerate() {
|
||||
write!(f, "{i}: {key}")?;
|
||||
}
|
||||
write!(f, "{}", self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -151,11 +144,7 @@ impl GLWETensorKey<Vec<u8>> {
|
||||
|
||||
pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self {
|
||||
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
|
||||
GLWETensorKey {
|
||||
keys: (0..pairs)
|
||||
.map(|_| GGLWE::alloc(n, base2k, k, Rank(1), rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
GLWETensorKey(GGLWE::alloc(n, base2k, k, Rank(pairs), rank, dnum, dsize))
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A>(infos: &A) -> usize
|
||||
@@ -178,85 +167,39 @@ impl GLWETensorKey<Vec<u8>> {
|
||||
}
|
||||
|
||||
pub fn bytes_of(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 * GGLWE::bytes_of(n, base2k, k, Rank(1), rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWETensorKey<D> {
|
||||
// Returns a mutable reference to GGLWE_{s}(s[i] * s[j])
|
||||
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWE<D> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank_out().into();
|
||||
&mut self.keys[i * rank + j - (i * (i + 1) / 2)]
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWETensorKey<D> {
|
||||
// Returns a reference to GGLWE_{s}(s[i] * s[j])
|
||||
pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWE<D> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank_out().into();
|
||||
&self.keys[i * rank + j - (i * (i + 1) / 2)]
|
||||
let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
|
||||
GGLWE::bytes_of(n, base2k, k, Rank(pairs), rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWETensorKey<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 {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!("self.keys.len()={} != read len={}", self.keys.len(), len),
|
||||
));
|
||||
}
|
||||
for key in &mut self.keys {
|
||||
key.read_from(reader)?;
|
||||
}
|
||||
self.0.read_from(reader)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> WriterTo for GLWETensorKey<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 {
|
||||
key.write_to(writer)?;
|
||||
}
|
||||
self.0.write_to(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyToRef {
|
||||
fn to_ref(&self) -> GLWETensorKey<&[u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWETensorKeyToRef for GLWETensorKey<D>
|
||||
impl<D: DataRef> GGLWEToRef for GLWETensorKey<D>
|
||||
where
|
||||
GGLWE<D>: GGLWEToRef,
|
||||
{
|
||||
fn to_ref(&self) -> GLWETensorKey<&[u8]> {
|
||||
GLWETensorKey {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
fn to_ref(&self) -> GGLWE<&[u8]> {
|
||||
self.0.to_ref()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyToMut {
|
||||
fn to_mut(&mut self) -> GLWETensorKey<&mut [u8]>;
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWETensorKeyToMut for GLWETensorKey<D>
|
||||
impl<D: DataMut> GGLWEToMut for GLWETensorKey<D>
|
||||
where
|
||||
GGLWE<D>: GGLWEToMut,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWETensorKey<&mut [u8]> {
|
||||
GLWETensorKey {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
fn to_mut(&mut self) -> GGLWE<&mut [u8]> {
|
||||
self.0.to_mut()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +59,9 @@ impl GGLWEInfos for GLWEToLWEKeyLayout {
|
||||
|
||||
/// A special [GLWESwitchingKey] required to for the conversion from [GLWE] to [LWE].
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
pub struct GLWEToLWEKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: Data> LWEInfos for GLWEToLWEKey<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.0.base2k()
|
||||
}
|
||||
@@ -79,12 +79,12 @@ impl<D: Data> LWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: Data> GLWEInfos for GLWEToLWEKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GGLWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: Data> GGLWEInfos for GLWEToLWEKey<D> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.0.rank_in()
|
||||
}
|
||||
@@ -102,37 +102,37 @@ impl<D: Data> GGLWEInfos for GLWEToLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataRef> fmt::Debug for GLWEToLWEKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataMut> FillUniform for GLWEToLWEKey<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 GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataRef> fmt::Display for GLWEToLWEKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(GLWEToLWESwitchingKey) {}", self.0)
|
||||
write!(f, "(GLWEToLWEKey) {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataMut> ReaderFrom for GLWEToLWEKey<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 GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataRef> WriterTo for GLWEToLWEKey<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
self.0.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEToLWESwitchingKey<Vec<u8>> {
|
||||
impl GLWEToLWEKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
@@ -140,12 +140,12 @@ impl GLWEToLWESwitchingKey<Vec<u8>> {
|
||||
assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKey"
|
||||
"rank_out > 1 is not supported for GLWEToLWEKey"
|
||||
);
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKey"
|
||||
"dsize > 1 is not supported for GLWEToLWEKey"
|
||||
);
|
||||
Self::alloc(
|
||||
infos.n(),
|
||||
@@ -157,7 +157,7 @@ impl GLWEToLWESwitchingKey<Vec<u8>> {
|
||||
}
|
||||
|
||||
pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self {
|
||||
GLWEToLWESwitchingKey(GLWESwitchingKey::alloc(
|
||||
GLWEToLWEKey(GLWESwitchingKey::alloc(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
@@ -196,19 +196,19 @@ impl GLWEToLWESwitchingKey<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEToRef for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataRef> GGLWEToRef for GLWEToLWEKey<D> {
|
||||
fn to_ref(&self) -> GGLWE<&[u8]> {
|
||||
self.0.to_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToMut for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataMut> GGLWEToMut for GLWEToLWEKey<D> {
|
||||
fn to_mut(&mut self) -> GGLWE<&mut [u8]> {
|
||||
self.0.to_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESwitchingKeyDegreesMut for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataMut> GLWESwitchingKeyDegreesMut for GLWEToLWEKey<D> {
|
||||
fn input_degree(&mut self) -> &mut Degree {
|
||||
&mut self.0.input_degree
|
||||
}
|
||||
@@ -218,7 +218,7 @@ impl<D: DataMut> GLWESwitchingKeyDegreesMut for GLWEToLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESwitchingKeyDegrees for GLWEToLWESwitchingKey<D> {
|
||||
impl<D: DataRef> GLWESwitchingKeyDegrees for GLWEToLWEKey<D> {
|
||||
fn input_degree(&self) -> &Degree {
|
||||
&self.0.input_degree
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use crate::layouts::{
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub struct LWEToGLWESwitchingKeyLayout {
|
||||
pub struct LWEToGLWEKeyLayout {
|
||||
pub n: Degree,
|
||||
pub base2k: Base2K,
|
||||
pub k: TorusPrecision,
|
||||
@@ -19,7 +19,7 @@ pub struct LWEToGLWESwitchingKeyLayout {
|
||||
pub dnum: Dnum,
|
||||
}
|
||||
|
||||
impl LWEInfos for LWEToGLWESwitchingKeyLayout {
|
||||
impl LWEInfos for LWEToGLWEKeyLayout {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.base2k
|
||||
}
|
||||
@@ -33,13 +33,13 @@ impl LWEInfos for LWEToGLWESwitchingKeyLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl GLWEInfos for LWEToGLWESwitchingKeyLayout {
|
||||
impl GLWEInfos for LWEToGLWEKeyLayout {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl GGLWEInfos for LWEToGLWESwitchingKeyLayout {
|
||||
impl GGLWEInfos for LWEToGLWEKeyLayout {
|
||||
fn rank_in(&self) -> Rank {
|
||||
Rank(1)
|
||||
}
|
||||
@@ -58,9 +58,9 @@ impl GGLWEInfos for LWEToGLWESwitchingKeyLayout {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub struct LWEToGLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
pub struct LWEToGLWEKey<D: Data>(pub(crate) GLWESwitchingKey<D>);
|
||||
|
||||
impl<D: Data> LWEInfos for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: Data> LWEInfos for LWEToGLWEKey<D> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.0.base2k()
|
||||
}
|
||||
@@ -78,12 +78,12 @@ impl<D: Data> LWEInfos for LWEToGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data> GLWEInfos for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: Data> GLWEInfos for LWEToGLWEKey<D> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
impl<D: Data> GGLWEInfos for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: Data> GGLWEInfos for LWEToGLWEKey<D> {
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.0.dsize()
|
||||
}
|
||||
@@ -101,37 +101,37 @@ impl<D: Data> GGLWEInfos for LWEToGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> fmt::Debug for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> fmt::Debug for LWEToGLWEKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> FillUniform for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataMut> FillUniform for LWEToGLWEKey<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 LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> fmt::Display for LWEToGLWEKey<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "(LWEToGLWESwitchingKey) {}", self.0)
|
||||
write!(f, "(LWEToGLWEKey) {}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> ReaderFrom for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataMut> ReaderFrom for LWEToGLWEKey<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 LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> WriterTo for LWEToGLWEKey<D> {
|
||||
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
self.0.write_to(writer)
|
||||
}
|
||||
}
|
||||
|
||||
impl LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
impl LWEToGLWEKey<Vec<u8>> {
|
||||
pub fn alloc_from_infos<A>(infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
@@ -139,12 +139,12 @@ impl LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"rank_in > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"dsize > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
|
||||
Self::alloc(
|
||||
@@ -157,7 +157,7 @@ impl LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
}
|
||||
|
||||
pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self {
|
||||
LWEToGLWESwitchingKey(GLWESwitchingKey::alloc(
|
||||
LWEToGLWEKey(GLWESwitchingKey::alloc(
|
||||
n,
|
||||
base2k,
|
||||
k,
|
||||
@@ -175,12 +175,12 @@ impl LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"rank_in > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"dsize > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
Self::bytes_of(
|
||||
infos.n(),
|
||||
@@ -196,19 +196,19 @@ impl LWEToGLWESwitchingKey<Vec<u8>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GGLWEToRef for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> GGLWEToRef for LWEToGLWEKey<D> {
|
||||
fn to_ref(&self) -> GGLWE<&[u8]> {
|
||||
self.0.to_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GGLWEToMut for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataMut> GGLWEToMut for LWEToGLWEKey<D> {
|
||||
fn to_mut(&mut self) -> GGLWE<&mut [u8]> {
|
||||
self.0.to_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut> GLWESwitchingKeyDegreesMut for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataMut> GLWESwitchingKeyDegreesMut for LWEToGLWEKey<D> {
|
||||
fn input_degree(&mut self) -> &mut Degree {
|
||||
&mut self.0.input_degree
|
||||
}
|
||||
@@ -218,7 +218,7 @@ impl<D: DataMut> GLWESwitchingKeyDegreesMut for LWEToGLWESwitchingKey<D> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef> GLWESwitchingKeyDegrees for LWEToGLWESwitchingKey<D> {
|
||||
impl<D: DataRef> GLWESwitchingKeyDegrees for LWEToGLWEKey<D> {
|
||||
fn input_degree(&self) -> &Degree {
|
||||
&self.0.input_degree
|
||||
}
|
||||
@@ -1,40 +1,44 @@
|
||||
mod gglwe;
|
||||
mod gglwe_to_ggsw_key;
|
||||
mod ggsw;
|
||||
mod glwe;
|
||||
mod glwe_automorphism_key;
|
||||
mod glwe_plaintext;
|
||||
mod glwe_public_key;
|
||||
mod glwe_secret;
|
||||
mod glwe_secret_tensor;
|
||||
mod glwe_switching_key;
|
||||
mod glwe_tensor;
|
||||
mod glwe_tensor_key;
|
||||
mod glwe_to_lwe_switching_key;
|
||||
mod glwe_to_lwe_key;
|
||||
mod lwe;
|
||||
mod lwe_plaintext;
|
||||
mod lwe_secret;
|
||||
mod lwe_switching_key;
|
||||
mod lwe_to_glwe_switching_key;
|
||||
mod lwe_to_glwe_key;
|
||||
|
||||
pub mod compressed;
|
||||
pub mod prepared;
|
||||
|
||||
pub use compressed::*;
|
||||
pub use gglwe::*;
|
||||
pub use gglwe_to_ggsw_key::*;
|
||||
pub use ggsw::*;
|
||||
pub use glwe::*;
|
||||
pub use glwe_automorphism_key::*;
|
||||
pub use glwe_plaintext::*;
|
||||
pub use glwe_public_key::*;
|
||||
pub use glwe_secret::*;
|
||||
pub use glwe_secret_tensor::*;
|
||||
pub use glwe_switching_key::*;
|
||||
pub use glwe_tensor::*;
|
||||
pub use glwe_tensor_key::*;
|
||||
pub use glwe_to_lwe_switching_key::*;
|
||||
pub use glwe_to_lwe_key::*;
|
||||
pub use lwe::*;
|
||||
pub use lwe_plaintext::*;
|
||||
pub use lwe_secret::*;
|
||||
pub use lwe_switching_key::*;
|
||||
pub use lwe_to_glwe_switching_key::*;
|
||||
pub use lwe_to_glwe_key::*;
|
||||
pub use prepared::*;
|
||||
|
||||
use poulpy_hal::layouts::{Backend, Module};
|
||||
|
||||
252
poulpy-core/src/layouts/prepared/gglwe_to_ggsw_key.rs
Normal file
252
poulpy-core/src/layouts/prepared/gglwe_to_ggsw_key.rs
Normal file
@@ -0,0 +1,252 @@
|
||||
use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWEPrepared, GGLWEPreparedFactory, GGLWEPreparedToMut, GGLWEPreparedToRef,
|
||||
GGLWEToGGSWKey, GGLWEToGGSWKeyToRef, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
};
|
||||
|
||||
pub struct GGLWEToGGSWKeyPrepared<D: Data, BE: Backend> {
|
||||
pub(crate) keys: Vec<GGLWEPrepared<D, BE>>,
|
||||
}
|
||||
|
||||
impl<D: Data, BE: Backend> LWEInfos for GGLWEToGGSWKeyPrepared<D, BE> {
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, BE: Backend> GLWEInfos for GGLWEToGGSWKeyPrepared<D, BE> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, BE: Backend> GGLWEInfos for GGLWEToGGSWKeyPrepared<D, BE> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
|
||||
fn rank_out(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
}
|
||||
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.keys[0].dsize()
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.keys[0].dnum()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyPreparedFactory<BE: Backend> {
|
||||
fn alloc_gglwe_to_ggsw_key_prepared_from_infos<A>(&self, infos: &A) -> GGLWEToGGSWKeyPrepared<Vec<u8>, BE>
|
||||
where
|
||||
A: GGLWEInfos;
|
||||
|
||||
fn alloc_gglwe_to_ggsw_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> GGLWEToGGSWKeyPrepared<Vec<u8>, BE>;
|
||||
|
||||
fn bytes_of_gglwe_to_ggsw_from_infos<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos;
|
||||
|
||||
fn bytes_of_gglwe_to_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize;
|
||||
|
||||
fn prepare_gglwe_to_ggsw_key_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos;
|
||||
|
||||
fn prepare_gglwe_to_ggsw_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
R: GGLWEToGGSWKeyPreparedToMut<BE>,
|
||||
O: GGLWEToGGSWKeyToRef;
|
||||
}
|
||||
|
||||
impl<BE: Backend> GGLWEToGGSWKeyPreparedFactory<BE> for Module<BE>
|
||||
where
|
||||
Self: GGLWEPreparedFactory<BE>,
|
||||
{
|
||||
fn alloc_gglwe_to_ggsw_key_prepared_from_infos<A>(&self, infos: &A) -> GGLWEToGGSWKeyPrepared<Vec<u8>, BE>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
assert_eq!(
|
||||
infos.rank_in(),
|
||||
infos.rank_out(),
|
||||
"rank_in != rank_out is not supported for GGLWEToGGSWKeyPrepared"
|
||||
);
|
||||
self.alloc_gglwe_to_ggsw_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
fn alloc_gglwe_to_ggsw_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
rank: Rank,
|
||||
dnum: Dnum,
|
||||
dsize: Dsize,
|
||||
) -> GGLWEToGGSWKeyPrepared<Vec<u8>, BE> {
|
||||
GGLWEToGGSWKeyPrepared {
|
||||
keys: (0..rank.as_usize())
|
||||
.map(|_| self.alloc_gglwe_prepared(base2k, k, rank, rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn bytes_of_gglwe_to_ggsw_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 GGLWEToGGSWKeyPrepared"
|
||||
);
|
||||
self.bytes_of_gglwe_to_ggsw(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank(),
|
||||
infos.dnum(),
|
||||
infos.dsize(),
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_gglwe_to_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize {
|
||||
rank.as_usize() * self.bytes_of_gglwe_prepared(base2k, k, rank, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
fn prepare_gglwe_to_ggsw_key_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.prepare_gglwe_tmp_bytes(infos)
|
||||
}
|
||||
|
||||
fn prepare_gglwe_to_ggsw_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
R: GGLWEToGGSWKeyPreparedToMut<BE>,
|
||||
O: GGLWEToGGSWKeyToRef,
|
||||
{
|
||||
let res: &mut GGLWEToGGSWKeyPrepared<&mut [u8], BE> = &mut res.to_mut();
|
||||
let other: &GGLWEToGGSWKey<&[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_gglwe(a, b, scratch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<BE: Backend> GGLWEToGGSWKeyPrepared<Vec<u8>, BE> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GGLWEToGGSWKeyPreparedFactory<BE>,
|
||||
{
|
||||
module.alloc_gglwe_to_ggsw_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self
|
||||
where
|
||||
M: GGLWEToGGSWKeyPreparedFactory<BE>,
|
||||
{
|
||||
module.alloc_gglwe_to_ggsw_key_prepared(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GGLWEToGGSWKeyPreparedFactory<BE>,
|
||||
{
|
||||
module.bytes_of_gglwe_to_ggsw_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
|
||||
where
|
||||
M: GGLWEToGGSWKeyPreparedFactory<BE>,
|
||||
{
|
||||
module.bytes_of_gglwe_to_ggsw(base2k, k, rank, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, BE: Backend> GGLWEToGGSWKeyPrepared<D, BE> {
|
||||
pub fn prepare<M, O>(&mut self, module: &M, other: &O, scratch: &mut Scratch<BE>)
|
||||
where
|
||||
M: GGLWEToGGSWKeyPreparedFactory<BE>,
|
||||
O: GGLWEToGGSWKeyToRef,
|
||||
{
|
||||
module.prepare_gglwe_to_ggsw_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, BE: Backend> GGLWEToGGSWKeyPrepared<D, BE> {
|
||||
// Returns a mutable reference to GGLWEPrepared_{s}([s[i]*s[0], s[i]*s[1], ..., s[i]*s[rank]])
|
||||
pub fn at_mut(&mut self, i: usize) -> &mut GGLWEPrepared<D, BE> {
|
||||
assert!((i as u32) < self.rank());
|
||||
&mut self.keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, BE: Backend> GGLWEToGGSWKeyPrepared<D, BE> {
|
||||
// Returns a reference to GGLWEPrepared_{s}([s[i]*s[0], s[i]*s[1], ..., s[i]*s[rank]])
|
||||
pub fn at(&self, i: usize) -> &GGLWEPrepared<D, BE> {
|
||||
assert!((i as u32) < self.rank());
|
||||
&self.keys[i]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyPreparedToRef<BE: Backend> {
|
||||
fn to_ref(&self) -> GGLWEToGGSWKeyPrepared<&[u8], BE>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, BE: Backend> GGLWEToGGSWKeyPreparedToRef<BE> for GGLWEToGGSWKeyPrepared<D, BE>
|
||||
where
|
||||
GGLWEPrepared<D, BE>: GGLWEPreparedToRef<BE>,
|
||||
{
|
||||
fn to_ref(&self) -> GGLWEToGGSWKeyPrepared<&[u8], BE> {
|
||||
GGLWEToGGSWKeyPrepared {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GGLWEToGGSWKeyPreparedToMut<BE: Backend> {
|
||||
fn to_mut(&mut self) -> GGLWEToGGSWKeyPrepared<&mut [u8], BE>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, BE: Backend> GGLWEToGGSWKeyPreparedToMut<BE> for GGLWEToGGSWKeyPrepared<D, BE>
|
||||
where
|
||||
GGLWEPrepared<D, BE>: GGLWEPreparedToMut<BE>,
|
||||
{
|
||||
fn to_mut(&mut self) -> GGLWEToGGSWKeyPrepared<&mut [u8], BE> {
|
||||
GGLWEToGGSWKeyPrepared {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
fn bytes_of_glwe_switching_key_prepared(
|
||||
fn bytes_of_glwe_key_prepared(
|
||||
&self,
|
||||
base2k: Base2K,
|
||||
k: TorusPrecision,
|
||||
@@ -125,7 +125,7 @@ where
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
self.bytes_of_glwe_switching_key_prepared(
|
||||
self.bytes_of_glwe_key_prepared(
|
||||
infos.base2k(),
|
||||
infos.k(),
|
||||
infos.rank_in(),
|
||||
@@ -199,7 +199,7 @@ impl<B: Backend> GLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
where
|
||||
M: GLWESwitchingKeyPreparedFactory<B>,
|
||||
{
|
||||
module.bytes_of_glwe_switching_key_prepared(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
module.bytes_of_glwe_key_prepared(base2k, k, rank_in, rank_out, dnum, dsize)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,29 +2,27 @@ use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch};
|
||||
|
||||
use crate::layouts::{
|
||||
Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWEPrepared, GGLWEPreparedFactory, GGLWEPreparedToMut, GGLWEPreparedToRef,
|
||||
GLWEInfos, GLWETensorKey, GLWETensorKeyToRef, LWEInfos, Rank, TorusPrecision,
|
||||
GGLWEToRef, GLWEInfos, LWEInfos, Rank, TorusPrecision,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GLWETensorKeyPrepared<D: Data, B: Backend> {
|
||||
pub(crate) keys: Vec<GGLWEPrepared<D, B>>,
|
||||
}
|
||||
pub struct GLWETensorKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWEPrepared<D, B>);
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GLWETensorKeyPrepared<D, B> {
|
||||
fn n(&self) -> Degree {
|
||||
self.keys[0].n()
|
||||
self.0.n()
|
||||
}
|
||||
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.keys[0].base2k()
|
||||
self.0.base2k()
|
||||
}
|
||||
|
||||
fn k(&self) -> TorusPrecision {
|
||||
self.keys[0].k()
|
||||
self.0.k()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
self.keys[0].size()
|
||||
self.0.size()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,15 +38,15 @@ impl<D: Data, B: Backend> GGLWEInfos for GLWETensorKeyPrepared<D, B> {
|
||||
}
|
||||
|
||||
fn rank_out(&self) -> Rank {
|
||||
self.keys[0].rank_out()
|
||||
self.0.rank_out()
|
||||
}
|
||||
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.keys[0].dsize()
|
||||
self.0.dsize()
|
||||
}
|
||||
|
||||
fn dnum(&self) -> Dnum {
|
||||
self.keys[0].dnum()
|
||||
self.0.dnum()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +63,7 @@ where
|
||||
rank: Rank,
|
||||
) -> GLWETensorKeyPrepared<Vec<u8>, B> {
|
||||
let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
|
||||
GLWETensorKeyPrepared {
|
||||
keys: (0..pairs)
|
||||
.map(|_| self.alloc_gglwe_prepared(base2k, k, Rank(1), rank, dnum, dsize))
|
||||
.collect(),
|
||||
}
|
||||
GLWETensorKeyPrepared(self.alloc_gglwe_prepared(base2k, k, Rank(pairs), rank, dnum, dsize))
|
||||
}
|
||||
|
||||
fn alloc_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> GLWETensorKeyPrepared<Vec<u8>, B>
|
||||
@@ -91,8 +85,8 @@ where
|
||||
}
|
||||
|
||||
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_gglwe_prepared(base2k, k, Rank(1), rank, dnum, dsize)
|
||||
let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1);
|
||||
self.bytes_of_gglwe_prepared(base2k, k, Rank(pairs), rank, dnum, dsize)
|
||||
}
|
||||
|
||||
fn bytes_of_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> usize
|
||||
@@ -117,17 +111,10 @@ where
|
||||
|
||||
fn prepare_tensor_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: GLWETensorKeyPreparedToMut<B>,
|
||||
O: GLWETensorKeyToRef,
|
||||
R: GGLWEPreparedToMut<B>,
|
||||
O: GGLWEToRef,
|
||||
{
|
||||
let mut res: GLWETensorKeyPrepared<&mut [u8], B> = res.to_mut();
|
||||
let other: GLWETensorKey<&[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_gglwe(a, b, scratch);
|
||||
}
|
||||
self.prepare_gglwe(res, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,28 +152,6 @@ impl<B: Backend> GLWETensorKeyPrepared<Vec<u8>, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWETensorKeyPrepared<D, B> {
|
||||
// Returns a mutable reference to GGLWE_{s}(s[i] * s[j])
|
||||
pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWEPrepared<D, B> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank_out().into();
|
||||
&mut self.keys[i * rank + j - (i * (i + 1) / 2)]
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWETensorKeyPrepared<D, B> {
|
||||
// Returns a reference to GGLWE_{s}(s[i] * s[j])
|
||||
pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWEPrepared<D, B> {
|
||||
if i > j {
|
||||
std::mem::swap(&mut i, &mut j);
|
||||
};
|
||||
let rank: usize = self.rank_out().into();
|
||||
&self.keys[i * rank + j - (i * (i + 1) / 2)]
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWETensorKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize
|
||||
where
|
||||
@@ -200,39 +165,27 @@ impl<B: Backend> GLWETensorKeyPrepared<Vec<u8>, B> {
|
||||
impl<D: DataMut, B: Backend> GLWETensorKeyPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: GLWETensorKeyToRef,
|
||||
O: GGLWEToRef,
|
||||
M: GLWETensorKeyPreparedFactory<B>,
|
||||
{
|
||||
module.prepare_tensor_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyPreparedToMut<B: Backend> {
|
||||
fn to_mut(&mut self) -> GLWETensorKeyPrepared<&mut [u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWETensorKeyPreparedToMut<B> for GLWETensorKeyPrepared<D, B>
|
||||
impl<D: DataMut, B: Backend> GGLWEPreparedToMut<B> for GLWETensorKeyPrepared<D, B>
|
||||
where
|
||||
GGLWEPrepared<D, B>: GGLWEPreparedToMut<B>,
|
||||
{
|
||||
fn to_mut(&mut self) -> GLWETensorKeyPrepared<&mut [u8], B> {
|
||||
GLWETensorKeyPrepared {
|
||||
keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
|
||||
}
|
||||
fn to_mut(&mut self) -> GGLWEPrepared<&mut [u8], B> {
|
||||
self.0.to_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWETensorKeyPreparedToRef<B: Backend> {
|
||||
fn to_ref(&self) -> GLWETensorKeyPrepared<&[u8], B>;
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWETensorKeyPreparedToRef<B> for GLWETensorKeyPrepared<D, B>
|
||||
impl<D: DataRef, B: Backend> GGLWEPreparedToRef<B> for GLWETensorKeyPrepared<D, B>
|
||||
where
|
||||
GGLWEPrepared<D, B>: GGLWEPreparedToRef<B>,
|
||||
{
|
||||
fn to_ref(&self) -> GLWETensorKeyPrepared<&[u8], B> {
|
||||
GLWETensorKeyPrepared {
|
||||
keys: self.keys.iter().map(|c| c.to_ref()).collect(),
|
||||
}
|
||||
fn to_ref(&self) -> GGLWEPrepared<&[u8], B> {
|
||||
self.0.to_ref()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ use crate::layouts::{
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GLWEToLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
pub struct GLWEToLWEKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> LWEInfos for GLWEToLWEKeyPrepared<D, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.0.base2k()
|
||||
}
|
||||
@@ -27,13 +27,13 @@ impl<D: Data, B: Backend> LWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GLWEInfos for GLWEToLWEKeyPrepared<D, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GGLWEInfos for GLWEToLWEKeyPrepared<D, B> {
|
||||
fn rank_in(&self) -> Rank {
|
||||
self.0.rank_in()
|
||||
}
|
||||
@@ -51,65 +51,65 @@ impl<D: Data, B: Backend> GGLWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GLWEToLWESwitchingKeyPreparedFactory<B: Backend>
|
||||
pub trait GLWEToLWEKeyPreparedFactory<B: Backend>
|
||||
where
|
||||
Self: GLWESwitchingKeyPreparedFactory<B>,
|
||||
{
|
||||
fn alloc_glwe_to_lwe_switching_key_prepared(
|
||||
fn alloc_glwe_to_lwe_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)))
|
||||
) -> GLWEToLWEKeyPrepared<Vec<u8>, B> {
|
||||
GLWEToLWEKeyPrepared(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>
|
||||
fn alloc_glwe_to_lwe_key_prepared_from_infos<A>(&self, infos: &A) -> GLWEToLWEKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_out().0,
|
||||
1,
|
||||
"rank_out > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
"rank_out > 1 is not supported for GLWEToLWEKeyPrepared"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
"dsize > 1 is not supported for GLWEToLWEKeyPrepared"
|
||||
);
|
||||
self.alloc_glwe_to_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
self.alloc_glwe_to_lwe_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_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_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
|
||||
fn bytes_of_glwe_to_lwe_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"
|
||||
"rank_out > 1 is not supported for GLWEToLWEKeyPrepared"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared"
|
||||
"dsize > 1 is not supported for GLWEToLWEKeyPrepared"
|
||||
);
|
||||
self.bytes_of_glwe_to_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
self.bytes_of_glwe_to_lwe_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum())
|
||||
}
|
||||
|
||||
fn prepare_glwe_to_lwe_switching_key_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
fn prepare_glwe_to_lwe_key_tmp_bytes<A>(&self, infos: &A) -> usize
|
||||
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>)
|
||||
fn prepare_glwe_to_lwe_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: GGLWEPreparedToMut<B> + GLWESwitchingKeyDegreesMut,
|
||||
O: GGLWEToRef + GLWESwitchingKeyDegrees,
|
||||
@@ -118,61 +118,61 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyPreparedFactory<B> for Module<B> where Self: GLWESwitchingKeyPreparedFactory<B> {}
|
||||
impl<B: Backend> GLWEToLWEKeyPreparedFactory<B> for Module<B> where Self: GLWESwitchingKeyPreparedFactory<B> {}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
impl<B: Backend> GLWEToLWEKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyPreparedFactory<B>,
|
||||
M: GLWEToLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.alloc_glwe_to_lwe_switching_key_prepared_from_infos(infos)
|
||||
module.alloc_glwe_to_lwe_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
M: GLWEToLWESwitchingKeyPreparedFactory<B>,
|
||||
M: GLWEToLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.alloc_glwe_to_lwe_switching_key_prepared(base2k, k, rank_in, dnum)
|
||||
module.alloc_glwe_to_lwe_key_prepared(base2k, k, rank_in, dnum)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyPreparedFactory<B>,
|
||||
M: GLWEToLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.bytes_of_glwe_to_lwe_switching_key_prepared_from_infos(infos)
|
||||
module.bytes_of_glwe_to_lwe_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize
|
||||
where
|
||||
M: GLWEToLWESwitchingKeyPreparedFactory<B>,
|
||||
M: GLWEToLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.bytes_of_glwe_to_lwe_switching_key_prepared(base2k, k, rank_in, dnum)
|
||||
module.bytes_of_glwe_to_lwe_key_prepared(base2k, k, rank_in, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
impl<B: Backend> GLWEToLWEKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: GLWEToLWESwitchingKeyPreparedFactory<B>,
|
||||
M: GLWEToLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.prepare_glwe_to_lwe_switching_key_tmp_bytes(infos);
|
||||
module.prepare_glwe_to_lwe_key_tmp_bytes(infos);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: DataMut, B: Backend> GLWEToLWEKeyPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: GGLWEToRef + GLWESwitchingKeyDegrees,
|
||||
M: GLWEToLWESwitchingKeyPreparedFactory<B>,
|
||||
M: GLWEToLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.prepare_glwe_to_lwe_switching_key(self, other, scratch);
|
||||
module.prepare_glwe_to_lwe_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGLWEPreparedToRef<B> for GLWEToLWESwitchingKeyPrepared<D, B>
|
||||
impl<D: DataRef, B: Backend> GGLWEPreparedToRef<B> for GLWEToLWEKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GGLWEPreparedToRef<B>,
|
||||
{
|
||||
@@ -181,7 +181,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GGLWEPreparedToMut<B> for GLWEToLWESwitchingKeyPrepared<D, B>
|
||||
impl<D: DataMut, B: Backend> GGLWEPreparedToMut<B> for GLWEToLWEKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GGLWEPreparedToRef<B>,
|
||||
{
|
||||
@@ -190,7 +190,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWESwitchingKeyDegreesMut for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: DataMut, B: Backend> GLWESwitchingKeyDegreesMut for GLWEToLWEKeyPrepared<D, B> {
|
||||
fn input_degree(&mut self) -> &mut Degree {
|
||||
&mut self.0.input_degree
|
||||
}
|
||||
@@ -200,7 +200,7 @@ impl<D: DataMut, B: Backend> GLWESwitchingKeyDegreesMut for GLWEToLWESwitchingKe
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GLWESwitchingKeyDegrees for GLWEToLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: DataRef, B: Backend> GLWESwitchingKeyDegrees for GLWEToLWEKeyPrepared<D, B> {
|
||||
fn input_degree(&self) -> &Degree {
|
||||
&self.0.input_degree
|
||||
}
|
||||
@@ -86,7 +86,7 @@ where
|
||||
}
|
||||
|
||||
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))
|
||||
self.bytes_of_glwe_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
|
||||
|
||||
@@ -8,9 +8,9 @@ use crate::layouts::{
|
||||
|
||||
/// A special [GLWESwitchingKey] required to for the conversion from [LWE] to [GLWE].
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
pub struct LWEToGLWEKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>);
|
||||
|
||||
impl<D: Data, B: Backend> LWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> LWEInfos for LWEToGLWEKeyPrepared<D, B> {
|
||||
fn base2k(&self) -> Base2K {
|
||||
self.0.base2k()
|
||||
}
|
||||
@@ -28,13 +28,13 @@ impl<D: Data, B: Backend> LWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GLWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GLWEInfos for LWEToGLWEKeyPrepared<D, B> {
|
||||
fn rank(&self) -> Rank {
|
||||
self.rank_out()
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Data, B: Backend> GGLWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: Data, B: Backend> GGLWEInfos for LWEToGLWEKeyPrepared<D, B> {
|
||||
fn dsize(&self) -> Dsize {
|
||||
self.0.dsize()
|
||||
}
|
||||
@@ -52,71 +52,65 @@ impl<D: Data, B: Backend> GGLWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LWEToGLWESwitchingKeyPreparedFactory<B: Backend>
|
||||
pub trait LWEToGLWEKeyPreparedFactory<B: Backend>
|
||||
where
|
||||
Self: GLWESwitchingKeyPreparedFactory<B>,
|
||||
{
|
||||
fn alloc_lwe_to_glwe_switching_key_prepared(
|
||||
fn alloc_lwe_to_glwe_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)))
|
||||
) -> LWEToGLWEKeyPrepared<Vec<u8>, B> {
|
||||
LWEToGLWEKeyPrepared(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>
|
||||
fn alloc_lwe_to_glwe_key_prepared_from_infos<A>(&self, infos: &A) -> LWEToGLWEKeyPrepared<Vec<u8>, B>
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
{
|
||||
debug_assert_eq!(
|
||||
infos.rank_in().0,
|
||||
1,
|
||||
"rank_in > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"rank_in > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"dsize > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
self.alloc_lwe_to_glwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
self.alloc_lwe_to_glwe_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_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> usize {
|
||||
self.bytes_of_glwe_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
|
||||
fn bytes_of_lwe_to_glwe_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"
|
||||
"rank_in > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
infos.dsize().0,
|
||||
1,
|
||||
"dsize > 1 is not supported for LWEToGLWESwitchingKey"
|
||||
"dsize > 1 is not supported for LWEToGLWEKey"
|
||||
);
|
||||
self.bytes_of_lwe_to_glwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
self.bytes_of_lwe_to_glwe_key_prepared(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum())
|
||||
}
|
||||
|
||||
fn prepare_lwe_to_glwe_switching_key_tmp_bytes<A>(&self, infos: &A)
|
||||
fn prepare_lwe_to_glwe_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>)
|
||||
fn prepare_lwe_to_glwe_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
R: GGLWEPreparedToMut<B> + GLWESwitchingKeyDegreesMut,
|
||||
O: GGLWEToRef + GLWESwitchingKeyDegrees,
|
||||
@@ -125,61 +119,61 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyPreparedFactory<B> for Module<B> where Self: GLWESwitchingKeyPreparedFactory<B> {}
|
||||
impl<B: Backend> LWEToGLWEKeyPreparedFactory<B> for Module<B> where Self: GLWESwitchingKeyPreparedFactory<B> {}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
impl<B: Backend> LWEToGLWEKeyPrepared<Vec<u8>, B> {
|
||||
pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyPreparedFactory<B>,
|
||||
M: LWEToGLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.alloc_lwe_to_glwe_switching_key_prepared_from_infos(infos)
|
||||
module.alloc_lwe_to_glwe_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self
|
||||
where
|
||||
M: LWEToGLWESwitchingKeyPreparedFactory<B>,
|
||||
M: LWEToGLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.alloc_lwe_to_glwe_switching_key_prepared(base2k, k, rank_out, dnum)
|
||||
module.alloc_lwe_to_glwe_key_prepared(base2k, k, rank_out, dnum)
|
||||
}
|
||||
|
||||
pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyPreparedFactory<B>,
|
||||
M: LWEToGLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.bytes_of_lwe_to_glwe_switching_key_prepared_from_infos(infos)
|
||||
module.bytes_of_lwe_to_glwe_key_prepared_from_infos(infos)
|
||||
}
|
||||
|
||||
pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> usize
|
||||
where
|
||||
M: LWEToGLWESwitchingKeyPreparedFactory<B>,
|
||||
M: LWEToGLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.bytes_of_lwe_to_glwe_switching_key_prepared(base2k, k, rank_out, dnum)
|
||||
module.bytes_of_lwe_to_glwe_key_prepared(base2k, k, rank_out, dnum)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> {
|
||||
impl<B: Backend> LWEToGLWEKeyPrepared<Vec<u8>, B> {
|
||||
pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A)
|
||||
where
|
||||
A: GGLWEInfos,
|
||||
M: LWEToGLWESwitchingKeyPreparedFactory<B>,
|
||||
M: LWEToGLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.prepare_lwe_to_glwe_switching_key_tmp_bytes(infos);
|
||||
module.prepare_lwe_to_glwe_key_tmp_bytes(infos);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: DataMut, B: Backend> LWEToGLWEKeyPrepared<D, B> {
|
||||
pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>)
|
||||
where
|
||||
O: GGLWEToRef + GLWESwitchingKeyDegrees,
|
||||
M: LWEToGLWESwitchingKeyPreparedFactory<B>,
|
||||
M: LWEToGLWEKeyPreparedFactory<B>,
|
||||
{
|
||||
module.prepare_lwe_to_glwe_switching_key(self, other, scratch);
|
||||
module.prepare_lwe_to_glwe_key(self, other, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataRef, B: Backend> GGLWEPreparedToRef<B> for LWEToGLWESwitchingKeyPrepared<D, B>
|
||||
impl<D: DataRef, B: Backend> GGLWEPreparedToRef<B> for LWEToGLWEKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GGLWEPreparedToRef<B>,
|
||||
{
|
||||
@@ -188,7 +182,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GGLWEPreparedToMut<B> for LWEToGLWESwitchingKeyPrepared<D, B>
|
||||
impl<D: DataMut, B: Backend> GGLWEPreparedToMut<B> for LWEToGLWEKeyPrepared<D, B>
|
||||
where
|
||||
GLWESwitchingKeyPrepared<D, B>: GGLWEPreparedToMut<B>,
|
||||
{
|
||||
@@ -197,7 +191,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: DataMut, B: Backend> GLWESwitchingKeyDegreesMut for LWEToGLWESwitchingKeyPrepared<D, B> {
|
||||
impl<D: DataMut, B: Backend> GLWESwitchingKeyDegreesMut for LWEToGLWEKeyPrepared<D, B> {
|
||||
fn input_degree(&mut self) -> &mut Degree {
|
||||
&mut self.0.input_degree
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
mod gglwe;
|
||||
mod gglwe_to_ggsw_key;
|
||||
mod ggsw;
|
||||
mod glwe;
|
||||
mod glwe_automorphism_key;
|
||||
@@ -6,11 +7,12 @@ mod glwe_public_key;
|
||||
mod glwe_secret;
|
||||
mod glwe_switching_key;
|
||||
mod glwe_tensor_key;
|
||||
mod glwe_to_lwe_switching_key;
|
||||
mod glwe_to_lwe_key;
|
||||
mod lwe_switching_key;
|
||||
mod lwe_to_glwe_switching_key;
|
||||
mod lwe_to_glwe_key;
|
||||
|
||||
pub use gglwe::*;
|
||||
pub use gglwe_to_ggsw_key::*;
|
||||
pub use ggsw::*;
|
||||
pub use glwe::*;
|
||||
pub use glwe_automorphism_key::*;
|
||||
@@ -18,6 +20,6 @@ pub use glwe_public_key::*;
|
||||
pub use glwe_secret::*;
|
||||
pub use glwe_switching_key::*;
|
||||
pub use glwe_tensor_key::*;
|
||||
pub use glwe_to_lwe_switching_key::*;
|
||||
pub use glwe_to_lwe_key::*;
|
||||
pub use lwe_switching_key::*;
|
||||
pub use lwe_to_glwe_switching_key::*;
|
||||
pub use lwe_to_glwe_key::*;
|
||||
|
||||
Reference in New Issue
Block a user