From 7704e14d45da2cab4c33e77df5a36ca17203aae6 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bossuat Date: Fri, 31 Jan 2025 12:01:28 +0100 Subject: [PATCH] VecZnx: added ring degree switching --- base2k/build.rs | 49 ----------------------------- base2k/spqlios-arithmetic | 1 - base2k/src/bindgen.rs | 36 +++++++++++++++++++++ base2k/src/scalar.rs | 7 +++++ base2k/src/scalar_vector_product.rs | 8 +++-- base2k/src/vec_znx.rs | 26 +++++++++++++++ 6 files changed, 75 insertions(+), 52 deletions(-) delete mode 160000 base2k/spqlios-arithmetic create mode 100644 base2k/src/bindgen.rs diff --git a/base2k/build.rs b/base2k/build.rs index c11becf..4ddb96c 100644 --- a/base2k/build.rs +++ b/base2k/build.rs @@ -1,55 +1,6 @@ -//use bindgen; -//use std::env; -//use std::fs; use std::path::absolute; -//use std::path::PathBuf; -//use std::time::SystemTime; fn main() { - /* - - [build-dependencies] - bindgen ="0.71.1" - - // Path to the C header file - let header_paths: [&str; 2] = [ - "spqlios-arithmetic/spqlios/coeffs/coeffs_arithmetic.h", - "spqlios-arithmetic/spqlios/arithmetic/vec_znx_arithmetic.h", - ]; - - let out_path: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap()); - let bindings_file = out_path.join("bindings.rs"); - - let regenerate: bool = header_paths.iter().any(|header| { - let header_metadata: SystemTime = fs::metadata(header) - .and_then(|m| m.modified()) - .unwrap_or(SystemTime::UNIX_EPOCH); - let bindings_metadata: SystemTime = fs::metadata(&bindings_file) - .and_then(|m| m.modified()) - .unwrap_or(SystemTime::UNIX_EPOCH); - header_metadata > bindings_metadata - }); - - if regenerate { - // Generate the Rust bindings - let mut builder: bindgen::Builder = bindgen::Builder::default(); - for header in header_paths { - builder = builder.header(header); - } - - let bindings = builder - .generate_comments(false) // Optional: includes comments in bindings - .generate_inline_functions(true) // Optional: includes inline functions - .generate() - .expect("Unable to generate bindings"); - - // Write the bindings to the OUT_DIR - bindings - .write_to_file(&bindings_file) - .expect("Couldn't write bindings!"); - } - */ - println!( "cargo:rustc-link-search=native={}", absolute("./spqlios-arithmetic/build/spqlios") diff --git a/base2k/spqlios-arithmetic b/base2k/spqlios-arithmetic deleted file mode 160000 index 7ea875f..0000000 --- a/base2k/spqlios-arithmetic +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7ea875f61c51c67687ec9c15ae0eae04cda961f8 diff --git a/base2k/src/bindgen.rs b/base2k/src/bindgen.rs new file mode 100644 index 0000000..39e4ca9 --- /dev/null +++ b/base2k/src/bindgen.rs @@ -0,0 +1,36 @@ +/* +[build-dependencies] +bindgen ="0.71.1" + +//use bindgen; +//use std::env; +//use std::fs; +//use std::path::PathBuf; +//use std::time::SystemTime; + +// Path to the C header file +let header_paths: [&str; 2] = [ + "spqlios-arithmetic/spqlios/coeffs/coeffs_arithmetic.h", + "spqlios-arithmetic/spqlios/arithmetic/vec_znx_arithmetic.h", +]; + +let out_path: PathBuf = PathBuf::from(env::var("OUT_DIR").unwrap()); +let bindings_file = out_path.join("bindings.rs"); + +let mut builder: bindgen::Builder = bindgen::Builder::default(); +for header in header_paths { + builder = builder.header(header); +} + +let bindings = builder + .generate_comments(false) // Optional: includes comments in bindings + .generate_inline_functions(true) // Optional: includes inline functions + .generate() + .expect("Unable to generate bindings"); + +// Write the bindings to the OUT_DIR +bindings + .write_to_file(&bindings_file) + .expect("Couldn't write bindings!"); + +*/ \ No newline at end of file diff --git a/base2k/src/scalar.rs b/base2k/src/scalar.rs index 34e46a8..59b85f7 100644 --- a/base2k/src/scalar.rs +++ b/base2k/src/scalar.rs @@ -1,3 +1,4 @@ +use crate::Module; use rand::seq::SliceRandom; use rand_core::RngCore; use rand_distr::{Distribution, WeightedIndex}; @@ -5,6 +6,12 @@ use sampling::source::Source; pub struct Scalar(pub Vec); +impl Module { + pub fn new_scalar(&self) -> Scalar { + Scalar::new(self.n()) + } +} + impl Scalar { pub fn new(n: usize) -> Self { Self(vec![i64::default(); Self::buffer_size(n)]) diff --git a/base2k/src/scalar_vector_product.rs b/base2k/src/scalar_vector_product.rs index 548ad04..3c2b13e 100644 --- a/base2k/src/scalar_vector_product.rs +++ b/base2k/src/scalar_vector_product.rs @@ -2,9 +2,13 @@ use crate::ffi::svp::{delete_svp_ppol, new_svp_ppol, svp_apply_dft, svp_ppol_t, use crate::scalar::Scalar; use crate::{Module, VecZnx, VecZnxDft}; -pub struct SvpPPol(pub *mut svp_ppol_t); +pub struct SvpPPol(pub *mut svp_ppol_t, pub usize); impl SvpPPol { + pub fn n(&self) -> usize { + self.1 + } + pub fn delete(self) { unsafe { delete_svp_ppol(self.0) }; let _ = drop(self); @@ -20,7 +24,7 @@ impl Module { // Allocates a scalar-vector-product prepared-poly (VecZnxBig). pub fn svp_new_ppol(&self) -> SvpPPol { - unsafe { SvpPPol(new_svp_ppol(self.0)) } + unsafe { SvpPPol(new_svp_ppol(self.0), self.n()) } } // Applies a scalar x vector product: res <- a (ppol) x b diff --git a/base2k/src/vec_znx.rs b/base2k/src/vec_znx.rs index cefcad3..534d5d0 100644 --- a/base2k/src/vec_znx.rs +++ b/base2k/src/vec_znx.rs @@ -98,6 +98,10 @@ impl VecZnx { &mut self.data[i * self.n..(i + 1) * self.n] } + pub fn zero(&mut self) { + unsafe { znx_zero_i64_ref(self.data.len() as u64, self.data.as_mut_ptr()) } + } + pub fn from_i64(&mut self, data: &[i64], log_max: usize) { let size: usize = min(data.len(), self.n()); let k_rem: usize = self.log_base2k - (self.log_q % self.log_base2k); @@ -362,6 +366,28 @@ impl VecZnx { }) } } + + pub fn switch_degree(&self, a: &mut VecZnx) { + let (n_in, n_out) = (self.n(), a.n()); + let (gap_in, gap_out): (usize, usize); + + if n_in > n_out { + (gap_in, gap_out) = (n_in / n_out, 1) + } else { + (gap_in, gap_out) = (1, n_out / n_in); + a.zero(); + } + + let limbs = min(self.limbs(), a.limbs()); + + (0..limbs).for_each(|i| { + izip!( + self.at(i).iter().step_by(gap_in), + a.at_mut(i).iter_mut().step_by(gap_out) + ) + .for_each(|(x_in, x_out)| *x_out = *x_in); + }); + } } #[cfg(test)]