rust_poly/poly/
calculus.rs1use itertools::chain;
2use num::{Complex, Zero};
3
4use crate::{Poly, RealScalar};
5
6impl<T: RealScalar> Poly<T> {
7 #[must_use]
12 pub fn diff(self) -> Self {
13 debug_assert!(self.is_normalized());
14
15 if self.degree_raw() == 0 {
17 return Self::from_real_slice(&[T::zero()]);
18 }
19
20 let coeffs: Vec<_> = (0..self.len())
21 .map(|x| T::from_usize(x).expect("overflow"))
22 .map(|x| Complex::new(x, T::zero()))
23 .zip(self.0.iter())
24 .map(|(n, c)| n * c)
25 .skip(1) .collect();
27 Self::from_complex_vec(coeffs).normalize()
28 }
29
30 #[must_use]
35 pub fn integral(self) -> Self {
36 debug_assert!(self.is_normalized());
37
38 let coeffs: Vec<_> = chain(
39 [Complex::<T>::zero()],
40 (1..=self.len())
41 .map(|x| T::from_usize(x).expect("overflow"))
42 .map(|x| Complex::new(x, T::zero()))
43 .zip(self.0.iter())
44 .map(|(n, c)| c / n),
45 )
46 .collect();
47 Self::from_complex_vec(coeffs).normalize()
48 }
49}
50
51#[cfg(test)]
52mod test {
53
54 #[test]
55 fn diff() {
56 let p = poly![1.0, 2.0, 3.0];
57 assert_eq!(p.diff(), poly![2.0, 6.0]);
58 }
59
60 #[test]
62 fn diff1() {
63 let one = poly![1.0];
64 assert_eq!(one.diff().degree(), -1);
65 }
66
67 #[test]
68 fn integral() {
69 let p = poly![1.0, 2.0, 3.0];
70 assert_eq!(p.integral(), poly![0.0, 1.0, 1.0, 1.0]);
71 }
72
73 #[test]
74 fn integral_diff() {
75 let p = poly![1.0, 2.0, 3.0];
76 let q = p.clone().integral().diff();
77 assert_eq!(p, q);
78 }
79}