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