mathhook_core/functions/elementary/
logarithmic.rs

1//! Logarithmic Function Intelligence
2//!
3//! with verified derivatives, special values, and logarithm laws.
4
5use crate::core::{Expression, Symbol};
6use crate::functions::properties::*;
7use std::collections::HashMap;
8use std::sync::Arc;
9
10/// Logarithmic Function Intelligence
11///
12/// Complete mathematical intelligence for logarithmic functions
13pub struct LogarithmicIntelligence {
14    /// Function properties for logarithmic functions
15    properties: HashMap<String, FunctionProperties>,
16}
17
18impl Default for LogarithmicIntelligence {
19    fn default() -> Self {
20        Self::new()
21    }
22}
23
24impl LogarithmicIntelligence {
25    /// Create new logarithmic intelligence system
26    pub fn new() -> Self {
27        let mut intelligence = Self {
28            properties: HashMap::with_capacity(4),
29        };
30
31        intelligence.initialize_ln();
32        intelligence.initialize_log();
33
34        intelligence
35    }
36
37    /// Get all logarithmic function properties
38    pub fn get_properties(&self) -> HashMap<String, FunctionProperties> {
39        self.properties.clone()
40    }
41
42    /// Check if function is logarithmic
43    pub fn has_function(&self, name: &str) -> bool {
44        self.properties.contains_key(name)
45    }
46
47    /// Initialize natural logarithm
48    fn initialize_ln(&mut self) {
49        // Natural Logarithm ln(x)
50        self.properties.insert(
51            "ln".to_owned(),
52            FunctionProperties::Elementary(Box::new(ElementaryProperties {
53                // DERIVATIVE: d/dx ln(x) = 1/x (x > 0)
54                derivative_rule: Some(DerivativeRule {
55                    rule_type: DerivativeRuleType::Custom {
56                        builder: Arc::new(|arg: &Expression| {
57                            Expression::pow(arg.clone(), Expression::integer(-1))
58                        }),
59                    },
60                    result_template: "1/x".to_owned(),
61                }),
62                antiderivative_rule: Some(AntiderivativeRule {
63                    rule_type: AntiderivativeRuleType::Custom {
64                        builder: Arc::new(|var: Symbol| {
65                            Expression::add(vec![
66                                Expression::mul(vec![
67                                    Expression::symbol(var.clone()),
68                                    Expression::function(
69                                        "ln",
70                                        vec![Expression::symbol(var.clone())],
71                                    ),
72                                ]),
73                                Expression::mul(vec![
74                                    Expression::integer(-1),
75                                    Expression::symbol(var),
76                                ]),
77                            ])
78                        }),
79                    },
80                    result_template: "∫ln(x)dx = x·ln(x) - x + C".to_owned(),
81                    constant_handling: ConstantOfIntegration::AddConstant,
82                }),
83
84                // SPECIAL VALUES
85                special_values: vec![
86                    // ln(1) = 0
87                    SpecialValue {
88                        input: "1".to_owned(),
89                        output: Expression::integer(0),
90                        latex_explanation: "\\ln(1) = 0".to_owned(),
91                    },
92                    // ln(e) = 1
93                    SpecialValue {
94                        input: "e".to_owned(),
95                        output: Expression::integer(1),
96                        latex_explanation: "\\ln(e) = 1".to_owned(),
97                    },
98                ],
99
100                // Logarithm Laws
101                identities: Box::new(vec![
102                    // ln(xy) = ln(x) + ln(y)
103                    MathIdentity {
104                        name: "Logarithm Product Law".to_owned(),
105                        lhs: Expression::function(
106                            "ln",
107                            vec![Expression::mul(vec![
108                                Expression::symbol("x"),
109                                Expression::symbol("y"),
110                            ])],
111                        ),
112                        rhs: Expression::add(vec![
113                            Expression::function("ln", vec![Expression::symbol("x")]),
114                            Expression::function("ln", vec![Expression::symbol("y")]),
115                        ]),
116                        conditions: vec!["x, y > 0".to_owned()],
117                    },
118                ]),
119
120                domain_range: Box::new(DomainRangeData {
121                    domain: Domain::Interval(Expression::integer(0), Expression::symbol("∞")), // (0, ∞)
122                    range: Range::Real,                          // (-∞, ∞)
123                    singularities: vec![Expression::integer(0)], // Singularity at x = 0
124                }),
125
126                // No periodicity
127                periodicity: None,
128                wolfram_name: Some("Log"),
129            })),
130        );
131    }
132
133    /// Initialize base-10 logarithm
134    fn initialize_log(&mut self) {
135        self.properties.insert(
136            "log".to_owned(),
137            FunctionProperties::Elementary(Box::new(ElementaryProperties {
138                derivative_rule: Some(DerivativeRule {
139                    rule_type: DerivativeRuleType::Custom {
140                        builder: Arc::new(|arg: &Expression| {
141                            Expression::mul(vec![
142                                Expression::pow(arg.clone(), Expression::integer(-1)),
143                                Expression::pow(
144                                    Expression::function("ln", vec![Expression::integer(10)]),
145                                    Expression::integer(-1),
146                                ),
147                            ])
148                        }),
149                    },
150                    result_template: "1/(x·ln(10))".to_owned(),
151                }),
152                antiderivative_rule: Some(AntiderivativeRule {
153                    rule_type: AntiderivativeRuleType::Custom {
154                        builder: Arc::new(|var: Symbol| {
155                            Expression::mul(vec![
156                                Expression::pow(
157                                    Expression::function("ln", vec![Expression::integer(10)]),
158                                    Expression::integer(-1),
159                                ),
160                                Expression::add(vec![
161                                    Expression::mul(vec![
162                                        Expression::symbol(var.clone()),
163                                        Expression::function(
164                                            "ln",
165                                            vec![Expression::symbol(var.clone())],
166                                        ),
167                                    ]),
168                                    Expression::mul(vec![
169                                        Expression::integer(-1),
170                                        Expression::symbol(var),
171                                    ]),
172                                ]),
173                            ])
174                        }),
175                    },
176                    result_template: "∫log(x)dx = (1/ln(10))·(x·ln(x) - x) + C".to_owned(),
177                    constant_handling: ConstantOfIntegration::AddConstant,
178                }),
179                special_values: vec![
180                    SpecialValue {
181                        input: "1".to_owned(),
182                        output: Expression::integer(0),
183                        latex_explanation: "\\log(1) = 0".to_owned(),
184                    },
185                    SpecialValue {
186                        input: "10".to_owned(),
187                        output: Expression::integer(1),
188                        latex_explanation: "\\log(10) = 1".to_owned(),
189                    },
190                ],
191                identities: Box::new(vec![]),
192                domain_range: Box::new(DomainRangeData {
193                    domain: Domain::Interval(Expression::integer(0), Expression::symbol("∞")),
194                    range: Range::Real,
195                    singularities: vec![Expression::integer(0)],
196                }),
197                periodicity: None,
198                wolfram_name: Some("Log"),
199            })),
200        );
201    }
202}