mathhook_core/
lib.rs

1//! Core mathematical engine for MathHook
2//!
3//! This crate provides the foundational types and operations for symbolic mathematics,
4//! implementing a hybrid API architecture optimized for both performance and usability.
5
6extern crate self as mathhook_core;
7
8pub mod algebra;
9pub mod calculus;
10pub mod core;
11pub mod educational;
12pub mod error;
13pub mod formatter;
14pub mod functions;
15pub mod macros;
16pub mod matrices;
17pub mod parser;
18pub mod pattern;
19pub mod serialize;
20pub mod simplify;
21pub mod solvers;
22
23// Curated re-exports (no wildcards for maintainability)
24
25// Macro re-exports (at crate root for backward compatibility)
26pub use mathhook_macros::{expr, function, symbol, symbols};
27
28// Core types (most commonly used)
29pub use core::expression::eval_numeric::{EvalContext, EvalNumeric};
30pub use core::{
31    Commutativity, Expression, MathConstant, Number, NumericMatrix, Symbol, SymbolType,
32};
33
34// Algebra traits and key types
35pub use algebra::{multivariate_gcd, polynomial_div, polynomial_quo, polynomial_rem};
36pub use algebra::{
37    AdvancedPolynomial, AdvancedSimplify, Collect, ComplexOperations, EquationAnalyzer,
38    EquationType, Expand, Factor, PolynomialGcd, RationalSimplify, SmartEquationSolver,
39    ZeroDetection,
40};
41
42// Calculus operations
43pub use calculus::derivatives::Derivative;
44pub use calculus::{
45    BasicDerivatives, BasicIntegrals, ChainRule, ComplexAnalysis, FunctionIntegrals,
46    HigherOrderDerivatives, Integration, IntegrationMethods, LimitDirection, Limits, PowerRule,
47    ProductRule, ResidueCalculus, SeriesExpansion, SeriesType, Summation, SummationMethods,
48};
49
50// Solvers
51pub use solvers::{MathSolver, SolverConfig, SolverResult};
52
53// Pattern matching and substitution
54pub use pattern::{Matchable, Pattern, PatternMatches, Substitutable};
55
56// Parser types (commonly needed)
57pub use parser::config::ParserConfig;
58pub use parser::error::ParseError;
59pub use parser::Parser;
60
61// Error types
62pub use error::MathError;
63
64// Formatter types
65pub use formatter::{LaTeXFormatter, MathLanguage, SimpleFormatter, WolframFormatter};
66
67// Functions (re-export function modules for users who want specific functions)
68pub use functions::elementary;
69pub use functions::polynomials;
70pub use functions::special;
71
72// Simplify operations
73pub use simplify::Simplify;
74
75/// Convenience prelude for common imports
76///
77/// This prelude provides everything needed for typical symbolic mathematics operations.
78/// Import with `use mathhook_core::prelude::*;` to access all common types and traits.
79pub mod prelude {
80    pub use crate::macros::*;
81    pub use crate::{expr, function, symbol, symbols};
82
83    // Core types
84    pub use crate::{
85        Commutativity, Expression, MathConstant, Number, NumericMatrix, Symbol, SymbolType,
86    };
87
88    // Algebra traits
89    pub use crate::{
90        AdvancedPolynomial, AdvancedSimplify, Collect, ComplexOperations, EquationAnalyzer,
91        EquationType, Expand, Factor, PolynomialGcd, RationalSimplify, Simplify,
92        SmartEquationSolver, ZeroDetection,
93    };
94
95    // Algebra functions
96    pub use crate::{multivariate_gcd, polynomial_div, polynomial_quo, polynomial_rem};
97
98    // Calculus traits (comprehensive)
99    pub use crate::Derivative;
100    pub use crate::{
101        BasicDerivatives, BasicIntegrals, ChainRule, ComplexAnalysis, FunctionIntegrals,
102        HigherOrderDerivatives, Integration, IntegrationMethods, LimitDirection, Limits, PowerRule,
103        ProductRule, ResidueCalculus, SeriesExpansion, SeriesType, Summation, SummationMethods,
104    };
105
106    // Pattern matching and substitution
107    pub use crate::{Matchable, Pattern, PatternMatches, Substitutable};
108
109    // Educational features
110    pub use crate::educational::{
111        DifficultyLevel, EducationalExt, EducationalOperation, EducationalResult, EnhancedStep,
112        EnhancedStepExplanation, OperationContext, Step, StepByStep, StepByStepExplanation,
113    };
114
115    // Matrix operations
116    pub use crate::matrices::{
117        CoreMatrixOps, EigenOperations, Matrix, MatrixDecomposition, MatrixOperations,
118    };
119
120    // Solver
121    pub use crate::{MathSolver, SolverConfig, SolverResult};
122
123    // Parser
124    pub use crate::{Parser, ParserConfig};
125
126    // Error types
127    pub use crate::{MathError, ParseError};
128
129    // Formatters
130    pub use crate::{LaTeXFormatter, MathLanguage, SimpleFormatter, WolframFormatter};
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136
137    #[test]
138    fn test_expression_memory_optimization() {
139        let expression_size = std::mem::size_of::<Expression>();
140        println!("Clean Expression size: {} bytes", expression_size);
141
142        assert!(
143            expression_size <= 32,
144            "Expression should be ≤ 32 bytes, got {} bytes",
145            expression_size
146        );
147    }
148
149    #[test]
150    fn test_hybrid_api_basic_operations() {
151        let expr = Expression::add(vec![Expression::integer(2), Expression::integer(3)]);
152        let simplified = expr.simplify();
153
154        match simplified {
155            Expression::Number(num) => {
156                if let Number::Integer(i) = num {
157                    assert_eq!(i, 5);
158                } else {
159                    panic!("Expected integer result");
160                }
161            }
162            _ => panic!("Expected number result"),
163        }
164    }
165
166    #[test]
167    fn test_solver_object_api() {
168        let mut solver = MathSolver::new();
169
170        let equation = Expression::equation(expr!(x), expr!(42));
171
172        let result = solver.solve(&equation, &symbol!(x));
173
174        match result {
175            SolverResult::Single(solution) => match solution {
176                Expression::Number(num) => {
177                    if let Number::Integer(i) = num {
178                        assert_eq!(i, 42);
179                    } else {
180                        panic!("Expected integer solution");
181                    }
182                }
183                _ => panic!("Expected number solution"),
184            },
185            _ => panic!("Expected single solution"),
186        }
187    }
188
189    #[test]
190    fn test_hot_path_performance() {
191        let start = std::time::Instant::now();
192
193        for _ in 0..10000 {
194            let expr = expr!(1 + x + 2);
195            let _simplified = expr.simplify();
196        }
197
198        let duration = start.elapsed();
199        println!("10K hot-path operations took: {:?}", duration);
200
201        assert!(
202            duration.as_millis() < 100,
203            "Hot path too slow: {:?}",
204            duration
205        );
206    }
207
208    #[test]
209    #[allow(non_snake_case)]
210    fn test_procedural_symbol_macro() {
211        let x = symbol!(x);
212        assert_eq!(x.name(), "x");
213        assert_eq!(x.commutativity(), Commutativity::Commutative);
214
215        let A = symbol!(A; matrix);
216        assert_eq!(A.name(), "A");
217        assert_eq!(A.commutativity(), Commutativity::Noncommutative);
218
219        let p = symbol!(p; operator);
220        assert_eq!(p.name(), "p");
221        assert_eq!(p.commutativity(), Commutativity::Noncommutative);
222
223        let i = symbol!(i; quaternion);
224        assert_eq!(i.name(), "i");
225        assert_eq!(i.commutativity(), Commutativity::Noncommutative);
226
227        let syms = symbols![x, y, z];
228        assert_eq!(syms.len(), 3);
229        assert_eq!(syms[0].name(), "x");
230        assert_eq!(syms[1].name(), "y");
231        assert_eq!(syms[2].name(), "z");
232        assert_eq!(syms[0].commutativity(), Commutativity::Commutative);
233
234        let mats = symbols![A, B => matrix];
235        assert_eq!(mats.len(), 2);
236        assert_eq!(mats[0].name(), "A");
237        assert_eq!(mats[1].name(), "B");
238        assert_eq!(mats[0].commutativity(), Commutativity::Noncommutative);
239    }
240
241    #[test]
242    fn test_procedural_function_macro() {
243        let gamma_call = function!(gamma);
244        if let Expression::Function { name, args } = &gamma_call {
245            assert_eq!(name, "gamma");
246            assert_eq!(args.len(), 0);
247        } else {
248            panic!("Expected Function expression");
249        }
250
251        let x = expr!(x);
252        let sin_x = function!(sin, x.clone());
253        if let Expression::Function { name, args } = &sin_x {
254            assert_eq!(name, "sin");
255            assert_eq!(args.len(), 1);
256        } else {
257            panic!("Expected Function expression");
258        }
259
260        let y = expr!(y);
261        let log_xy = function!(log, x, y);
262        if let Expression::Function { name, args } = &log_xy {
263            assert_eq!(name, "log");
264            assert_eq!(args.len(), 2);
265        } else {
266            panic!("Expected Function expression");
267        }
268    }
269}