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_dft_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 {
67 vec_znx_dft::vec_znx_idft_tmp_a(self.0, b.0, b.limbs() as u64, a.0, a_limbs as u64)
68 }
69 }
70
71 // Returns the size of the scratch space for [vec_znx_idft].
72 pub fn vec_znx_idft_tmp_bytes(&self) -> usize {
73 unsafe { vec_znx_dft::vec_znx_idft_tmp_bytes(self.0) as usize }
74 }
75
76 /// b <- DFT(a)
77 ///
78 /// # Panics
79 /// If b.limbs < a_limbs
80 pub fn vec_znx_dft(&self, b: &mut VecZnxDft, a: &VecZnx, a_limbs: usize) {
81 assert!(
82 b.limbs() >= a_limbs,
83 "invalid a_limbs: b.limbs()={} < a_limbs={}",
84 b.limbs(),
85 a_limbs
86 );
87 unsafe {
88 vec_znx_dft::vec_znx_dft(
89 self.0,
90 b.0,
91 b.limbs() as u64,
92 a.as_ptr(),
93 a_limbs as u64,
94 a.n as u64,
95 )
96 }
97 }
98
99 // b <- IDFT(a), scratch space size obtained with [vec_znx_idft_tmp_bytes].
100 pub fn vec_znx_idft(
101 &self,
102 b: &mut VecZnxBig,
103 a: &mut VecZnxDft,
104 a_limbs: usize,
105 tmp_bytes: &mut [u8],
106 ) {
107 assert!(
108 b.limbs() >= a_limbs,
109 "invalid c_vector: b.limbs()={} < a_limbs={}",
110 b.limbs(),
111 a_limbs
112 );
113 assert!(
114 a.limbs() >= a_limbs,
115 "invalid c_vector: a.limbs()={} < a_limbs={}",
116 a.limbs(),
117 a_limbs
118 );
119 assert!(
120 tmp_bytes.len() <= self.vec_znx_idft_tmp_bytes(),
121 "invalid tmp_bytes: tmp_bytes.len()={} < self.vec_znx_idft_tmp_bytes()={}",
122 tmp_bytes.len(),
123 self.vec_znx_idft_tmp_bytes()
124 );
125 unsafe {
126 vec_znx_dft::vec_znx_idft(
127 self.0,
128 b.0,
129 a.limbs() as u64,
130 a.0,
131 a_limbs as u64,
132 tmp_bytes.as_mut_ptr(),
133 )
134 }
135 }
136}