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::{Module, VecZnx, 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(limbs: usize, data: &mut [u8]) -> VecZnxDft {
13 VecZnxDft(data.as_mut_ptr() as *mut vec_znx_dft::vec_znx_dft_t, limbs)
14 }
15
16 /// Cast a [VecZnxDft] into a [VecZnxBig].
17 /// The returned [VecZnxBig] shares the backing array
18 /// with the original [VecZnxDft].
19 pub fn as_vec_znx_big(&mut self) -> VecZnxBig {
20 VecZnxBig(self.0 as *mut vec_znx_big::vec_znx_bigcoeff_t, self.1)
21 }
22 pub fn limbs(&self) -> usize {
23 self.1
24 }
25}
26
27impl Module {
28 // Allocates a vector Z[X]/(X^N+1) that stores normalized in the DFT space.
29 pub fn new_vec_znx_dft(&self, limbs: usize) -> VecZnxDft {
30 unsafe { VecZnxDft(vec_znx_dft::new_vec_znx_dft(self.0, limbs as u64), limbs) }
31 }
32
33 /// Returns a new [VecZnxDft] with the provided bytes array as backing array.
34 ///
35 /// # Arguments
36 ///
37 /// * `limbs`: the number of limbs of the [VecZnxDft].
38 /// * `bytes`: a byte array of size at least [Module::bytes_of_vec_znx_dft].
39 ///
40 /// # Panics
41 /// If `bytes.len()` < [Module::bytes_of_vec_znx_dft].
42 pub fn new_vec_znx_from_bytes(&self, limbs: usize, bytes: &mut [u8]) -> VecZnxDft {
43 assert!(
44 bytes.len() >= self.bytes_of_vec_znx_dft(limbs),
45 "invalid bytes: bytes.len()={} < bytes_of_vec_znx_dft={}",
46 bytes.len(),
47 self.bytes_of_vec_znx_dft(limbs)
48 );
49 VecZnxDft::from_bytes(limbs, bytes)
50 }
51
52 /// Returns the minimum number of bytes necessary to allocate
53 /// a new [VecZnxDft] through [VecZnxDft::from_bytes].
54 pub fn bytes_of_vec_znx_dft(&self, limbs: usize) -> usize {
55 unsafe { bytes_of_vec_znx_dft(self.0, limbs as u64) as usize }
56 }
57
58 // b <- IDFT(a), uses a as scratch space.
59 pub fn vec_znx_idft_tmp_a(&self, b: &mut VecZnxBig, a: &mut VecZnxDft, a_limbs: usize) {
60 assert!(
61 b.limbs() >= a_limbs,
62 "invalid c_vector: b_vector.limbs()={} < a_limbs={}",
63 b.limbs(),
64 a_limbs
65 );
66 unsafe { vec_znx_dft::vec_znx_idft_tmp_a(self.0, b.0, b.limbs() as u64, a.0, a_limbs as u64) }
67 }
68
69 // Returns the size of the scratch space for [vec_znx_idft].
70 pub fn vec_znx_idft_tmp_bytes(&self) -> usize {
71 unsafe { vec_znx_dft::vec_znx_idft_tmp_bytes(self.0) as usize }
72 }
73
74 /// b <- DFT(a)
75 ///
76 /// # Panics
77 /// If b.limbs < a_limbs
78 pub fn vec_znx_dft(&self, b: &mut VecZnxDft, a: &VecZnx, a_limbs: usize) {
79 assert!(
80 b.limbs() >= a_limbs,
81 "invalid a_limbs: b.limbs()={} < a_limbs={}",
82 b.limbs(),
83 a_limbs
84 );
85 unsafe {
86 vec_znx_dft::vec_znx_dft(
87 self.0,
88 b.0,
89 b.limbs() as u64,
90 a.as_ptr(),
91 a_limbs as u64,
92 a.n as u64,
93 )
94 }
95 }
96
97 // b <- IDFT(a), scratch space size obtained with [vec_znx_idft_tmp_bytes].
98 pub fn vec_znx_idft(
99 &self,
100 b: &mut VecZnxBig,
101 a: &mut VecZnxDft,
102 a_limbs: usize,
103 tmp_bytes: &mut [u8],
104 ) {
105 assert!(
106 b.limbs() >= a_limbs,
107 "invalid c_vector: b.limbs()={} < a_limbs={}",
108 b.limbs(),
109 a_limbs
110 );
111 assert!(
112 a.limbs() >= a_limbs,
113 "invalid c_vector: a.limbs()={} < a_limbs={}",
114 a.limbs(),
115 a_limbs
116 );
117 assert!(
118 tmp_bytes.len() <= self.vec_znx_idft_tmp_bytes(),
119 "invalid tmp_bytes: tmp_bytes.len()={} < self.vec_znx_idft_tmp_bytes()={}",
120 tmp_bytes.len(),
121 self.vec_znx_idft_tmp_bytes()
122 );
123 unsafe {
124 vec_znx_dft::vec_znx_idft(
125 self.0,
126 b.0,
127 a.limbs() as u64,
128 a.0,
129 a_limbs as u64,
130 tmp_bytes.as_mut_ptr(),
131 )
132 }
133 }
134}