poulpy/base2k/src/svp.rs
base2k/src/svp.rsRaw
1use crate::ffi::svp::{delete_svp_ppol, new_svp_ppol, svp_apply_dft, svp_ppol_t, svp_prepare};
2use crate::scalar::Scalar;
3use crate::{Free, Module, VecZnx, VecZnxDft};
4
5pub struct SvpPPol(pub *mut svp_ppol_t, pub usize);
6
7/// A prepared [crate::Scalar] for [ScalarVectorProduct::svp_apply_dft].
8/// An [SvpPPol] an be seen as a [VecZnxDft] of one limb.
9/// The backend array of an [SvpPPol] is allocated in C and must be freed manually.
10impl SvpPPol {
11 /// Returns the ring degree of the [SvpPPol].
12 pub fn n(&self) -> usize {
13 self.1
14 }
15
16 /// Returns the number of limbs of the [SvpPPol], which is always 1.
17 pub fn limbs(&self) -> usize {
18 1
19 }
20}
21
22impl Free for SvpPPol {
23 fn free(self) {
24 unsafe { delete_svp_ppol(self.0) };
25 let _ = drop(self);
26 }
27}
28
29pub trait ScalarVectorProduct {
30 /// Prepares a [crate::Scalar] for a [ScalarVectorProduct::svp_apply_dft].
31 fn svp_prepare(&self, svp_ppol: &mut SvpPPol, a: &Scalar);
32
33 /// Allocates a new [SvpPPol].
34 fn svp_new_ppol(&self) -> SvpPPol;
35
36 /// Applies the [SvpPPol] x [VecZnxDft] product, where each limb of
37 /// the [VecZnxDft] is multiplied with [SvpPPol].
38 fn svp_apply_dft(&self, c: &mut VecZnxDft, a: &SvpPPol, b: &VecZnx);
39}
40
41impl Module {
42 pub fn svp_prepare(&self, svp_ppol: &mut SvpPPol, a: &Scalar) {
43 unsafe { svp_prepare(self.0, svp_ppol.0, a.as_ptr()) }
44 }
45
46 pub fn svp_new_ppol(&self) -> SvpPPol {
47 unsafe { SvpPPol(new_svp_ppol(self.0), self.n()) }
48 }
49
50 pub fn svp_apply_dft(&self, c: &mut VecZnxDft, a: &SvpPPol, b: &VecZnx) {
51 let limbs: u64 = b.limbs() as u64;
52 assert!(
53 c.limbs() as u64 >= limbs,
54 "invalid c_vector: c_vector.limbs()={} < b.limbs()={}",
55 c.limbs(),
56 limbs
57 );
58 unsafe { svp_apply_dft(self.0, c.0, limbs, a.0, b.as_ptr(), limbs, b.n() as u64) }
59 }
60}