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}