mathhook-core 0.2.0

Core mathematical engine for MathHook - expressions, algebra, and solving
Documentation
//! Legendre Polynomial Intelligence
//!
//! Mathematically accurate implementation of Legendre polynomials P_n(x)
//! with verified recurrence relations, orthogonality properties, and special values.

use crate::core::{Expression, Symbol};
use crate::functions::properties::*;
use std::collections::HashMap;
use std::sync::Arc;

/// Legendre Polynomial Intelligence
///
/// Complete mathematical intelligence for Legendre polynomials P_n(x)
/// with ABSOLUTE MATHEMATICAL ACCURACY verified against literature.
pub struct LegendreIntelligence {
    /// Function properties for Legendre polynomials
    properties: HashMap<String, FunctionProperties>,
}

impl Default for LegendreIntelligence {
    fn default() -> Self {
        Self::new()
    }
}

impl LegendreIntelligence {
    /// Create new Legendre polynomial intelligence system
    pub fn new() -> Self {
        let mut intelligence = Self {
            properties: HashMap::with_capacity(4),
        };

        intelligence.initialize_legendre_polynomials();

        intelligence
    }

    /// Get all Legendre polynomial properties
    pub fn get_properties(&self) -> HashMap<String, FunctionProperties> {
        self.properties.clone()
    }

    /// Check if function is a Legendre polynomial
    pub fn has_function(&self, name: &str) -> bool {
        self.properties.contains_key(name)
    }

