mathhook_core/functions/polynomials/
legendre.rs

1//! Legendre Polynomial Intelligence
2//!
3//! Mathematically accurate implementation of Legendre polynomials P_n(x)
4//! with verified recurrence relations, orthogonality properties, and special values.
5
6use crate::core::{Expression, Symbol};
7use crate::functions::properties::*;
8use std::collections::HashMap;
9use std::sync::Arc;
10
11/// Legendre Polynomial Intelligence
12///
13/// Complete mathematical intelligence for Legendre polynomials P_n(x)
14/// with ABSOLUTE MATHEMATICAL ACCURACY verified against literature.
15pub struct LegendreIntelligence {
16    /// Function properties for Legendre polynomials
17    properties: HashMap<String, FunctionProperties>,
18}
19
20impl Default for LegendreIntelligence {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl LegendreIntelligence {
27    /// Create new Legendre polynomial intelligence system
28    pub fn new() -> Self {
29        let mut intelligence = Self {
30            properties: HashMap::with_capacity(4),
31        };
32
33        intelligence.initialize_legendre_polynomials();
34
35        intelligence
36    }
37
38    /// Get all Legendre polynomial properties
39    pub fn get_properties(&self) -> HashMap<String, FunctionProperties> {
40        self.properties.clone()
41    }
42
43    /// Check if function is a Legendre polynomial
44    pub fn has_function(&self, name: &str) -> bool {
45        self.properties.contains_key(name)
46    }
47
48    /// Initialize Legendre polynomials with ABSOLUTE MATHEMATICAL ACCURACY
49    ///
50    /// ## Mathematical Background
51    /// Legendre polynomials P_n(x) are orthogonal polynomials that arise naturally in:
52    /// - **Physics**: Solutions to Laplace's equation in spherical coordinates
53    /// - **Quantum Mechanics**: Angular part of hydrogen atom wavefunctions
54    /// - **Numerical Analysis**: Gaussian quadrature for high-precision integration
55    /// - **Potential Theory**: Multipole expansions in electrostatics
56    ///
57    /// ## Key Properties (Verified against Abramowitz & Stegun, Chapter 8)
58    /// - **Orthogonality**: ∫₋₁¹ Pₘ(x) Pₙ(x) dx = 2/(2n+1) δₘₙ
59    /// - **Recurrence**: (n+1)P_{n+1}(x) = (2n+1)x Pₙ(x) - n P_{n-1}(x)
60    /// - **Rodrigues Formula**: Pₙ(x) = 1/(2ⁿn!) dⁿ/dxⁿ (x²-1)ⁿ
61    /// - **Generating Function**: 1/√(1-2xt+t²) = Σ Pₙ(x) tⁿ
62    fn initialize_legendre_polynomials(&mut self) {
63        self.properties.insert(
64            "legendre_p".to_owned(),
65            FunctionProperties::Polynomial(Box::new(PolynomialProperties {
66                family: PolynomialFamily::Legendre,
67                // THREE-TERM RECURRENCE RELATION (MATHEMATICALLY VERIFIED)
68                // (n+1)P_{n+1}(x) = (2n+1)x P_n(x) - n P_{n-1}(x)
69                // Normalized form: P_{n+1}(x) = [(2n+1)x P_n(x) - n P_{n-1}(x)]/(n+1)
70                recurrence: ThreeTermRecurrence {
71                    // Coefficient of x*P_n(x): (2n+1)/(n+1)
72                    alpha_coeff: Expression::function("legendre_alpha", vec![Expression::symbol("n")]),
73
74                    // No linear term
75                    beta_coeff: Expression::integer(0),
76
77                    // Coefficient of P_{n-1}(x): -n/(n+1)
78                    gamma_coeff: Expression::function("legendre_gamma", vec![Expression::symbol("n")]),
79
80                    // Initial conditions (mathematically verified)
81                    // P_0(x) = 1, P_1(x) = x
82                    initial_conditions: (Expression::integer(1), Expression::symbol("x")),
83                },
84
85                // Orthogonality properties (mathematically verified)
86                // ∫_{-1}^{1} P_m(x) P_n(x) dx = (2/(2n+1)) δ_{mn}
87                orthogonality: Some(OrthogonalityData {
88                    // Weight function: w(x) = 1 (constant)
89                    weight_function: Expression::integer(1),
90
91                    // Orthogonality interval: [-1, 1]
92                    interval: (Expression::integer(-1), Expression::integer(1)),
93
94                    // Normalization: ||P_n||² = 2/(2n+1)
95                    norm_squared: Expression::function("legendre_norm_squared", vec![Expression::symbol("n")]),
96                }),
97
98                // Rodrigues' formula (mathematically verified)
99                // P_n(x) = (1/2^n n!) d^n/dx^n (x²-1)^n
100                rodrigues_formula: Some(RodriguesFormula {
101                    formula: "P_n(x) = (1/2^n n!) d^n/dx^n (x²-1)^n".to_owned(),
102                    normalization: Expression::function("legendre_rodrigues_norm", vec![Expression::symbol("n")]),
103                    weight_function: Expression::function("legendre_rodrigues_weight", vec![Expression::symbol("n"), Expression::symbol("x")]),
104                }),
105
106                // Generating function (mathematically verified)
107                // 1/√(1-2xt+t²) = Σ_{n=0}^∞ P_n(x) t^n
108                generating_function: Some(GeneratingFunction {
109                    function: Expression::function("legendre_generating", vec![Expression::symbol("x"), Expression::symbol("t")]),
110                    gf_type: GeneratingFunctionType::Ordinary,
111                }),
112
113                // Special values (mathematically verified)
114                special_values: vec![
115                    // P_n(1) = 1 for all n ≥ 0
116                    SpecialValue {
117                        input: "1".to_owned(),
118                        output: Expression::integer(1),
119                        latex_explanation: "P_n(1) = 1 \\text{ for all } n \\geq 0".to_owned(),
120                    },
121
122                    // P_n(-1) = (-1)^n for all n ≥ 0
123                    SpecialValue {
124                        input: "-1".to_owned(),
125                        output: Expression::pow(Expression::integer(-1), Expression::symbol("n")),
126                        latex_explanation: "P_n(-1) = (-1)^n \\text{ for all } n \\geq 0".to_owned(),
127                    },
128
129                    // P_n(0) depends on parity of n
130                    SpecialValue {
131                        input: "0".to_owned(),
132                        output: Expression::function("legendre_zero_value", vec![Expression::symbol("n")]),
133                        latex_explanation: "P_n(0) = \\begin{cases} (-1)^{n/2} \\frac{(n-1)!!}{n!!} & \\text{if } n \\text{ even} \\\\ 0 & \\text{if } n \\text{ odd} \\end{cases}".to_owned(),
134                    },
135                ],
136
137                // Evaluation method: Recurrence is most stable and efficient
138                evaluation_method: EvaluationMethod::Recurrence,
139
140                // Numerical evaluator using recurrence relation),
141
142                // Symbolic expansion method for intelligence-driven computation
143                symbolic_expander: Some(super::super::properties::special::SymbolicExpander::Custom(
144                    super::symbolic::expand_legendre_symbolic
145                )),
146
147                antiderivative_rule: AntiderivativeRule {
148                    rule_type: AntiderivativeRuleType::Custom {
149                        builder: Arc::new(|var: Symbol| {
150                            Expression::integral(
151                                Expression::function("legendre_p", vec![Expression::symbol(var.clone())]),
152                                var
153                            )
154                        }),
155                    },
156                    result_template: "∫P_n(x) dx (symbolic - orthogonal polynomial integration requires specialized techniques)".to_owned(),
157                    constant_handling: ConstantOfIntegration::AddConstant,
158                },
159                wolfram_name: None,
160            })),
161        );
162    }
163}
164
165#[cfg(test)]
166mod tests {
167    use super::*;
168
169    #[test]
170    fn test_legendre_mathematical_accuracy() {
171        let legendre = LegendreIntelligence::new();
172
173        // Test that Legendre polynomials are recognized
174        assert!(legendre.has_function("legendre_p"));
175
176        // Test mathematical properties
177        let properties = legendre.get_properties();
178        if let Some(FunctionProperties::Polynomial(legendre_props)) = properties.get("legendre_p") {
179            // Verify polynomial family
180            assert_eq!(legendre_props.family, PolynomialFamily::Legendre);
181
182            // Verify initial conditions: P_0 = 1, P_1 = x
183            assert_eq!(
184                legendre_props.recurrence.initial_conditions.0,
185                Expression::integer(1)
186            );
187            assert_eq!(
188                legendre_props.recurrence.initial_conditions.1,
189                Expression::symbol("x")
190            );
191
192            // Verify orthogonality interval [-1, 1]
193            if let Some(ref ortho) = legendre_props.orthogonality {
194                assert_eq!(ortho.interval.0, Expression::integer(-1));
195                assert_eq!(ortho.interval.1, Expression::integer(1));
196                assert_eq!(ortho.weight_function, Expression::integer(1));
197            }
198
199            // Verify special values
200            assert!(!legendre_props.special_values.is_empty());
201
202            // Verify P_n(1) = 1
203            let p_at_1 = legendre_props
204                .special_values
205                .iter()
206                .find(|sv| sv.input == "1")
207                .expect("P_n(1) special value should exist");
208            assert_eq!(p_at_1.output, Expression::integer(1));
209        }
210    }
211
212    #[test]
213    fn test_legendre_recurrence_accuracy() {
214        let legendre = LegendreIntelligence::new();
215        let properties = legendre.get_properties();
216
217        if let Some(FunctionProperties::Polynomial(legendre_props)) = properties.get("legendre_p") {
218            // Verify recurrence relation structure
219            // (n+1)P_{n+1}(x) = (2n+1)x P_n(x) - n P_{n-1}(x)
220
221            // Beta coefficient should be 0 (no constant term)
222            assert_eq!(legendre_props.recurrence.beta_coeff, Expression::integer(0));
223
224            // Evaluation method should be recurrence (most accurate)
225            assert_eq!(
226                legendre_props.evaluation_method,
227                EvaluationMethod::Recurrence
228            );
229        }
230    }
231}