Add Hardware Abstraction Layer (#56)

This commit is contained in:
Jean-Philippe Bossuat
2025-08-08 19:22:42 +02:00
committed by GitHub
parent 833520b163
commit 0e0745065e
194 changed files with 17397 additions and 11955 deletions

View File

@@ -1,56 +1,73 @@
use backend::{FFT64, Module, Scratch, ZnxZero};
use backend::hal::{
api::{ScratchAvailable, TakeVecZnxDft, ZnxZero},
layouts::{Backend, DataMut, DataRef, Module, Scratch},
};
use crate::{FourierGLWECiphertext, GLWEAutomorphismKey, GLWESwitchingKey, GetRow, Infos, ScratchCore, SetRow};
use crate::{
AutomorphismKey, AutomorphismKeyExec, GLWECiphertext, GLWEKeyswitchFamily, GLWESwitchingKey, GLWESwitchingKeyExec, Infos,
};
impl GLWEAutomorphismKey<Vec<u8>, FFT64> {
pub fn keyswitch_scratch_space(
module: &Module<FFT64>,
impl AutomorphismKey<Vec<u8>> {
pub fn keyswitch_scratch_space<B: Backend>(
module: &Module<B>,
basek: usize,
k_out: usize,
k_in: usize,
k_ksk: usize,
digits: usize,
rank: usize,
) -> usize {
) -> usize
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWESwitchingKey::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank, rank)
}
pub fn keyswitch_inplace_scratch_space(
module: &Module<FFT64>,
pub fn keyswitch_inplace_scratch_space<B: Backend>(
module: &Module<B>,
basek: usize,
k_out: usize,
k_ksk: usize,
digits: usize,
rank: usize,
) -> usize {
) -> usize
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWESwitchingKey::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank)
}
}
impl<DataSelf: AsMut<[u8]> + AsRef<[u8]>> GLWEAutomorphismKey<DataSelf, FFT64> {
pub fn keyswitch<DataLhs: AsRef<[u8]>, DataRhs: AsRef<[u8]>>(
impl<DataSelf: DataMut> AutomorphismKey<DataSelf> {
pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self,
module: &Module<FFT64>,
lhs: &GLWEAutomorphismKey<DataLhs, FFT64>,
rhs: &GLWESwitchingKey<DataRhs, FFT64>,
scratch: &mut Scratch,
) {
module: &Module<B>,
lhs: &AutomorphismKey<DataLhs>,
rhs: &GLWESwitchingKeyExec<DataRhs, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWEKeyswitchFamily<B>,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
{
self.key.keyswitch(module, &lhs.key, rhs, scratch);
}
pub fn keyswitch_inplace<DataRhs: AsRef<[u8]>>(
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>(
&mut self,
module: &Module<FFT64>,
rhs: &GLWEAutomorphismKey<DataRhs, FFT64>,
scratch: &mut Scratch,
) {
module: &Module<B>,
rhs: &AutomorphismKeyExec<DataRhs, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWEKeyswitchFamily<B>,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
{
self.key.keyswitch_inplace(module, &rhs.key, scratch);
}
}
impl GLWESwitchingKey<Vec<u8>, FFT64> {
pub fn keyswitch_scratch_space(
module: &Module<FFT64>,
impl GLWESwitchingKey<Vec<u8>> {
pub fn keyswitch_scratch_space<B: Backend>(
module: &Module<B>,
basek: usize,
k_out: usize,
k_in: usize,
@@ -58,36 +75,39 @@ impl GLWESwitchingKey<Vec<u8>, FFT64> {
digits: usize,
rank_in: usize,
rank_out: usize,
) -> usize {
let tmp_in: usize = FourierGLWECiphertext::bytes_of(module, basek, k_in, rank_in);
let tmp_out: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank_out);
let ksk: usize =
FourierGLWECiphertext::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out);
tmp_in + tmp_out + ksk
) -> usize
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWECiphertext::keyswitch_scratch_space(module, basek, k_out, k_in, k_ksk, digits, rank_in, rank_out)
}
pub fn keyswitch_inplace_scratch_space(
module: &Module<FFT64>,
pub fn keyswitch_inplace_scratch_space<B: Backend>(
module: &Module<B>,
basek: usize,
k_out: usize,
k_ksk: usize,
digits: usize,
rank: usize,
) -> usize {
let tmp: usize = FourierGLWECiphertext::bytes_of(module, basek, k_out, rank);
let ksk: usize = FourierGLWECiphertext::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank);
tmp + ksk
) -> usize
where
Module<B>: GLWEKeyswitchFamily<B>,
{
GLWECiphertext::keyswitch_inplace_scratch_space(module, basek, k_out, k_ksk, digits, rank)
}
}
impl<DataSelf: AsMut<[u8]> + AsRef<[u8]>> GLWESwitchingKey<DataSelf, FFT64> {
pub fn keyswitch<DataLhs: AsRef<[u8]>, DataRhs: AsRef<[u8]>>(
impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>(
&mut self,
module: &Module<FFT64>,
lhs: &GLWESwitchingKey<DataLhs, FFT64>,
rhs: &GLWESwitchingKey<DataRhs, FFT64>,
scratch: &mut Scratch,
) {
module: &Module<B>,
lhs: &GLWESwitchingKey<DataLhs>,
rhs: &GLWESwitchingKeyExec<DataRhs, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWEKeyswitchFamily<B>,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
{
#[cfg(debug_assertions)]
{
assert_eq!(
@@ -113,32 +133,29 @@ impl<DataSelf: AsMut<[u8]> + AsRef<[u8]>> GLWESwitchingKey<DataSelf, FFT64> {
);
}
let (mut tmp_in, scratch1) = scratch.tmp_fourier_glwe_ct(module, lhs.basek(), lhs.k(), lhs.rank());
let (mut tmp_out, scratch2) = scratch1.tmp_fourier_glwe_ct(module, self.basek(), self.k(), self.rank());
(0..self.rank_in()).for_each(|col_i| {
(0..self.rows()).for_each(|row_j| {
lhs.get_row(module, row_j, col_i, &mut tmp_in);
tmp_out.keyswitch(module, &tmp_in, rhs, scratch2);
self.set_row(module, row_j, col_i, &tmp_out);
self.at_mut(row_j, col_i)
.keyswitch(module, &lhs.at(row_j, col_i), rhs, scratch);
});
});
tmp_out.data.zero();
(self.rows().min(lhs.rows())..self.rows()).for_each(|row_i| {
(0..self.rank_in()).for_each(|col_j| {
self.set_row(module, row_i, col_j, &tmp_out);
self.at_mut(row_i, col_j).data.zero();
});
});
}
pub fn keyswitch_inplace<DataRhs: AsRef<[u8]>>(
pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>(
&mut self,
module: &Module<FFT64>,
rhs: &GLWESwitchingKey<DataRhs, FFT64>,
scratch: &mut Scratch,
) {
module: &Module<B>,
rhs: &GLWESwitchingKeyExec<DataRhs, B>,
scratch: &mut Scratch<B>,
) where
Module<B>: GLWEKeyswitchFamily<B>,
Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable,
{
#[cfg(debug_assertions)]
{
assert_eq!(
@@ -150,13 +167,10 @@ impl<DataSelf: AsMut<[u8]> + AsRef<[u8]>> GLWESwitchingKey<DataSelf, FFT64> {
);
}
let (mut tmp, scratch1) = scratch.tmp_fourier_glwe_ct(module, self.basek(), self.k(), self.rank());
(0..self.rank_in()).for_each(|col_i| {
(0..self.rows()).for_each(|row_j| {
self.get_row(module, row_j, col_i, &mut tmp);
tmp.keyswitch_inplace(module, rhs, scratch1);
self.set_row(module, row_j, col_i, &tmp);
self.at_mut(row_j, col_i)
.keyswitch_inplace(module, rhs, scratch)
});
});
}