mirror of
https://github.com/arnaucube/poulpy.git
synced 2026-02-10 05:06:44 +01:00
Add bdd rotation
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -353,7 +353,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "poulpy-backend"
|
name = "poulpy-backend"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"cmake",
|
"cmake",
|
||||||
@@ -370,7 +370,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "poulpy-core"
|
name = "poulpy-core"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"criterion",
|
"criterion",
|
||||||
@@ -383,7 +383,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "poulpy-hal"
|
name = "poulpy-hal"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
@@ -400,7 +400,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "poulpy-schemes"
|
name = "poulpy-schemes"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"criterion",
|
"criterion",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "poulpy-backend"
|
name = "poulpy-backend"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "poulpy-core"
|
name = "poulpy-core"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
description = "A backend agnostic crate implementing RLWE-based encryption & arithmetic."
|
description = "A backend agnostic crate implementing RLWE-based encryption & arithmetic."
|
||||||
|
|||||||
55
poulpy-core/src/operations/ggsw.rs
Normal file
55
poulpy-core/src/operations/ggsw.rs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
use poulpy_hal::layouts::{Backend, Module, Scratch};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
GLWERotate, ScratchTakeCore,
|
||||||
|
layouts::{GGSW, GGSWInfos, GGSWToMut, GGSWToRef, GLWEInfos},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<BE: Backend> GGSWRotate<BE> for Module<BE> where Module<BE>: GLWERotate<BE> {}
|
||||||
|
|
||||||
|
pub trait GGSWRotate<BE: Backend>
|
||||||
|
where
|
||||||
|
Self: GLWERotate<BE>,
|
||||||
|
{
|
||||||
|
fn ggsw_rotate_tmp_bytes(&self) -> usize {
|
||||||
|
self.glwe_rotate_tmp_bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ggsw_rotate<R, A>(&self, k: i64, res: &mut R, a: &A)
|
||||||
|
where
|
||||||
|
R: GGSWToMut,
|
||||||
|
A: GGSWToRef,
|
||||||
|
{
|
||||||
|
let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
|
||||||
|
let a: &GGSW<&[u8]> = &a.to_ref();
|
||||||
|
|
||||||
|
assert!(res.dnum() <= a.dnum());
|
||||||
|
assert_eq!(res.dsize(), a.dsize());
|
||||||
|
assert_eq!(res.rank(), a.rank());
|
||||||
|
let rows: usize = res.dnum().into();
|
||||||
|
let cols: usize = (res.rank() + 1).into();
|
||||||
|
|
||||||
|
for row in 0..rows {
|
||||||
|
for col in 0..cols {
|
||||||
|
self.glwe_rotate(k, &mut res.at_mut(row, col), &a.at(row, col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ggsw_rotate_inplace<R>(&self, k: i64, res: &mut R, scratch: &mut Scratch<BE>)
|
||||||
|
where
|
||||||
|
R: GGSWToMut,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
|
||||||
|
|
||||||
|
let rows: usize = res.dnum().into();
|
||||||
|
let cols: usize = (res.rank() + 1).into();
|
||||||
|
|
||||||
|
for row in 0..rows {
|
||||||
|
for col in 0..cols {
|
||||||
|
self.glwe_rotate_inplace(k, &mut res.at_mut(row, col), scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ use poulpy_hal::{
|
|||||||
VecZnxSubInplace, VecZnxSubNegateInplace,
|
VecZnxSubInplace, VecZnxSubNegateInplace,
|
||||||
},
|
},
|
||||||
layouts::{Backend, Module, Scratch, VecZnx, ZnxZero},
|
layouts::{Backend, Module, Scratch, VecZnx, ZnxZero},
|
||||||
|
reference::vec_znx::vec_znx_rotate_inplace_tmp_bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -185,6 +186,10 @@ pub trait GLWERotate<BE: Backend>
|
|||||||
where
|
where
|
||||||
Self: ModuleN + VecZnxRotate + VecZnxRotateInplace<BE>,
|
Self: ModuleN + VecZnxRotate + VecZnxRotateInplace<BE>,
|
||||||
{
|
{
|
||||||
|
fn glwe_rotate_tmp_bytes(&self) -> usize {
|
||||||
|
vec_znx_rotate_inplace_tmp_bytes(self.n())
|
||||||
|
}
|
||||||
|
|
||||||
fn glwe_rotate<R, A>(&self, k: i64, res: &mut R, a: &A)
|
fn glwe_rotate<R, A>(&self, k: i64, res: &mut R, a: &A)
|
||||||
where
|
where
|
||||||
R: GLWEToMut,
|
R: GLWEToMut,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
mod ggsw;
|
||||||
mod glwe;
|
mod glwe;
|
||||||
|
|
||||||
|
pub use ggsw::*;
|
||||||
pub use glwe::*;
|
pub use glwe::*;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "poulpy-hal"
|
name = "poulpy-hal"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "poulpy-schemes"
|
name = "poulpy-schemes"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
42
poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_rotation.rs
Normal file
42
poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_rotation.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
use poulpy_core::{
|
||||||
|
GLWECopy, GLWERotate, ScratchTakeCore,
|
||||||
|
layouts::{GLWE, GLWEToMut},
|
||||||
|
};
|
||||||
|
use poulpy_hal::layouts::{Backend, Scratch};
|
||||||
|
|
||||||
|
use crate::tfhe::bdd_arithmetic::{Cmux, GetGGSWBit, UnsignedInteger};
|
||||||
|
|
||||||
|
pub trait BDDRotation<T: UnsignedInteger, BE: Backend>
|
||||||
|
where
|
||||||
|
Self: GLWECopy + GLWERotate<BE> + Cmux<BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
/// Homomorphic multiplication of res by X^{k[bit_start..bit_start + bit_size] * bit_step}.
|
||||||
|
fn bdd_rotate<R, K, D>(
|
||||||
|
&self,
|
||||||
|
res: &mut R,
|
||||||
|
k: K,
|
||||||
|
bit_start: usize,
|
||||||
|
bit_size: usize,
|
||||||
|
bit_step: usize,
|
||||||
|
scratch: &mut Scratch<BE>,
|
||||||
|
) where
|
||||||
|
R: GLWEToMut,
|
||||||
|
K: GetGGSWBit<T, BE>,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
let res: &mut GLWE<&mut [u8]> = &mut res.to_mut();
|
||||||
|
|
||||||
|
let (mut tmp_res, scratch_1) = scratch.take_glwe(res);
|
||||||
|
|
||||||
|
self.glwe_copy(&mut tmp_res, res);
|
||||||
|
|
||||||
|
for i in 1..bit_size {
|
||||||
|
// res' = res * X^2^(i * bit_step)
|
||||||
|
self.glwe_rotate(1 << (i + bit_step), &mut tmp_res, res);
|
||||||
|
|
||||||
|
// res = (res - res') * GGSW(b[i]) + res'
|
||||||
|
self.cmux_inplace(res, &tmp_res, &k.get_bit(i + bit_start), scratch_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,6 +39,17 @@ impl<D: DataRef, T: UnsignedInteger> GLWEInfos for FheUintBlocks<D, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<D: Data, T: UnsignedInteger> FheUintBlocks<D, T> {
|
||||||
|
pub fn new(blocks: Vec<GLWE<D>>) -> Self {
|
||||||
|
assert_eq!(blocks.len(), T::WORD_SIZE);
|
||||||
|
Self {
|
||||||
|
blocks,
|
||||||
|
_base: 1,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: UnsignedInteger> FheUintBlocks<Vec<u8>, T> {
|
impl<T: UnsignedInteger> FheUintBlocks<Vec<u8>, T> {
|
||||||
pub fn alloc_from_infos<A, BE: Backend>(module: &Module<BE>, infos: &A) -> Self
|
pub fn alloc_from_infos<A, BE: Backend>(module: &Module<BE>, infos: &A) -> Self
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::marker::PhantomData;
|
|||||||
use poulpy_core::layouts::{
|
use poulpy_core::layouts::{
|
||||||
Base2K, Dnum, Dsize, GGSWInfos, GGSWPreparedFactory, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWPrepared,
|
Base2K, Dnum, Dsize, GGSWInfos, GGSWPreparedFactory, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWPrepared,
|
||||||
};
|
};
|
||||||
|
use poulpy_core::layouts::{GGSWPreparedToMut, GGSWPreparedToRef};
|
||||||
|
|
||||||
use poulpy_core::{GGSWEncryptSk, ScratchTakeCore, layouts::GLWESecretPreparedToRef};
|
use poulpy_core::{GGSWEncryptSk, ScratchTakeCore, layouts::GLWESecretPreparedToRef};
|
||||||
use poulpy_hal::layouts::{Backend, Data, DataRef, Module};
|
use poulpy_hal::layouts::{Backend, Data, DataRef, Module};
|
||||||
@@ -28,6 +29,28 @@ impl<T: UnsignedInteger, BE: Backend> FheUintBlocksPreparedFactory<T, BE> for Mo
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait GetGGSWBit<T: UnsignedInteger, BE: Backend> {
|
||||||
|
fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: DataRef, T: UnsignedInteger, BE: Backend> GetGGSWBit<T, BE> for FheUintBlocksPrepared<D, T, BE> {
|
||||||
|
fn get_bit(&self, bit: usize) -> GGSWPrepared<&[u8], BE> {
|
||||||
|
assert!(bit <= self.blocks.len());
|
||||||
|
self.blocks[bit].to_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GetGGSWBitMut<T: UnsignedInteger, BE: Backend> {
|
||||||
|
fn get_bit(&mut self, bit: usize) -> GGSWPrepared<&mut [u8], BE>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: DataMut, T: UnsignedInteger, BE: Backend> GetGGSWBitMut<T, BE> for FheUintBlocksPrepared<D, T, BE> {
|
||||||
|
fn get_bit(&mut self, bit: usize) -> GGSWPrepared<&mut [u8], BE> {
|
||||||
|
assert!(bit <= self.blocks.len());
|
||||||
|
self.blocks[bit].to_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait FheUintBlocksPreparedFactory<T: UnsignedInteger, BE: Backend>
|
pub trait FheUintBlocksPreparedFactory<T: UnsignedInteger, BE: Backend>
|
||||||
where
|
where
|
||||||
Self: Sized + GGSWPreparedFactory<BE>,
|
Self: Sized + GGSWPreparedFactory<BE>,
|
||||||
|
|||||||
@@ -3,12 +3,9 @@ use core::panic;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use poulpy_core::{
|
use poulpy_core::{
|
||||||
GLWEAdd, GLWECopy, GLWEExternalProduct, GLWESub, ScratchTakeCore,
|
GLWEAdd, GLWECopy, GLWEExternalProduct, GLWESub, ScratchTakeCore,
|
||||||
layouts::{
|
layouts::{GLWE, GLWEToMut, GLWEToRef, LWEInfos, prepared::GGSWPreparedToRef},
|
||||||
GLWE, LWEInfos,
|
|
||||||
prepared::{GGSWPrepared, GGSWPreparedToRef},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero};
|
use poulpy_hal::layouts::{Backend, DataMut, Module, Scratch, ZnxZero};
|
||||||
|
|
||||||
use crate::tfhe::bdd_arithmetic::UnsignedInteger;
|
use crate::tfhe::bdd_arithmetic::UnsignedInteger;
|
||||||
|
|
||||||
@@ -146,30 +143,38 @@ pub enum Node {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Cmux<BE: Backend> {
|
pub trait Cmux<BE: Backend>
|
||||||
fn cmux<O, T, F, S>(&self, out: &mut GLWE<O>, t: &GLWE<T>, f: &GLWE<F>, s: &GGSWPrepared<S, BE>, scratch: &mut Scratch<BE>)
|
where
|
||||||
|
Self: GLWEExternalProduct<BE> + GLWESub + GLWEAdd,
|
||||||
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
|
{
|
||||||
|
fn cmux<R, T, F, S>(&self, res: &mut R, t: &T, f: &F, s: &S, scratch: &mut Scratch<BE>)
|
||||||
where
|
where
|
||||||
O: DataMut,
|
R: GLWEToMut,
|
||||||
T: DataRef,
|
T: GLWEToRef,
|
||||||
F: DataRef,
|
F: GLWEToRef,
|
||||||
S: DataRef;
|
S: GGSWPreparedToRef<BE>,
|
||||||
|
{
|
||||||
|
self.glwe_sub(res, t, f);
|
||||||
|
self.glwe_external_product_inplace(res, s, scratch);
|
||||||
|
self.glwe_add_inplace(res, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cmux_inplace<R, A, S>(&self, res: &mut R, a: &A, s: &S, scratch: &mut Scratch<BE>)
|
||||||
|
where
|
||||||
|
R: GLWEToMut,
|
||||||
|
A: GLWEToRef,
|
||||||
|
S: GGSWPreparedToRef<BE>,
|
||||||
|
{
|
||||||
|
self.glwe_sub_inplace(res, a);
|
||||||
|
self.glwe_external_product_inplace(res, s, scratch);
|
||||||
|
self.glwe_add_inplace(res, a);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BE: Backend> Cmux<BE> for Module<BE>
|
impl<BE: Backend> Cmux<BE> for Module<BE>
|
||||||
where
|
where
|
||||||
Module<BE>: GLWEExternalProduct<BE> + GLWESub + GLWEAdd,
|
Self: GLWEExternalProduct<BE> + GLWESub + GLWEAdd,
|
||||||
Scratch<BE>: ScratchTakeCore<BE>,
|
Scratch<BE>: ScratchTakeCore<BE>,
|
||||||
{
|
{
|
||||||
fn cmux<O, T, F, S>(&self, out: &mut GLWE<O>, t: &GLWE<T>, f: &GLWE<F>, s: &GGSWPrepared<S, BE>, scratch: &mut Scratch<BE>)
|
|
||||||
where
|
|
||||||
O: DataMut,
|
|
||||||
T: DataRef,
|
|
||||||
F: DataRef,
|
|
||||||
S: DataRef,
|
|
||||||
{
|
|
||||||
// let mut out: GLWECiphertext<&mut [u8]> = out.to_mut();
|
|
||||||
self.glwe_sub(out, t, f);
|
|
||||||
self.glwe_external_product_inplace(out, s, scratch);
|
|
||||||
self.glwe_add_inplace(out, f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
mod bdd_2w_to_1w;
|
mod bdd_2w_to_1w;
|
||||||
|
mod bdd_rotation;
|
||||||
mod ciphertexts;
|
mod ciphertexts;
|
||||||
mod circuits;
|
mod circuits;
|
||||||
mod eval;
|
mod eval;
|
||||||
mod key;
|
mod key;
|
||||||
|
|
||||||
pub use bdd_2w_to_1w::*;
|
pub use bdd_2w_to_1w::*;
|
||||||
|
pub use bdd_rotation::*;
|
||||||
pub use ciphertexts::*;
|
pub use ciphertexts::*;
|
||||||
pub(crate) use circuits::*;
|
pub(crate) use circuits::*;
|
||||||
pub(crate) use eval::*;
|
pub(crate) use eval::*;
|
||||||
|
|||||||
Reference in New Issue
Block a user