rust_poly/
lib.rs

1// TODO(version: v1.0.0): license/author header project-wide, see MIT guidelines
2
3// lint groups
4#![warn(clippy::pedantic)]
5#![warn(clippy::cargo)]
6// restriction lints
7#![warn(clippy::dbg_macro)]
8#![warn(clippy::print_stdout)]
9#![warn(clippy::print_stderr)]
10#![warn(clippy::undocumented_unsafe_blocks)]
11#![warn(clippy::unnecessary_safety_doc)]
12#![warn(clippy::unwrap_used)]
13
14pub use num;
15
16/// A more convenient way to write `Complex::new(...)`.
17///
18/// # Examples
19///
20/// ```
21/// use rust_poly::complex;
22/// use num::Complex;
23///
24/// let c1: Complex<f32> = complex!();
25/// let c2 = Complex::new(0.0, 0.0);
26/// let c3 = complex!(1.0f32, 2.0);
27/// let c4 = Complex::new(1.0, 2.0);
28///
29/// assert_eq!(c1, c2);
30/// assert_eq!(c3, c4);
31/// assert_eq!(complex!(4.20), complex!(4.20, 0.0));
32/// ```
33#[macro_export]
34macro_rules! complex {
35    () => {{
36        <$crate::num::Complex<_> as $crate::num::Zero>::zero()
37    }};
38    ($re:expr) => {{
39        $crate::num::Complex::new(
40            $re,
41            <$crate::num::Complex<_> as $crate::num::Zero>::zero().im,
42        )
43    }};
44    ($re:expr, $im: expr) => {{
45        $crate::num::Complex::new($re, $im)
46    }};
47}
48
49/// A more convenient way of writing `Poly::new(&[Complex::new(...)...])`
50///
51/// It takes ownership of its arguments.
52///
53/// It can take a list of `Scalar` or `Complex<Scalar>`. If left empty, it is
54/// equivalent to `Poly::zero()`.
55///
56/// # Examples
57///
58/// Basic syntax
59/// ```
60/// use rust_poly::{poly, Poly};
61/// use num::Zero;
62/// use num::Complex;
63///
64/// let p1: Poly<f32> = poly![];
65/// let p2 = poly![1.0f32, 2.0, 3.0];
66/// let p3 = Poly::from_complex_vec(vec![Complex::new(1.0, 0.0), Complex::new(2.0, 0.0), Complex::new(3.0, 0.0)]);
67///
68/// assert_eq!(p1, Poly::zero());
69/// assert_eq!(p2, p3);
70/// ```
71///
72/// Similarly to `vec!`, you can initialize a large polynomial where all coefficients
73/// are equal like so:
74/// ```
75/// # use rust_poly::{poly, Poly};
76/// use num::Complex;
77///
78/// let p1 = poly![2.0; 4];
79/// let p2 = poly![(2.0, 0.0); 4];
80/// let p3 = poly![2.0, 2.0, 2.0, 2.0];
81/// assert_eq!(p1, p2);
82/// assert_eq!(p2, p3);
83/// ```
84#[macro_export]
85macro_rules! poly {
86    () => {{
87        <$crate::Poly<_> as $crate::num::Zero>::zero()
88    }};
89    (($re:expr, $im:expr); $n:expr) => {{
90        $crate::Poly::from_complex_vec(vec![$crate::complex!($re, $im); $n])
91    }};
92    ($elem:expr; $n:expr) => {{
93        $crate::Poly::from_real_vec(vec![$elem; $n])
94    }};
95    ($(($re:expr, $im:expr)),+ $(,)?) => {{
96        $crate::Poly::from_complex_vec(vec![$($crate::complex!($re, $im)),*])
97    }};
98    ($($elems:expr),+ $(,)?) => {{
99        $crate::Poly::from_real_vec(vec![$($elems),*])
100    }};
101}
102
103mod scalar;
104pub use scalar::RealScalar;
105
106mod poly;
107pub use poly::{roots, Poly};
108
109pub(crate) mod util;
110pub use util::__testing;
111
112pub(crate) mod base;
113
114pub type Poly32 = Poly<f32>;
115pub type Poly64 = Poly<f64>;
116
117#[cfg(test)]
118mod tests {
119    use super::*;
120    use num::{Complex, One, Zero};
121
122    #[test]
123    fn macro_complex() {
124        assert_eq!(complex!(), Complex::<f64>::zero());
125        assert_eq!(complex!(1.0, 2.0), Complex::<f64>::new(1.0, 2.0));
126    }
127
128    #[test]
129    fn macro_poly() {
130        assert_eq!(poly!(), Poly::<f64>::zero());
131        assert_eq!(poly!(1.0), Poly::<f64>::one());
132        assert_eq!(
133            poly!(1.0, 2.0, 3.0),
134            Poly::<f64>::new(&[
135                Complex::new(1.0, 0.0),
136                Complex::new(2.0, 0.0),
137                Complex::new(3.0, 0.0),
138            ])
139        );
140        assert_eq!(poly!((1.0, 0.0)), Poly::<f64>::one());
141        assert_eq!(
142            poly!((1.0, 1.0), (2.0, 2.0), (3.0, 3.0)),
143            Poly::<f64>::new(&[
144                Complex::new(1.0, 1.0),
145                Complex::new(2.0, 2.0),
146                Complex::new(3.0, 3.0)
147            ])
148        );
149        assert_eq!(
150            poly!(2.0; 3),
151            Poly::<f64>::new(&[
152                Complex::new(2.0, 0.0),
153                Complex::new(2.0, 0.0),
154                Complex::new(2.0, 0.0)
155            ])
156        );
157        assert_eq!(
158            poly!((1.0, -1.0); 3),
159            Poly::<f64>::new(&[
160                Complex::new(1.0, -1.0),
161                Complex::new(1.0, -1.0),
162                Complex::new(1.0, -1.0)
163            ])
164        );
165    }
166
167    #[test]
168    fn poly_new() {
169        // trivial, but here for completeness
170        Poly::new(&[Complex::new(2.0, -2.0)]);
171    }
172
173    #[test]
174    fn poly_from_complex_slice() {
175        let p = Poly::from_complex_slice(&[Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)]);
176        let e = poly!((1.0, 2.0), (3.0, 4.0));
177        assert_eq!(p, e);
178    }
179
180    // TODO: test the rest of the "boring" functions
181
182    #[test]
183    fn poly_line() {
184        let p = Poly::<f64>::line(Complex::<f64>::new(1.0, 0.0), Complex::<f64>::new(2.0, 0.0));
185        let e = poly!(1.0, 2.0);
186        assert_eq!(p, e);
187    }
188
189    #[test]
190    fn poly_term() {
191        let p = Poly64::term(complex!(2.0), 2);
192        let e = poly!(0.0, 0.0, 2.0);
193        assert_eq!(p, e);
194    }
195
196    #[test]
197    fn poly_bessel() {
198        assert_eq!(Poly64::bessel(0).unwrap(), poly![1.0]);
199        assert_eq!(Poly64::bessel(1).unwrap(), poly![1.0, 1.0]);
200        assert_eq!(Poly64::bessel(2).unwrap(), poly![1.0, 3.0, 3.0]);
201        assert_eq!(Poly64::bessel(3).unwrap(), poly![1.0, 6.0, 15.0, 15.0]);
202    }
203
204    #[test]
205    fn poly_reverse_bessel() {
206        assert_eq!(Poly64::reverse_bessel(0).unwrap(), poly![1.0]);
207        assert_eq!(Poly64::reverse_bessel(1).unwrap(), poly![1.0, 1.0]);
208        assert_eq!(Poly64::reverse_bessel(2).unwrap(), poly![3.0, 3.0, 1.0]);
209        assert_eq!(
210            Poly64::reverse_bessel(3).unwrap(),
211            poly![15.0, 15.0, 6.0, 1.0]
212        );
213    }
214}