poulpy/base2k/src/vec_znx_dft.rs
base2k/src/vec_znx_dft.rsRaw
1use crate::ffi::vec_znx_big;
2use crate::ffi::vec_znx_dft;
3use crate::ffi::vec_znx_dft::bytes_of_vec_znx_dft;
4use crate::{assert_alignement, Infos, Module, VecZnxApi, VecZnxBig};
5
6pub struct VecZnxDft(pub *mut vec_znx_dft::vec_znx_dft_t, pub usize);
7
8impl VecZnxDft {
9 /// Returns a new [VecZnxDft] with the provided data as backing array.
10 /// User must ensure that data is properly alligned and that
11 /// the size of data is at least equal to [Module::bytes_of_vec_znx_dft].
12 pub fn from_bytes(cols: usize, tmp_bytes: &mut [u8]) -> VecZnxDft {
13 #[cfg(debug_assertions)]
14 {
15 assert_alignement(tmp_bytes.as_ptr())
16 }
17 VecZnxDft(
18 tmp_bytes.as_mut_ptr() as *mut vec_znx_dft::vec_znx_dft_t,
19 cols,
20 )
21 }
22
23 /// Cast a [VecZnxDft] into a [VecZnxBig].
24 /// The returned [VecZnxBig] shares the backing array
25 /// with the original [VecZnxDft].
26 pub fn as_vec_znx_big(&mut self) -> VecZnxBig {
27 VecZnxBig(self.0 as *mut vec_znx_big::vec_znx_bigcoeff_t, self.1)
28 }
29 pub fn cols(&self) -> usize {
30 self.1
31 }
32}
33
34pub trait VecZnxDftOps {
35 /// Allocates a vector Z[X]/(X^N+1) that stores normalized in the DFT space.
36 fn new_vec_znx_dft(&self, cols: usize) -> VecZnxDft;
37
38 /// Returns a new [VecZnxDft] with the provided bytes array as backing array.
39 ///
40 /// # Arguments
41 ///
42 /// * `cols`: the number of cols of the [VecZnxDft].
43 /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft].
44 ///
45 /// # Panics
46 /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft].
47 fn new_vec_znx_dft_from_bytes(&self, cols: usize, bytes: &mut [u8]) -> VecZnxDft;
48
49 /// Returns a new [VecZnxDft] with the provided bytes array as backing array.
50 ///
51 /// # Arguments
52 ///
53 /// * `cols`: the number of cols of the [VecZnxDft].
54 /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft].
55 ///
56 /// # Panics
57 /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft].
58 fn bytes_of_vec_znx_dft(&self, cols: usize) -> usize;
59
60 /// Returns the minimum number of bytes necessary to allocate
61 /// a new [VecZnxDft] through [VecZnxDft::from_bytes].
62 fn vec_znx_idft_tmp_bytes(&self) -> usize;
63
64 /// b <- IDFT(a), uses a as scratch space.
65 fn vec_znx_idft_tmp_a(&self, b: &mut VecZnxBig, a: &mut VecZnxDft, a_limbs: usize);
66
67 fn vec_znx_idft(
68 &self,
69 b: &mut VecZnxBig,
70 a: &mut VecZnxDft,
71 a_limbs: usize,
72 tmp_bytes: &mut [u8],
73 );
74
75 fn vec_znx_dft<T: VecZnxApi + Infos>(&self, b: &mut VecZnxDft, a: &T, a_limbs: usize);
76}
77
78impl VecZnxDftOps for Module {
79 fn new_vec_znx_dft(&self, cols: usize) -> VecZnxDft {
80 unsafe { VecZnxDft(vec_znx_dft::new_vec_znx_dft(self.0, cols as u64), cols) }
81 }
82
83 fn new_vec_znx_dft_from_bytes(&self, cols: usize, tmp_bytes: &mut [u8]) -> VecZnxDft {
84 debug_assert!(
85 tmp_bytes.len() >= <Module as VecZnxDftOps>::bytes_of_vec_znx_dft(self, cols),
86 "invalid bytes: bytes.len()={} < bytes_of_vec_znx_dft={}",
87 tmp_bytes.len(),
88 <Module as VecZnxDftOps>::bytes_of_vec_znx_dft(self, cols)
89 );
90 #[cfg(debug_assertions)]
91 {
92 assert_alignement(tmp_bytes.as_ptr())
93 }
94 VecZnxDft::from_bytes(cols, tmp_bytes)
95 }
96
97 fn bytes_of_vec_znx_dft(&self, cols: usize) -> usize {
98 unsafe { bytes_of_vec_znx_dft(self.0, cols as u64) as usize }
99 }
100
101 fn vec_znx_idft_tmp_a(&self, b: &mut VecZnxBig, a: &mut VecZnxDft, a_limbs: usize) {
102 debug_assert!(
103 b.cols() >= a_limbs,
104 "invalid c_vector: b_vector.cols()={} < a_limbs={}",
105 b.cols(),
106 a_limbs
107 );
108 unsafe {
109 vec_znx_dft::vec_znx_idft_tmp_a(self.0, b.0, b.cols() as u64, a.0, a_limbs as u64)
110 }
111 }
112
113 fn vec_znx_idft_tmp_bytes(&self) -> usize {
114 unsafe { vec_znx_dft::vec_znx_idft_tmp_bytes(self.0) as usize }
115 }
116
117 /// b <- DFT(a)
118 ///
119 /// # Panics
120 /// If b.cols < a_cols
121 fn vec_znx_dft<T: VecZnxApi + Infos>(&self, b: &mut VecZnxDft, a: &T, a_cols: usize) {
122 debug_assert!(
123 b.cols() >= a_cols,
124 "invalid a_cols: b.cols()={} < a_cols={}",
125 b.cols(),
126 a_cols
127 );
128 unsafe {
129 vec_znx_dft::vec_znx_dft(
130 self.0,
131 b.0,
132 b.cols() as u64,
133 a.as_ptr(),
134 a_cols as u64,
135 a.n() as u64,
136 )
137 }
138 }
139
140 // b <- IDFT(a), scratch space size obtained with [vec_znx_idft_tmp_bytes].
141 fn vec_znx_idft(
142 &self,
143 b: &mut VecZnxBig,
144 a: &mut VecZnxDft,
145 a_cols: usize,
146 tmp_bytes: &mut [u8],
147 ) {
148 debug_assert!(
149 b.cols() >= a_cols,
150 "invalid c_vector: b.cols()={} < a_cols={}",
151 b.cols(),
152 a_cols
153 );
154 debug_assert!(
155 a.cols() >= a_cols,
156 "invalid c_vector: a.cols()={} < a_cols={}",
157 a.cols(),
158 a_cols
159 );
160 debug_assert!(
161 tmp_bytes.len() <= <Module as VecZnxDftOps>::vec_znx_idft_tmp_bytes(self),
162 "invalid tmp_bytes: tmp_bytes.len()={} < self.vec_znx_idft_tmp_bytes()={}",
163 tmp_bytes.len(),
164 <Module as VecZnxDftOps>::vec_znx_idft_tmp_bytes(self)
165 );
166 #[cfg(debug_assertions)]
167 {
168 assert_alignement(tmp_bytes.as_ptr())
169 }
170 unsafe {
171 vec_znx_dft::vec_znx_idft(
172 self.0,
173 b.0,
174 a.cols() as u64,
175 a.0,
176 a_cols as u64,
177 tmp_bytes.as_mut_ptr(),
178 )
179 }
180 }
181}