qfall_math/integer/mat_poly_over_z/
coefficient_embedding.rs1use super::MatPolyOverZ;
13use crate::{
14 integer::{MatZ, PolyOverZ, Z},
15 traits::{
16 FromCoefficientEmbedding, GetCoefficient, IntoCoefficientEmbedding, MatrixDimensions,
17 MatrixGetEntry, MatrixSetEntry, SetCoefficient,
18 },
19};
20
21impl IntoCoefficientEmbedding<MatZ> for &MatPolyOverZ {
22 fn into_coefficient_embedding(self, size: impl Into<i64>) -> MatZ {
53 let size = size.into();
54
55 let num_rows = self.get_num_rows();
56 let num_columns = self.get_num_columns();
57
58 let mut out = MatZ::new(num_rows * size, num_columns);
59
60 for column in 0..num_columns {
61 for row in 0..num_rows {
62 let entry: PolyOverZ = unsafe { self.get_entry_unchecked(row, column) };
63 let length = entry.get_degree() + 1;
64 assert!(
65 size >= length,
66 "The matrix can not be embedded, as the length \
67 of a polynomial ({length}) is larger than \
68 the provided size ({size})."
69 );
70
71 for index in 0..size {
72 let coeff: Z = unsafe { entry.get_coeff_unchecked(index) };
73 unsafe { out.set_entry_unchecked(row * size + index, column, coeff) }
74 }
75 }
76 }
77
78 out
79 }
80}
81
82impl FromCoefficientEmbedding<(&MatZ, i64)> for MatPolyOverZ {
83 fn from_coefficient_embedding(embedding: (&MatZ, i64)) -> Self {
111 let degree = embedding.1;
112 let num_rows = embedding.0.get_num_rows();
113 let num_columns = embedding.0.get_num_columns();
114
115 assert_eq!(
116 num_rows % (degree + 1),
117 0,
118 "The provided degree of polynomials ({degree}) +1 must divide the number of rows of the embedding ({num_rows})."
119 );
120
121 let mut out = MatPolyOverZ::new(num_rows / (degree + 1), num_columns);
122
123 for row in 0..out.get_num_rows() {
124 for column in 0..num_columns {
125 let mut poly = PolyOverZ::default();
126 for index in 0..(degree + 1) {
127 let coeff: Z = unsafe {
128 embedding
129 .0
130 .get_entry_unchecked(row * (degree + 1) + index, column)
131 };
132 unsafe { poly.set_coeff_unchecked(index, coeff) };
133 }
134 unsafe { out.set_entry_unchecked(row, column, poly) };
135 }
136 }
137
138 out
139 }
140}
141
142#[cfg(test)]
143mod test_into_coefficient_embedding {
144 use crate::{
145 integer::{MatPolyOverZ, MatZ},
146 traits::{Concatenate, IntoCoefficientEmbedding},
147 };
148 use std::str::FromStr;
149
150 #[test]
152 fn standard_basis() {
153 let standard_basis =
154 MatPolyOverZ::from_str("[[1 1, 2 0 1, 3 0 0 1],[1 1, 2 0 1, 3 0 0 1]]").unwrap();
155
156 let basis = standard_basis.into_coefficient_embedding(3);
157
158 assert_eq!(
159 MatZ::identity(3, 3)
160 .concat_vertical(&MatZ::identity(3, 3))
161 .unwrap(),
162 basis
163 )
164 }
165
166 #[test]
168 fn standard_basis_vector() {
169 let standard_basis = MatPolyOverZ::from_str("[[1 1, 2 0 1]]").unwrap();
170
171 let basis = standard_basis.into_coefficient_embedding(3);
172
173 assert_eq!(MatZ::identity(3, 2), basis);
174 }
175
176 #[test]
178 fn large_entries() {
179 let poly = MatPolyOverZ::from_str(&format!(
180 "[[3 17 {} {}, 1 1],[1 1, 2 0 1]]",
181 i64::MAX,
182 i64::MIN
183 ))
184 .unwrap();
185
186 let matrix = poly.into_coefficient_embedding(3);
187
188 let cmp_matrix = MatZ::from_str(&format!("[[17, 1],[{}, 0],[{}, 0]]", i64::MAX, i64::MIN))
189 .unwrap()
190 .concat_vertical(&MatZ::identity(3, 2))
191 .unwrap();
192 assert_eq!(cmp_matrix, matrix);
193 }
194
195 #[test]
197 fn large_entries_vector() {
198 let poly =
199 MatPolyOverZ::from_str(&format!("[[3 17 {} {}, 1 1]]", i64::MAX, i64::MIN)).unwrap();
200
201 let matrix = poly.into_coefficient_embedding(3);
202
203 let cmp_matrix =
204 MatZ::from_str(&format!("[[17, 1],[{}, 0],[{}, 0]]", i64::MAX, i64::MIN)).unwrap();
205 assert_eq!(cmp_matrix, matrix);
206 }
207
208 #[test]
210 #[should_panic]
211 fn size_too_small() {
212 let poly = MatPolyOverZ::from_str("[[3 17 5 7, 2 0 1],[1 1, 1 1]]").unwrap();
213
214 let _ = poly.into_coefficient_embedding(2);
215 }
216
217 #[test]
219 #[should_panic]
220 fn size_too_small_vector() {
221 let poly = MatPolyOverZ::from_str("[[3 17 5 7, 2 0 1]]").unwrap();
222
223 let _ = poly.into_coefficient_embedding(2);
224 }
225}
226
227#[cfg(test)]
228mod test_from_coefficient_embedding {
229 use crate::{
230 integer::{MatPolyOverZ, MatZ},
231 traits::FromCoefficientEmbedding,
232 };
233 use std::str::FromStr;
234
235 #[test]
237 fn large_entries() {
238 let matrix =
239 MatZ::from_str(&format!("[[17, 0],[{}, -1],[{}, 0]]", i64::MAX, i64::MIN)).unwrap();
240
241 let poly = MatPolyOverZ::from_coefficient_embedding((&matrix, 0));
242
243 let cmp_poly = MatPolyOverZ::from_str(&format!(
244 "[[1 17, 0],[1 {}, 1 -1],[1 {}, 0]]",
245 i64::MAX,
246 i64::MIN
247 ))
248 .unwrap();
249 assert_eq!(cmp_poly, poly);
250 }
251
252 #[test]
254 fn large_entries_vector() {
255 let matrix =
256 MatZ::from_str(&format!("[[17, 0],[{}, -1],[{}, 0]]", i64::MAX, i64::MIN)).unwrap();
257
258 let poly = MatPolyOverZ::from_coefficient_embedding((&matrix, 2));
259
260 let cmp_poly =
261 MatPolyOverZ::from_str(&format!("[[3 17 {} {}, 2 0 -1]]", i64::MAX, i64::MIN))
262 .unwrap();
263 assert_eq!(cmp_poly, poly);
264 }
265
266 #[test]
269 #[should_panic]
270 fn degree_not_dividing() {
271 let matrix =
272 MatZ::from_str(&format!("[[17, 0],[{}, -1],[{}, 0]]", i64::MAX, i64::MIN)).unwrap();
273
274 let _ = MatPolyOverZ::from_coefficient_embedding((&matrix, 1));
275 }
276}