qfall_math/integer_mod_q/polynomial_ring_zq/
set.rs1use super::PolynomialRingZq;
12use crate::{
13 integer::Z,
14 integer_mod_q::{Modulus, ModulusPolynomialRingZq, Zq},
15 macros::for_others::implement_for_owned,
16 traits::SetCoefficient,
17};
18use flint3_sys::fmpz_poly_set_coeff_fmpz;
19
20impl<Integer: Into<Z>> SetCoefficient<Integer> for PolynomialRingZq {
21 unsafe fn set_coeff_unchecked(&mut self, index: i64, value: Integer) {
50 let value = value.into();
51
52 unsafe {
53 fmpz_poly_set_coeff_fmpz(&mut self.poly.poly, index, &value.value);
54 };
55 self.reduce();
56 }
57}
58
59impl SetCoefficient<&Zq> for PolynomialRingZq {
60 unsafe fn set_coeff_unchecked(&mut self, index: i64, value: &Zq) {
93 unsafe { self.set_coeff_unchecked(index, &value.value) };
94 }
95}
96
97implement_for_owned!(Zq, PolynomialRingZq, SetCoefficient);
98
99impl PolynomialRingZq {
100 pub fn change_modulus(&mut self, modulus: impl Into<ModulusPolynomialRingZq>) {
126 self.modulus = modulus.into();
127 self.reduce();
128 }
129
130 pub fn change_q(&mut self, q: impl Into<Modulus>) {
152 self.modulus.change_q(q);
153 self.reduce();
154 }
155}
156
157#[cfg(test)]
158mod test_set_coeff {
159 use crate::{
160 integer::{PolyOverZ, Z},
161 integer_mod_q::{ModulusPolynomialRingZq, PolynomialRingZq, Zq},
162 traits::SetCoefficient,
163 };
164 use std::str::FromStr;
165
166 #[test]
168 fn availability() {
169 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
170 let poly = PolyOverZ::from_str("3 0 1 1").unwrap();
171 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
172
173 poly_ring.set_coeff(1, 3u64).unwrap();
174 poly_ring.set_coeff(1, 3u32).unwrap();
175 poly_ring.set_coeff(1, 3u16).unwrap();
176 poly_ring.set_coeff(1, 3u8).unwrap();
177 poly_ring.set_coeff(1, 3i64).unwrap();
178 poly_ring.set_coeff(1, 3i32).unwrap();
179 poly_ring.set_coeff(1, 3i16).unwrap();
180 poly_ring.set_coeff(1, 3i8).unwrap();
181 poly_ring.set_coeff(1, Z::from(3)).unwrap();
182 poly_ring.set_coeff(1, &Z::from(3)).unwrap();
183 poly_ring.set_coeff(1, &Zq::from((3, 17))).unwrap();
184 }
185
186 #[test]
188 fn set_coeff_large() {
189 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
190 let poly = PolyOverZ::from_str("3 0 1 1").unwrap();
191 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
192
193 assert!(poly_ring.set_coeff(2, i32::MAX).is_ok());
194 assert!(poly_ring.set_coeff(2, i64::MAX).is_ok());
195 }
196
197 #[test]
199 fn set_index_large() {
200 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
201 let poly = PolyOverZ::from_str("3 0 1 1").unwrap();
202 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
203
204 assert!(poly_ring.set_coeff(u8::MAX, 2).is_ok());
205 assert!(poly_ring.set_coeff(u16::MAX, 2).is_ok());
206 }
207
208 #[test]
210 fn set_coeff_working() {
211 let modulus = ModulusPolynomialRingZq::from_str("5 1 0 0 1 1 mod 17").unwrap();
212 let poly = PolyOverZ::from_str("3 0 2 1").unwrap();
213 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
214 let value = 10000;
215
216 poly_ring.set_coeff(0, value).unwrap();
217 poly_ring.set_coeff(2, value).unwrap();
218
219 let cmp_poly = PolyOverZ::from_str("3 10000 2 10000").unwrap();
220 let cmp_poly_ring = PolynomialRingZq::from((&cmp_poly, &modulus));
221 assert_eq!(cmp_poly_ring, poly_ring);
222 }
223
224 #[test]
226 fn set_reduce() {
227 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
228 let poly = PolyOverZ::from(1);
229 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
230
231 poly_ring.set_coeff(3, 1).unwrap();
232
233 let cmp_poly = PolyOverZ::from(0);
234 let cmp_poly_ring = PolynomialRingZq::from((&cmp_poly, &modulus));
235 assert_eq!(cmp_poly_ring, poly_ring);
236 }
237
238 #[test]
240 fn set_coeff_rest_zero() {
241 let modulus = ModulusPolynomialRingZq::from_str("7 10 12 0 0 10 0 1 mod 17").unwrap();
242 let poly = PolyOverZ::from_str("2 0 2").unwrap();
243 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
244
245 poly_ring.set_coeff(5, 10).unwrap();
246
247 let cmp_poly = PolyOverZ::from_str("6 0 2 0 0 0 10").unwrap();
248 let cmp_poly_ring = PolynomialRingZq::from((&cmp_poly, &modulus));
249 assert_eq!(cmp_poly_ring, poly_ring);
250 }
251
252 #[test]
254 fn set_negative_index() {
255 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
256 let poly = PolyOverZ::from_str("3 0 1 1").unwrap();
257 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
258
259 assert!(poly_ring.set_coeff(-1, 2).is_err());
260 assert!(poly_ring.set_coeff(i64::MIN, 2).is_err());
261 assert!(poly_ring.set_coeff(i32::MIN, 2).is_err());
262 assert!(poly_ring.set_coeff(i16::MIN, 2).is_err());
263 assert!(poly_ring.set_coeff(i8::MIN, 2).is_err());
264 }
265
266 #[test]
268 fn different_base() {
269 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
270 let poly = PolyOverZ::from_str("3 0 1 1").unwrap();
271 let mut poly_ring = PolynomialRingZq::from((&poly, &modulus));
272 let value = Zq::from((13, 18));
273
274 assert!(poly_ring.set_coeff(1, &value).is_err());
275 }
276}
277
278#[cfg(test)]
279mod test_change_modulus {
280 use super::PolynomialRingZq;
281 use crate::integer_mod_q::ModulusPolynomialRingZq;
282 use std::str::FromStr;
283
284 #[test]
286 fn modulus_correct() {
287 let mut matrix = PolynomialRingZq::from_str("1 6 / 4 1 0 0 1 mod 7").unwrap();
288 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 5").unwrap();
289
290 matrix.change_modulus(&modulus);
291
292 assert_eq!("1 1 / 4 1 0 0 1 mod 5", matrix.to_string());
293 }
294
295 #[test]
297 fn big_modulus_correct() {
298 let mut matrix =
299 PolynomialRingZq::from_str(&format!("1 6 / 4 1 0 0 1 mod {}", i64::MAX)).unwrap();
300 let modulus =
301 ModulusPolynomialRingZq::from_str(&format!("4 1 0 0 1 mod {}", u64::MAX)).unwrap();
302
303 matrix.change_modulus(&modulus);
304
305 assert_eq!(
306 format!("1 6 / 4 1 0 0 1 mod {}", u64::MAX),
307 matrix.to_string()
308 );
309 }
310
311 #[test]
313 fn reduced_correct() {
314 let mut matrix =
315 PolynomialRingZq::from_str("4 1 0 0 1 / 8 1 0 0 0 0 0 0 1 mod 7").unwrap();
316 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 2").unwrap();
317
318 matrix.change_modulus(&modulus);
319
320 assert_eq!("0 / 4 1 0 0 1 mod 2", matrix.to_string());
321 }
322}
323
324#[cfg(test)]
325mod test_change_q {
326 use super::PolynomialRingZq;
327 use std::str::FromStr;
328
329 #[test]
331 fn q_correct() {
332 let mut matrix = PolynomialRingZq::from_str("1 6 / 4 1 0 0 1 mod 7").unwrap();
333
334 matrix.change_q(8);
335
336 assert_eq!("1 6 / 4 1 0 0 1 mod 8", matrix.to_string());
337 }
338
339 #[test]
341 fn big_q_correct() {
342 let mut matrix =
343 PolynomialRingZq::from_str(&format!("1 6 / 4 1 0 0 1 mod {}", i64::MAX)).unwrap();
344
345 matrix.change_q(u64::MAX);
346
347 assert_eq!(
348 format!("1 6 / 4 1 0 0 1 mod {}", u64::MAX),
349 matrix.to_string()
350 );
351 }
352
353 #[test]
355 fn reduced_correct() {
356 let mut matrix = PolynomialRingZq::from_str("2 5 4 / 4 1 0 0 1 mod 7").unwrap();
357
358 matrix.change_q(2);
359
360 assert_eq!("1 1 / 4 1 0 0 1 mod 2", matrix.to_string());
361 }
362}