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}