qualia_core_db/solvers/special_functions/
orthogonal.rs1pub fn legendre(n: u32, x: f64) -> f64 {
6 if n == 0 {
7 return 1.0;
8 }
9 let (mut p0, mut p1) = (1.0, x);
10 for k in 1..n {
11 let kf = k as f64;
12 let p2 = ((2.0 * kf + 1.0) * x * p1 - kf * p0) / (kf + 1.0);
13 p0 = p1;
14 p1 = p2;
15 }
16 p1
17}
18
19pub fn chebyshev_t(n: u32, x: f64) -> f64 {
21 if n == 0 {
22 return 1.0;
23 }
24 let (mut t0, mut t1) = (1.0, x);
25 for _ in 1..n {
26 let t2 = 2.0 * x * t1 - t0;
27 t0 = t1;
28 t1 = t2;
29 }
30 t1
31}
32
33pub fn chebyshev_u(n: u32, x: f64) -> f64 {
36 if n == 0 {
37 return 1.0;
38 }
39 let (mut u0, mut u1) = (1.0, 2.0 * x);
40 for _ in 1..n {
41 let u2 = 2.0 * x * u1 - u0;
42 u0 = u1;
43 u1 = u2;
44 }
45 u1
46}
47
48pub fn hermite(n: u32, x: f64) -> f64 {
51 if n == 0 {
52 return 1.0;
53 }
54 let (mut h0, mut h1) = (1.0, 2.0 * x);
55 for k in 1..n {
56 let h2 = 2.0 * x * h1 - 2.0 * k as f64 * h0;
57 h0 = h1;
58 h1 = h2;
59 }
60 h1
61}
62
63pub fn laguerre(n: u32, x: f64) -> f64 {
66 if n == 0 {
67 return 1.0;
68 }
69 let (mut l0, mut l1) = (1.0, 1.0 - x);
70 for k in 1..n {
71 let kf = k as f64;
72 let l2 = ((2.0 * kf + 1.0 - x) * l1 - kf * l0) / (kf + 1.0);
73 l0 = l1;
74 l1 = l2;
75 }
76 l1
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 const EPS: f64 = 1e-12;
83
84 #[test]
85 fn legendre_known() {
86 assert!((legendre(2, 0.5) - (3.0 * 0.25 - 1.0) / 2.0).abs() < EPS);
88 assert!((legendre(3, 0.5) - (5.0 * 0.125 - 1.5) / 2.0).abs() < EPS);
89 assert!((legendre(5, 1.0) - 1.0).abs() < EPS); assert!((legendre(0, 7.0) - 1.0).abs() < EPS);
91 }
92
93 #[test]
94 fn chebyshev_known() {
95 let theta = 0.7_f64;
97 for n in 0..6u32 {
98 assert!((chebyshev_t(n, theta.cos()) - (n as f64 * theta).cos()).abs() < 1e-10);
99 }
100 assert!((chebyshev_t(2, 0.3) - (2.0 * 0.09 - 1.0)).abs() < EPS);
102 assert!((chebyshev_u(2, 0.3) - (4.0 * 0.09 - 1.0)).abs() < EPS);
103 }
104
105 #[test]
106 fn hermite_known() {
107 assert!((hermite(2, 1.5) - (4.0 * 2.25 - 2.0)).abs() < EPS);
109 assert!((hermite(3, 1.5) - (8.0 * 3.375 - 18.0)).abs() < 1e-10);
110 }
111
112 #[test]
113 fn laguerre_known() {
114 assert!((laguerre(2, 1.0) - (1.0 - 4.0 + 2.0) / 2.0).abs() < EPS);
116 assert!((laguerre(4, 0.0) - 1.0).abs() < EPS);
117 }
118}