qfall_math/integer/poly_over_z/
get.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 get information about a [`PolyOverZ`].
10
11use super::PolyOverZ;
12use crate::{integer::Z, traits::GetCoefficient};
13use flint_sys::fmpz_poly::{fmpz_poly_degree, fmpz_poly_get_coeff_fmpz};
14
15impl GetCoefficient<Z> for PolyOverZ {
16    /// Returns the coefficient of a polynomial [`PolyOverZ`] as a [`Z`].
17    ///
18    /// If an index is provided which exceeds the highest set coefficient, `0` is returned.
19    ///
20    /// Parameters:
21    /// - `index`: the index of the coefficient to get (has to be positive)
22    ///
23    /// Returns the coefficient as a [`Z`], or a [`MathError`](crate::error::MathError) if the provided index
24    /// is negative and therefore invalid, or it does not fit into an [`i64`].
25    ///
26    /// # Examples
27    /// ```
28    /// use qfall_math::integer::{Z, PolyOverZ};
29    /// use std::str::FromStr;
30    /// use qfall_math::traits::*;
31    ///
32    /// let poly = PolyOverZ::from_str("4  0 1 2 3").unwrap();
33    ///
34    /// let coeff_0 = poly.get_coeff(0).unwrap();
35    /// let coeff_1 = unsafe{ poly.get_coeff_unchecked(1) };
36    /// let coeff_4 = poly.get_coeff(4).unwrap();
37    ///
38    /// assert_eq!(Z::ZERO, coeff_0);
39    /// assert_eq!(Z::ONE, coeff_1);
40    /// assert_eq!(Z::ZERO, coeff_4);
41    /// ```
42    ///
43    /// # Safety
44    /// To use this function safely, make sure that the selected index
45    /// is greater or equal than `0`.
46    unsafe fn get_coeff_unchecked(&self, index: i64) -> Z {
47        let mut out = Z::default();
48        unsafe { fmpz_poly_get_coeff_fmpz(&mut out.value, &self.poly, index) }
49        out
50    }
51}
52
53impl PolyOverZ {
54    /// Returns the degree of a polynomial [`PolyOverZ`] as a [`i64`].
55    /// The zero polynomial has degree `-1`.
56    ///
57    /// # Examples
58    /// ```
59    /// use qfall_math::integer::PolyOverZ;
60    /// use std::str::FromStr;
61    ///
62    /// let poly = PolyOverZ::from_str("4  0 1 2 3").unwrap();
63    ///
64    /// let degree = poly.get_degree();
65    ///
66    /// assert_eq!(3, degree);
67    /// ```
68    pub fn get_degree(&self) -> i64 {
69        unsafe { fmpz_poly_degree(&self.poly) }
70    }
71}
72
73#[cfg(test)]
74mod test_get_coeff {
75    use crate::{
76        integer::{PolyOverZ, Z},
77        traits::GetCoefficient,
78    };
79    use std::str::FromStr;
80
81    /// Ensure that 0 is returned if the provided index is not yet set.
82    #[test]
83    fn index_out_of_range() {
84        let poly = PolyOverZ::from_str("4  0 1 2 3").unwrap();
85
86        let zero_coeff = poly.get_coeff(4).unwrap();
87
88        assert_eq!(Z::ZERO, zero_coeff);
89    }
90
91    /// Tests if negative coefficients are returned correctly.
92    #[test]
93    fn negative_coeff() {
94        let poly = PolyOverZ::from_str("4  0 1 2 -3").unwrap();
95
96        let coeff = poly.get_coeff(3).unwrap();
97
98        assert_eq!(Z::from(-3), coeff);
99    }
100
101    /// Tests if positive coefficients are returned correctly.
102    #[test]
103    fn positive_coeff() {
104        let poly = PolyOverZ::from_str("4  0 1 2 -3").unwrap();
105
106        let coeff = poly.get_coeff(2).unwrap();
107
108        assert_eq!(Z::from(2), coeff);
109    }
110
111    /// Tests if large coefficients are returned correctly.
112    #[test]
113    fn large_coeff() {
114        let large_string = format!("2  {} {}", u64::MAX, i64::MIN);
115        let poly = PolyOverZ::from_str(&large_string).unwrap();
116
117        assert_eq!(Z::from(u64::MAX), poly.get_coeff(0).unwrap());
118        assert_eq!(Z::from(i64::MIN), poly.get_coeff(1).unwrap());
119    }
120
121    /// Tests if large negative coefficients are returned correctly.
122    #[test]
123    fn large_coeff_neg() {
124        let large_string = format!("2  -{} {}", u64::MAX, i64::MIN);
125        let poly = PolyOverZ::from_str(&large_string).unwrap();
126
127        assert_eq!(
128            Z::from_str(&format!("-{}", u64::MAX)).unwrap(),
129            poly.get_coeff(0).unwrap()
130        );
131        assert_eq!(Z::from(i64::MIN), poly.get_coeff(1).unwrap());
132    }
133
134    /// Tests if negative index yields an error.
135    #[test]
136    fn negative_index_error() {
137        let poly = PolyOverZ::from_str("4  0 1 2 -3").unwrap();
138
139        let coeff = poly.get_coeff(-1);
140
141        assert!(coeff.is_err());
142    }
143}
144
145#[cfg(test)]
146mod test_get_degree {
147    use crate::integer::PolyOverZ;
148    use std::str::FromStr;
149
150    /// Ensure that degree is working.
151    #[test]
152    fn degree() {
153        let poly = PolyOverZ::from_str("4  0 1 2 3").unwrap();
154
155        let deg = poly.get_degree();
156
157        assert_eq!(3, deg);
158    }
159
160    /// Ensure that degree is working for constant polynomials.
161    #[test]
162    fn degree_constant() {
163        let poly_1 = PolyOverZ::from(1);
164        let poly_2 = PolyOverZ::default();
165
166        let deg_1 = poly_1.get_degree();
167        let deg_2 = poly_2.get_degree();
168
169        assert_eq!(0, deg_1);
170        assert_eq!(-1, deg_2);
171    }
172
173    /// Ensure that degree is working for polynomials with leading 0 coefficients.
174    #[test]
175    fn degree_leading_zeros() {
176        let poly = PolyOverZ::from_str("4  1 0 0 0").unwrap();
177
178        let deg = poly.get_degree();
179
180        assert_eq!(0, deg);
181    }
182}