This commit is contained in:
Pro7ech
2025-10-13 23:49:09 +02:00
parent d32b4738c3
commit 0533cdff8a
27 changed files with 776 additions and 2022 deletions

View File

@@ -1,12 +1,11 @@
use poulpy_hal::{
api::{VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply},
layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VecZnxDft, VecZnxDftToMut, VecZnxDftToRef, ZnxInfos},
oep::VecZnxDftAllocBytesImpl,
layouts::{Backend, Data, DataMut, DataRef, Module, VecZnxDft, VecZnxDftToMut, VecZnxDftToRef, ZnxInfos},
};
use crate::{
dist::Distribution,
layouts::{Base2K, BuildError, Degree, GLWEInfos, GLWEPublicKey, GLWEPublicKeyToRef, LWEInfos, Rank, TorusPrecision},
layouts::{Base2K, Degree, GLWEInfos, GLWEPublicKey, GLWEPublicKeyToRef, GetDegree, GetDist, LWEInfos, Rank, TorusPrecision},
};
#[derive(PartialEq, Eq)]
@@ -51,229 +50,106 @@ impl<D: Data, B: Backend> GLWEInfos for GLWEPublicKeyPrepared<D, B> {
}
}
pub struct GLWEPublicKeyPreparedBuilder<D: Data, B: Backend> {
data: Option<VecZnxDft<D, B>>,
base2k: Option<Base2K>,
k: Option<TorusPrecision>,
}
impl<D: Data, B: Backend> GLWEPublicKeyPrepared<D, B> {
#[inline]
pub fn builder() -> GLWEPublicKeyPreparedBuilder<D, B> {
GLWEPublicKeyPreparedBuilder {
data: None,
base2k: None,
k: None,
}
}
}
impl<B: Backend> GLWEPublicKeyPreparedBuilder<Vec<u8>, B> {
#[inline]
pub fn layout<A>(mut self, layout: &A) -> Self
where
A: GLWEInfos,
B: VecZnxDftAllocBytesImpl<B>,
{
self.data = Some(VecZnxDft::alloc(
layout.n().into(),
(layout.rank() + 1).into(),
layout.size(),
));
self.base2k = Some(layout.base2k());
self.k = Some(layout.k());
self
}
}
impl<D: Data, B: Backend> GLWEPublicKeyPreparedBuilder<D, B> {
#[inline]
pub fn data(mut self, data: VecZnxDft<D, B>) -> Self {
self.data = Some(data);
self
}
#[inline]
pub fn base2k(mut self, base2k: Base2K) -> Self {
self.base2k = Some(base2k);
self
}
#[inline]
pub fn k(mut self, k: TorusPrecision) -> Self {
self.k = Some(k);
self
}
pub fn build(self) -> Result<GLWEPublicKeyPrepared<D, B>, BuildError> {
let data: VecZnxDft<D, B> = self.data.ok_or(BuildError::MissingData)?;
let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?;
let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?;
if base2k == 0_u32 {
return Err(BuildError::ZeroBase2K);
}
if k == 0_u32 {
return Err(BuildError::ZeroTorusPrecision);
}
if data.n() == 0 {
return Err(BuildError::ZeroDegree);
}
if data.cols() == 0 {
return Err(BuildError::ZeroCols);
}
if data.size() == 0 {
return Err(BuildError::ZeroLimbs);
}
Ok(GLWEPublicKeyPrepared {
data,
base2k,
k,
dist: Distribution::NONE,
})
}
}
impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> {
pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
where
A: GLWEInfos,
Module<B>: VecZnxDftAlloc<B>,
{
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
Self::alloc_with(module, infos.base2k(), infos.k(), infos.rank())
}
pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self
where
Module<B>: VecZnxDftAlloc<B>,
{
Self {
data: module.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
base2k,
k,
dist: Distribution::NONE,
}
}
pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
where
A: GLWEInfos,
Module<B>: VecZnxDftAllocBytes,
{
debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()");
Self::alloc_bytes_with(module, infos.base2k(), infos.k(), infos.rank())
}
pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize
where
Module<B>: VecZnxDftAllocBytes,
{
module.vec_znx_dft_alloc_bytes((rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
}
}
pub trait GLWEPublicKeyPrepareTmpBytes {
fn glwe_public_key_prepare_tmp_bytes<A>(&self, infos: &A)
where
A: GLWEInfos;
}
impl<B: Backend> GLWEPublicKeyPrepareTmpBytes for Module<B> {
fn glwe_public_key_prepare_tmp_bytes<A>(&self, infos: &A)
where
A: GLWEInfos,
{
0
}
}
impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> {
pub fn prepare_tmp_bytes<A>(&self, module: &Module<B>, infos: &A)
where
A: GLWEInfos,
Module<B>: GLWEPublicKeyPrepareTmpBytes,
{
module.glwe_public_key_prepare_tmp_bytes(infos);
}
}
pub trait GLWEPublicKeyPrepare<B: Backend> {
fn glwe_public_key_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &Scratch<B>)
where
R: GLWEPublicKeyPreparedToMut<B> + SetDist,
O: GLWEPublicKeyToRef;
}
impl<B: Backend> GLWEPublicKeyPrepare<B> for Module<B>
pub trait GLWEPublicKeyPreparedAlloc<B: Backend>
where
Module<B>: VecZnxDftAlloc<B> + VecZnxDftApply<B>,
Self: GetDegree + VecZnxDftAlloc<B> + VecZnxDftAllocBytes,
{
fn glwe_public_key_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &Scratch<B>)
fn glwe_public_key_prepared_alloc(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKeyPrepared<Vec<u8>, B> {
GLWEPublicKeyPrepared {
data: self.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize),
base2k,
k,
dist: Distribution::NONE,
}
}
fn glwe_public_key_alloc_from_infos<A>(&self, infos: &A) -> GLWEPublicKeyPrepared<Vec<u8>, B>
where
A: GLWEInfos,
{
self.glwe_public_key_prepared_alloc(infos.base2k(), infos.k(), infos.rank())
}
fn glwe_public_key_prepared_alloc_bytes(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
self.vec_znx_dft_alloc_bytes((rank + 1).into(), k.0.div_ceil(base2k.0) as usize)
}
fn glwe_public_key_prepared_alloc_bytes_from_infos<A>(&self, infos: &A) -> usize
where
A: GLWEInfos,
{
self.glwe_public_key_prepared_alloc_bytes(infos.base2k(), infos.k(), infos.rank())
}
}
impl<B: Backend> GLWEPublicKeyPreparedAlloc<B> for Module<B> where Self: VecZnxDftAlloc<B> + VecZnxDftAllocBytes {}
impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B>
where
Module<B>: GLWEPublicKeyPreparedAlloc<B>,
{
pub fn alloc_from_infos<A>(module: &Module<B>, infos: &A) -> Self
where
A: GLWEInfos,
{
module.glwe_public_key_alloc_from_infos(infos)
}
pub fn alloc(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self {
module.glwe_public_key_prepared_alloc(base2k, k, rank)
}
pub fn alloc_bytes_from_infos<A>(module: &Module<B>, infos: &A) -> usize
where
A: GLWEInfos,
{
module.glwe_public_key_prepared_alloc_bytes_from_infos(infos)
}
pub fn alloc_bytes(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize {
module.glwe_public_key_prepared_alloc_bytes(base2k, k, rank)
}
}
pub trait GLWEPublicKeyPrepare<B: Backend>
where
Self: GetDegree + VecZnxDftApply<B>,
{
fn glwe_public_key_prepare<R, O>(&self, res: &mut R, other: &O)
where
R: GLWEPublicKeyPreparedToMut<B> + SetDist,
O: GLWEPublicKeyToRef,
O: GLWEPublicKeyToRef + GetDist,
{
{
let res: GLWEPublicKeyPrepared<&mut [u8], B> = res.to_mut();
let mut res: GLWEPublicKeyPrepared<&mut [u8], B> = res.to_mut();
let other: GLWEPublicKey<&[u8]> = other.to_ref();
assert_eq!(res.n(), self.n() as u32);
assert_eq!(other.n(), self.n() as u32);
assert_eq!(res.n(), self.n());
assert_eq!(other.n(), self.n());
assert_eq!(res.size(), other.size());
assert_eq!(res.k(), other.k());
assert_eq!(res.base2k(), other.base2k());
for i in 0..(self.rank() + 1).into() {
self.vec_znx_dft_apply(1, 0, &mut self.data, i, &other.data, i);
for i in 0..(res.rank() + 1).into() {
self.vec_znx_dft_apply(1, 0, &mut res.data, i, &other.data, i);
}
}
res.set_dist(other.dist);
res.set_dist(other.get_dist());
}
}
impl<B: Backend> GLWEPublicKeyPrepare<B> for Module<B> where Self: GetDegree + VecZnxDftApply<B> {}
impl<D: DataMut, B: Backend> GLWEPublicKeyPrepared<D, B>
where
Module<B>: GLWEPublicKeyPrepare<B>,
{
pub fn prepare<O>(&mut self, module: &Module<B>, other: &O, scratch: &mut Scratch<B>)
pub fn prepare<O>(&mut self, module: &Module<B>, other: &O)
where
O: GLWEPublicKeyToRef,
O: GLWEPublicKeyToRef + GetDist,
{
module.glwe_public_key_prepare(self, other, scratch);
}
}
pub trait GLWEPublicKeyPrepareAlloc<B: Backend> {
fn glwe_public_key_prepare_alloc<O>(&self, other: &O, scratch: &mut Scratch<B>)
where
O: GLWEPublicKeyToRef;
}
impl<B: Backend> GLWEPublicKeyPrepareAlloc<B> for Module<B>
where
Module<B>: GLWEPublicKeyPrepare<B>,
{
fn glwe_public_key_prepare_alloc<O>(&self, other: &O, scratch: &mut Scratch<B>)
where
O: GLWEPublicKeyToRef,
{
let mut ct_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = GLWEPublicKeyPrepared::alloc(self, other);
self.glwe_public_key_prepare(&mut ct_prepared, ct_prepared, scratch);
ct_prepared
}
}
impl<D: DataRef> GLWEPublicKey<D> {
pub fn prepare_alloc<B: Backend>(&self, module: &Module<B>, scratch: &mut Scratch<B>)
where
Module<B>: GLWEPublicKeyPrepareAlloc<B>,
{
module.glwe_public_key_prepare_alloc(self, scratch);
module.glwe_public_key_prepare(self, other);
}
}