    /// Initialize Legendre polynomials with ABSOLUTE MATHEMATICAL ACCURACY
    ///
    /// ## Mathematical Background
    /// Legendre polynomials P_n(x) are orthogonal polynomials that arise naturally in:
    /// - **Physics**: Solutions to Laplace's equation in spherical coordinates
    /// - **Quantum Mechanics**: Angular part of hydrogen atom wavefunctions
    /// - **Numerical Analysis**: Gaussian quadrature for high-precision integration
    /// - **Potential Theory**: Multipole expansions in electrostatics
    ///
    /// ## Key Properties (Verified against Abramowitz & Stegun, Chapter 8)
    /// - **Orthogonality**: ∫₋₁¹ Pₘ(x) Pₙ(x) dx = 2/(2n+1) δₘₙ
    /// - **Recurrence**: (n+1)P_{n+1}(x) = (2n+1)x Pₙ(x) - n P_{n-1}(x)
    /// - **Rodrigues Formula**: Pₙ(x) = 1/(2ⁿn!) dⁿ/dxⁿ (x²-1)ⁿ
    /// - **Generating Function**: 1/√(1-2xt+t²) = Σ Pₙ(x) tⁿ
    fn initialize_legendre_polynomials(&mut self) {
        self.properties.insert(
            "legendre_p".to_owned(),
            FunctionProperties::Polynomial(Box::new(PolynomialProperties {
                family: PolynomialFamily::Legendre,
                // THREE-TERM RECURRENCE RELATION (MATHEMATICALLY VERIFIED)
                // (n+1)P_{n+1}(x) = (2n+1)x P_n(x) - n P_{n-1}(x)
                // Normalized form: P_{n+1}(x) = [(2n+1)x P_n(x) - n P_{n-1}(x)]/(n+1)
                recurrence: ThreeTermRecurrence {
                    // Coefficient of x*P_n(x): (2n+1)/(n+1)
                    alpha_coeff: Expression::function("legendre_alpha", vec![Expression::symbol("n")]),

                    // No linear term
                    beta_coeff: Expression::integer(0),

                    // Coefficient of P_{n-1}(x): -n/(n+1)
                    gamma_coeff: Expression::function("legendre_gamma", vec![Expression::symbol("n")]),

                    // Initial conditions (mathematically verified)
                    // P_0(x) = 1, P_1(x) = x
                    initial_conditions: (Expression::integer(1), Expression::symbol("x")),
                },

                // Orthogonality properties (mathematically verified)
                // ∫_{-1}^{1} P_m(x) P_n(x) dx = (2/(2n+1)) δ_{mn}
                orthogonality: Some(OrthogonalityData {
                    // Weight function: w(x) = 1 (constant)
                    weight_function: Expression::integer(1),

                    // Orthogonality interval: [-1, 1]
                    interval: (Expression::integer(-1), Expression::integer(1)),

                    // Normalization: ||P_n||² = 2/(2n+1)
                    norm_squared: Expression::function("legendre_norm_squared", vec![Expression::symbol("n")]),
                }),

                // Rodrigues' formula (mathematically verified)
                // P_n(x) = (1/2^n n!) d^n/dx^n (x²-1)^n
                rodrigues_formula: Some(RodriguesFormula {
                    formula: "P_n(x) = (1/2^n n!) d^n/dx^n (x²-1)^n".to_owned(),
                    normalization: Expression::function("legendre_rodrigues_norm", vec![Expression::symbol("n")]),
                    weight_function: Expression::function("legendre_rodrigues_weight", vec![Expression::symbol("n"), Expression::symbol("x")]),
                }),

                // Generating function (mathematically verified)
                // 1/√(1-2xt+t²) = Σ_{n=0}^∞ P_n(x) t^n
                generating_function: Some(GeneratingFunction {
                    function: Expression::function("legendre_generating", vec![Expression::symbol("x"), Expression::symbol("t")]),
                    gf_type: GeneratingFunctionType::Ordinary,
                }),

                // Special values (mathematically verified)
                special_values: vec![
                    // P_n(1) = 1 for all n ≥ 0
                    SpecialValue {
                        input: "1".to_owned(),
                        output: Expression::integer(1),
                        latex_explanation: "P_n(1) = 1 \\text{ for all } n \\geq 0".to_owned(),
                    },

                    // P_n(-1) = (-1)^n for all n ≥ 0
                    SpecialValue {
                        input: "-1".to_owned(),
                        output: Expression::pow(Expression::integer(-1), Expression::symbol("n")),
                        latex_explanation: "P_n(-1) = (-1)^n \\text{ for all } n \\geq 0".to_owned(),
                    },

                    // P_n(0) depends on parity of n
                    SpecialValue {
                        input: "0".to_owned(),
                        output: Expression::function("legendre_zero_value", vec![Expression::symbol("n")]),
                        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(),
                    },
                ],

                // Evaluation method: Recurrence is most stable and efficient
                evaluation_method: EvaluationMethod::Recurrence,

                // Numerical evaluator using recurrence relation),

                // Symbolic expansion method for intelligence-driven computation
                symbolic_expander: Some(super::super::properties::special::SymbolicExpander::Custom(
                    super::symbolic::expand_legendre_symbolic
                )),

                antiderivative_rule: AntiderivativeRule {
                    rule_type: AntiderivativeRuleType::Custom {
                        builder: Arc::new(|var: Symbol| {
                            Expression::integral(
                                Expression::function("legendre_p", vec![Expression::symbol(var.clone())]),
                                var
                            )
                        }),
                    },
                    result_template: "∫P_n(x) dx (symbolic - orthogonal polynomial integration requires specialized techniques)".to_owned(),
                    constant_handling: ConstantOfIntegration::AddConstant,
                },
                wolfram_name: None,
            })),
        );
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_legendre_mathematical_accuracy() {
        let legendre = LegendreIntelligence::new();

        // Test that Legendre polynomials are recognized
        assert!(legendre.has_function("legendre_p"));

        // Test mathematical properties
        let properties = legendre.get_properties();
        if let Some(FunctionProperties::Polynomial(legendre_props)) = properties.get("legendre_p") {
            // Verify polynomial family
            assert_eq!(legendre_props.family, PolynomialFamily::Legendre);

            // Verify initial conditions: P_0 = 1, P_1 = x
            assert_eq!(
                legendre_props.recurrence.initial_conditions.0,
                Expression::integer(1)
            );
            assert_eq!(
                legendre_props.recurrence.initial_conditions.1,
                Expression::symbol("x")
            );

            // Verify orthogonality interval [-1, 1]
            if let Some(ref ortho) = legendre_props.orthogonality {
                assert_eq!(ortho.interval.0, Expression::integer(-1));
                assert_eq!(ortho.interval.1, Expression::integer(1));
                assert_eq!(ortho.weight_function, Expression::integer(1));
            }

            // Verify special values
            assert!(!legendre_props.special_values.is_empty());

            // Verify P_n(1) = 1
            let p_at_1 = legendre_props
                .special_values
                .iter()
                .find(|sv| sv.input == "1")
                .expect("P_n(1) special value should exist");
            assert_eq!(p_at_1.output, Expression::integer(1));
        }
    }

    #[test]
    fn test_legendre_recurrence_accuracy() {
        let legendre = LegendreIntelligence::new();
        let properties = legendre.get_properties();

        if let Some(FunctionProperties::Polynomial(legendre_props)) = properties.get("legendre_p") {
            // Verify recurrence relation structure
            // (n+1)P_{n+1}(x) = (2n+1)x P_n(x) - n P_{n-1}(x)

            // Beta coefficient should be 0 (no constant term)
            assert_eq!(legendre_props.recurrence.beta_coeff, Expression::integer(0));

            // Evaluation method should be recurrence (most accurate)
            assert_eq!(
                legendre_props.evaluation_method,
                EvaluationMethod::Recurrence
            );
        }
    }
}