qfall_math/integer/poly_over_z/set.rs
1// Copyright © 2023 Marvin Beckmann
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Implementations to manipulate a [`PolyOverZ`] polynomial.
10
11use super::PolyOverZ;
12use crate::{integer::Z, traits::SetCoefficient};
13use flint_sys::fmpz_poly::fmpz_poly_set_coeff_fmpz;
14
15impl<Integer: Into<Z>> SetCoefficient<Integer> for PolyOverZ {
16 /// Sets the coefficient of a polynomial [`PolyOverZ`].
17 /// We advise to use small coefficients, since already 2^32 coefficients take space
18 /// of roughly 34 GB. If not careful, be prepared that memory problems can occur, if
19 /// the index is very high.
20 ///
21 /// Parameters:
22 /// - `index`: the index of the coefficient to set (has to be positive)
23 /// - `value`: the new value the index should have
24 ///
25 /// # Examples
26 /// ```
27 /// use qfall_math::integer::PolyOverZ;
28 /// use qfall_math::integer::Z;
29 /// use qfall_math::traits::*;
30 /// use std::str::FromStr;
31 ///
32 /// let mut poly = PolyOverZ::from_str("4 0 1 2 3").unwrap();
33 ///
34 /// assert!(poly.set_coeff(4, 1000).is_ok());
35 /// unsafe{ poly.set_coeff_unchecked(5, -1000) };
36 /// ```
37 ///
38 /// # Safety
39 /// To use this function safely, make sure that the selected index
40 /// is greater or equal than `0` and that the provided value has
41 /// the same base so that they have a matching base.
42 unsafe fn set_coeff_unchecked(&mut self, index: i64, value: Integer) {
43 let value = value.into();
44
45 unsafe {
46 fmpz_poly_set_coeff_fmpz(&mut self.poly, index, &value.value);
47 };
48 }
49}
50
51#[cfg(test)]
52mod test_set_coeff {
53 use crate::{
54 integer::{PolyOverZ, Z},
55 traits::SetCoefficient,
56 };
57 use std::str::FromStr;
58
59 /// Ensure that the negative indices return an error.
60 #[test]
61 fn set_negative_index() {
62 let mut poly = PolyOverZ::from_str("2 1 1").unwrap();
63
64 assert!(poly.set_coeff(i64::MIN, 2).is_err());
65 assert!(poly.set_coeff(i32::MIN, 2).is_err());
66 assert!(poly.set_coeff(i16::MIN, 2).is_err());
67 assert!(poly.set_coeff(i8::MIN, 2).is_err());
68 }
69
70 /// Ensure that large coefficients work.
71 #[test]
72 fn set_coeff_large() {
73 let mut poly = PolyOverZ::from_str("2 1 1").unwrap();
74
75 assert!(poly.set_coeff(2, i32::MAX).is_ok());
76 assert!(poly.set_coeff(2, i64::MAX).is_ok());
77 }
78
79 /// Ensure that the max of [`u8`] and [`u16`] works as an index.
80 #[test]
81 fn set_index_large() {
82 let mut poly = PolyOverZ::from_str("2 1 1").unwrap();
83
84 assert!(poly.set_coeff(u8::MAX, 2).is_ok());
85 assert!(poly.set_coeff(u16::MAX, 2).is_ok());
86 }
87
88 /// Ensure that a general case is working.
89 #[test]
90 fn set_coeff_working() {
91 let mut poly = PolyOverZ::from_str("4 0 1 2 3").unwrap();
92 let value = 10000;
93
94 poly.set_coeff(0, value).unwrap();
95 poly.set_coeff(5, value).unwrap();
96 assert_eq!(PolyOverZ::from_str("6 10000 1 2 3 0 10000").unwrap(), poly);
97 }
98
99 /// Ensure that the correct coefficient is set and all others are set to `0`.
100 #[test]
101 fn set_coeff_rest_zero() {
102 let mut poly = PolyOverZ::default();
103
104 poly.set_coeff(4, -10).unwrap();
105 assert_eq!(PolyOverZ::from_str("5 0 0 0 0 -10").unwrap(), poly);
106 }
107
108 /// Ensure that setting with a z works.
109 #[test]
110 fn set_coeff_z() {
111 let mut poly = PolyOverZ::default();
112
113 poly.set_coeff(4, Z::from(123)).unwrap();
114 assert_eq!(PolyOverZ::from_str("5 0 0 0 0 123").unwrap(), poly);
115 }
116}