From eaac9c07d8cd948c44b16668b9b8282ffe507d12 Mon Sep 17 00:00:00 2001 From: Pro7ech Date: Sat, 25 Oct 2025 15:43:18 +0200 Subject: [PATCH] Add GLWETensor --- poulpy-core/src/layouts/glwe_tensor.rs | 146 +++++++++++++++++++++++++ poulpy-core/src/layouts/mod.rs | 2 + 2 files changed, 148 insertions(+) create mode 100644 poulpy-core/src/layouts/glwe_tensor.rs diff --git a/poulpy-core/src/layouts/glwe_tensor.rs b/poulpy-core/src/layouts/glwe_tensor.rs new file mode 100644 index 0000000..516a854 --- /dev/null +++ b/poulpy-core/src/layouts/glwe_tensor.rs @@ -0,0 +1,146 @@ +use poulpy_hal::{ + layouts::{Data, DataMut, DataRef, FillUniform, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos}, + source::Source, +}; + +use crate::layouts::{Base2K, Degree, GLWEInfos, LWEInfos, Rank, SetGLWEInfos, TorusPrecision}; +use std::fmt; + +#[derive(PartialEq, Eq, Clone)] +pub struct GLWETensor { + pub(crate) data: VecZnx, + pub(crate) base2k: Base2K, + pub(crate) rank: Rank, + pub(crate) k: TorusPrecision, +} + +impl SetGLWEInfos for GLWETensor { + fn set_base2k(&mut self, base2k: Base2K) { + self.base2k = base2k + } + + fn set_k(&mut self, k: TorusPrecision) { + self.k = k + } +} + +impl GLWETensor { + pub fn data(&self) -> &VecZnx { + &self.data + } +} + +impl GLWETensor { + pub fn data_mut(&mut self) -> &mut VecZnx { + &mut self.data + } +} + +impl LWEInfos for GLWETensor { + fn base2k(&self) -> Base2K { + self.base2k + } + + fn k(&self) -> TorusPrecision { + self.k + } + + fn n(&self) -> Degree { + Degree(self.data.n() as u32) + } + + fn size(&self) -> usize { + self.data.size() + } +} + +impl GLWEInfos for GLWETensor { + fn rank(&self) -> Rank { + self.rank + } +} + +impl fmt::Debug for GLWETensor { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{self}") + } +} + +impl fmt::Display for GLWETensor { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "GLWETensor: base2k={} k={}: {}", + self.base2k().0, + self.k().0, + self.data + ) + } +} + +impl FillUniform for GLWETensor { + fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { + self.data.fill_uniform(log_bound, source); + } +} + +impl GLWETensor> { + pub fn alloc_from_infos(infos: &A) -> Self + where + A: GLWEInfos, + { + Self::alloc(infos.n(), infos.base2k(), infos.k(), infos.rank()) + } + + pub fn alloc(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self { + let pairs: usize = (((rank + 1) * rank).as_usize() >> 1).max(1) as usize; + GLWETensor { + data: VecZnx::alloc(n.into(), pairs + 1, k.0.div_ceil(base2k.0) as usize), + base2k, + k, + rank, + } + } + + pub fn bytes_of_from_infos(infos: &A) -> usize + where + A: GLWEInfos, + { + Self::bytes_of(infos.n(), infos.base2k(), infos.k(), infos.rank()) + } + + pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize { + let pairs: usize = (((rank + 1) * rank).as_usize() >> 1).max(1) as usize; + VecZnx::bytes_of(n.into(), pairs + 1, k.0.div_ceil(base2k.0) as usize) + } +} + +pub trait GLWETensorToRef { + fn to_ref(&self) -> GLWETensor<&[u8]>; +} + +impl GLWETensorToRef for GLWETensor { + fn to_ref(&self) -> GLWETensor<&[u8]> { + GLWETensor { + k: self.k, + base2k: self.base2k, + data: self.data.to_ref(), + rank: self.rank, + } + } +} + +pub trait GLWETensorToMut { + fn to_mut(&mut self) -> GLWETensor<&mut [u8]>; +} + +impl GLWETensorToMut for GLWETensor { + fn to_mut(&mut self) -> GLWETensor<&mut [u8]> { + GLWETensor { + k: self.k, + base2k: self.base2k, + rank: self.rank, + data: self.data.to_mut(), + } + } +} diff --git a/poulpy-core/src/layouts/mod.rs b/poulpy-core/src/layouts/mod.rs index 1168ac8..7c5cc5b 100644 --- a/poulpy-core/src/layouts/mod.rs +++ b/poulpy-core/src/layouts/mod.rs @@ -6,6 +6,7 @@ mod glwe_plaintext; mod glwe_public_key; mod glwe_secret; mod glwe_switching_key; +mod glwe_tensor; mod glwe_tensor_key; mod glwe_to_lwe_switching_key; mod lwe; @@ -26,6 +27,7 @@ pub use glwe_plaintext::*; pub use glwe_public_key::*; pub use glwe_secret::*; pub use glwe_switching_key::*; +pub use glwe_tensor::*; pub use glwe_tensor_key::*; pub use glwe_to_lwe_switching_key::*; pub use lwe::*;