bacon_sci/special/polynomial/
mod.rs1use crate::polynomial::Polynomial;
2use crate::roots::newton_polynomial;
3use nalgebra::ComplexField;
4use num_traits::FromPrimitive;
5
6pub fn legendre<N: ComplexField + FromPrimitive + Copy>(
30 n: u32,
31 tol: N::RealField,
32) -> Result<Polynomial<N>, String>
33where
34 <N as ComplexField>::RealField: FromPrimitive + Copy,
35{
36 if n == 0 {
37 let mut poly = polynomial![N::one()];
38 poly.set_tolerance(tol)?;
39 return Ok(poly);
40 }
41 if n == 1 {
42 let mut poly = polynomial![N::one(), N::zero()];
43 poly.set_tolerance(tol)?;
44 return Ok(poly);
45 }
46
47 let mut p_0 = polynomial![N::one()];
48 p_0.set_tolerance(tol)?;
49 let mut p_1 = polynomial![N::one(), N::zero()];
50 p_1.set_tolerance(tol)?;
51
52 for i in 1..n {
53 let mut p_next = polynomial![N::from_u32(2 * i + 1).unwrap(), N::zero()] * &p_1;
55 p_next.set_tolerance(tol)?;
56 p_next -= &p_0 * N::from_u32(i).unwrap();
57 p_next /= N::from_u32(i + 1).unwrap();
58 p_0 = p_1;
59 p_1 = p_next;
60 }
61
62 Ok(p_1)
63}
64
65pub fn legendre_zeros<N: ComplexField + FromPrimitive + Copy>(
72 n: u32,
73 tol: N::RealField,
74 poly_tol: N::RealField,
75 n_max: usize,
76) -> Result<Vec<N>, String>
77where
78 <N as ComplexField>::RealField: FromPrimitive + Copy,
79{
80 if n == 0 {
81 return Ok(vec![]);
82 }
83 if n == 1 {
84 return Ok(vec![N::zero()]);
85 }
86
87 let poly: Polynomial<N> = legendre(n, poly_tol)?;
88 Ok(poly
89 .roots(tol, n_max)?
90 .iter()
91 .map(|c| {
92 if c.re.abs() < tol {
93 N::zero()
94 } else {
95 N::from_real(c.re)
96 }
97 })
98 .collect())
99}
100
101pub fn hermite<N: ComplexField + FromPrimitive + Copy>(
126 n: u32,
127 tol: N::RealField,
128) -> Result<Polynomial<N>, String>
129where
130 <N as ComplexField>::RealField: FromPrimitive + Copy,
131{
132 if n == 0 {
133 let mut poly = polynomial![N::one()];
134 poly.set_tolerance(tol)?;
135 return Ok(poly);
136 }
137 if n == 1 {
138 let mut poly = polynomial![N::from_u8(2).unwrap(), N::zero()];
139 poly.set_tolerance(tol)?;
140 return Ok(poly);
141 }
142
143 let mut h_0 = polynomial![N::one()];
144 h_0.set_tolerance(tol)?;
145 let mut h_1 = polynomial![N::from_u8(2).unwrap(), N::zero()];
146 h_1.set_tolerance(tol)?;
147 let x_2 = h_1.clone();
148
149 for i in 1..n {
150 let next = &x_2 * &h_1 - (&h_0 * N::from_u32(2 * i).unwrap());
151 h_0 = h_1;
152 h_1 = next;
153 }
154
155 Ok(h_1)
156}
157
158pub fn hermite_zeros<N: ComplexField + FromPrimitive + Copy>(
167 n: u32,
168 tol: N::RealField,
169 poly_tol: N::RealField,
170 n_max: usize,
171) -> Result<Vec<N>, String>
172where
173 <N as ComplexField>::RealField: FromPrimitive + Copy,
174{
175 if n == 0 {
176 return Ok(vec![]);
177 }
178 if n == 1 {
179 return Ok(vec![N::zero()]);
180 }
181
182 let poly: Polynomial<N> = hermite(n, poly_tol)?;
183
184 let mut zeros = Vec::with_capacity(n as usize);
186 let special = N::from_f32(3.3721 / 6.0.cbrt()).unwrap();
187 let third = N::from_f32(1.0 / 3.0).unwrap().real();
188 for i in 1..=n {
189 let sqrt = N::from_u32(2 * i).unwrap().sqrt();
190 zeros.push(sqrt - special * sqrt.powf(-third));
191 }
192
193 let mut deflator = poly.clone();
195 let mut zs = Vec::with_capacity(zeros.len());
196 for z in &zeros {
197 let zero = newton_polynomial(*z, &deflator, tol, n_max)?;
198 let divisor = polynomial![N::one(), -zero];
199 let (quotient, _) = deflator.divide(&divisor)?;
200 let zero = newton_polynomial(zero, &poly, tol, n_max)?;
202 zs.push(zero);
203 deflator = quotient;
204 }
205 Ok(zs)
206}
207
208fn factorial<N: ComplexField + FromPrimitive>(k: u32) -> N {
209 let mut acc = N::one();
210 for i in 2..=k {
211 acc *= N::from_u32(i).unwrap();
212 }
213 acc
214}
215
216fn choose<N: ComplexField + FromPrimitive>(n: u32, k: u32) -> N {
217 let mut acc = N::one();
218 for i in n - k + 1..=n {
219 acc *= N::from_u32(i).unwrap();
220 }
221 for i in 2..=k {
222 acc /= N::from_u32(i).unwrap();
223 }
224 acc
225}
226
227pub fn laguerre<N: ComplexField + Copy + FromPrimitive>(
248 n: u32,
249 tol: N::RealField,
250) -> Result<Polynomial<N>, String>
251where
252 <N as ComplexField>::RealField: FromPrimitive + Copy,
253{
254 let mut coefficients = Vec::with_capacity(n as usize + 1);
255 for k in 0..=n {
256 coefficients.push(
257 choose::<N>(n, k) / factorial::<N>(k) * if k % 2 == 0 { N::one() } else { -N::one() },
258 );
259 }
260
261 let mut poly: Polynomial<N> = coefficients.iter().copied().collect();
262 poly.set_tolerance(tol)?;
263 Ok(poly)
264}
265
266pub fn laguerre_zeros<N: ComplexField + Copy + FromPrimitive>(
271 n: u32,
272 tol: N::RealField,
273 poly_tol: N::RealField,
274 n_max: usize,
275) -> Result<Vec<N>, String>
276where
277 <N as ComplexField>::RealField: FromPrimitive + Copy,
278{
279 if n == 0 {
280 return Ok(vec![]);
281 }
282 if n == 1 {
283 return Ok(vec![N::one()]);
284 }
285
286 let poly: Polynomial<N> = laguerre(n, poly_tol)?;
287
288 Ok(poly
289 .roots(tol, n_max)?
290 .iter()
291 .map(|c| {
292 if c.re.abs() < tol {
293 N::zero()
294 } else {
295 N::from_real(c.re)
296 }
297 })
298 .collect())
299}
300
301pub fn chebyshev<N: ComplexField + FromPrimitive + Copy>(
325 n: u32,
326 tol: N::RealField,
327) -> Result<Polynomial<N>, String>
328where
329 <N as ComplexField>::RealField: FromPrimitive + Copy,
330{
331 if n == 0 {
332 let mut poly = polynomial![N::one()];
333 poly.set_tolerance(tol)?;
334 return Ok(poly);
335 }
336 if n == 1 {
337 let mut poly = polynomial![N::one(), N::zero()];
338 poly.set_tolerance(tol)?;
339 return Ok(poly);
340 }
341
342 let half = chebyshev(n / 2, tol)?;
343 if n % 2 == 0 {
344 Ok(&half * &half * N::from_u8(2).unwrap() - polynomial![N::one()])
345 } else {
346 let other_half = chebyshev(n / 2 + 1, tol)?;
347 Ok(&half * &other_half * N::from_u8(2).unwrap() - polynomial![N::one(), N::zero()])
348 }
349}
350
351pub fn chebyshev_second<N: ComplexField + FromPrimitive + Copy>(
375 n: u32,
376 tol: N::RealField,
377) -> Result<Polynomial<N>, String>
378where
379 <N as ComplexField>::RealField: FromPrimitive + Copy,
380{
381 if n == 0 {
382 let mut poly = polynomial![N::one()];
383 poly.set_tolerance(tol)?;
384 return Ok(poly);
385 }
386 if n == 1 {
387 let mut poly = polynomial![N::from_u8(2).unwrap(), N::zero()];
388 poly.set_tolerance(tol)?;
389 return Ok(poly);
390 }
391
392 let mut t_0 = polynomial![N::one()];
393 t_0.set_tolerance(tol)?;
394 let mut t_1 = polynomial![N::from_u8(2).unwrap(), N::zero()];
395 t_1.set_tolerance(tol)?;
396 let double = t_1.clone();
397
398 for _ in 1..n {
399 let next = &double * &t_1 - &t_0;
400 t_0 = t_1;
401 t_1 = next;
402 }
403 Ok(t_1)
404}