thales/lib.rs
1//! # Thales - Computer Algebra System
2//!
3//! A comprehensive Computer Algebra System (CAS) library for symbolic mathematics,
4//! equation solving, calculus, and numerical methods. Named after
5//! [Thales of Miletus](https://en.wikipedia.org/wiki/Thales_of_Miletus),
6//! the first mathematician in the Greek tradition.
7//!
8//! ## Overview
9//!
10//! Thales provides:
11//! - **Symbolic equation solving** - Linear, quadratic, polynomial, transcendental, and systems
12//! - **Calculus** - Differentiation, integration, limits, Taylor series, first and second-order ODEs
13//! - **Numerical methods** - Newton-Raphson, bisection, Brent's method, Levenberg-Marquardt
14//! - **Coordinate systems** - 2D/3D transformations, complex numbers, De Moivre's theorem
15//! - **Units & dimensions** - Dimensional analysis and unit conversion
16//! - **Step-by-step solutions** - Resolution paths for educational applications
17//! - **iOS/macOS support** - FFI bindings via swift-bridge
18//!
19//! ## Key Features
20//!
21//! - Zero-cost abstractions with compile-time guarantees
22//! - Memory-safe implementation (no unsafe code except FFI boundary)
23//! - 970+ tests including property-based tests with proptest
24//! - Optimized for mobile targets (iOS)
25//! - Clear separation between symbolic and numerical methods
26//!
27//! # Quick Start
28//!
29//! ## Example 1: Coordinate Transformations
30//!
31//! Convert between Cartesian and polar coordinate systems:
32//!
33//! ```rust
34//! use thales::{Cartesian2D, Polar};
35//!
36//! // 2D Cartesian to Polar
37//! let cartesian = Cartesian2D::new(3.0, 4.0);
38//! let polar = cartesian.to_polar();
39//! assert!((polar.r - 5.0).abs() < 1e-10);
40//! assert!((polar.theta - 0.927295218).abs() < 1e-6);
41//!
42//! // Polar to Cartesian round-trip
43//! let back = polar.to_cartesian();
44//! assert!((back.x - 3.0).abs() < 1e-10);
45//! assert!((back.y - 4.0).abs() < 1e-10);
46//! ```
47//!
48//! ## Example 2: 3D Coordinate Transformations
49//!
50//! Convert between Cartesian and spherical coordinates:
51//!
52//! ```rust
53//! use thales::{Cartesian3D, Spherical};
54//!
55//! // Cartesian to Spherical
56//! let cart3d = Cartesian3D::new(1.0, 1.0, 1.0);
57//! let spherical = cart3d.to_spherical();
58//! assert!((spherical.r - 1.732050808).abs() < 1e-6);
59//!
60//! // Spherical to Cartesian round-trip
61//! let back = spherical.to_cartesian();
62//! assert!((back.x - 1.0).abs() < 1e-10);
63//! assert!((back.y - 1.0).abs() < 1e-10);
64//! assert!((back.z - 1.0).abs() < 1e-10);
65//! ```
66//!
67//! ## Example 3: Complex Number Operations
68//!
69//! Work with complex numbers and polar form:
70//!
71//! ```rust
72//! use thales::ComplexOps;
73//! use num_complex::Complex64;
74//!
75//! // De Moivre's theorem: (r∠θ)^n = r^n∠(nθ)
76//! let z = Complex64::new(1.0, 1.0);
77//! let result = ComplexOps::de_moivre(z, 2.0);
78//!
79//! // Complex conjugate (using num_complex methods)
80//! let conj = z.conj();
81//! assert_eq!(conj.re, z.re);
82//! assert_eq!(conj.im, -z.im);
83//!
84//! // Modulus (magnitude) of complex number
85//! let modulus = z.norm();
86//! assert!((modulus - 1.4142135623730951).abs() < 1e-10);
87//! ```
88//!
89//! ## Example 4: Expression and Variable Basics
90//!
91//! Build mathematical expressions using the AST:
92//!
93//! ```rust
94//! use thales::{Expression, Variable, BinaryOp};
95//!
96//! // Create expression: 2*x + 5
97//! let x = Variable::new("x");
98//! let two_x = Expression::Binary(
99//! BinaryOp::Mul,
100//! Box::new(Expression::Integer(2)),
101//! Box::new(Expression::Variable(x.clone()))
102//! );
103//! let expr = Expression::Binary(
104//! BinaryOp::Add,
105//! Box::new(two_x),
106//! Box::new(Expression::Integer(5))
107//! );
108//!
109//! // Check variable containment
110//! assert!(expr.contains_variable("x"));
111//! assert!(!expr.contains_variable("y"));
112//! ```
113//!
114//! ## User Guides
115//!
116//! For detailed tutorials and workflows, see the [`guides`] module:
117//!
118//! - [`guides::solving_equations`] - Linear, quadratic, polynomial, and systems
119//! - [`guides::calculus_operations`] - Derivatives, integrals, limits, ODEs
120//! - [`guides::series_expansions`] - Taylor, Maclaurin, Laurent, asymptotic
121//! - [`guides::coordinate_systems`] - 2D/3D transforms, complex numbers
122//! - [`guides::numerical_methods`] - Root-finding when symbolic fails
123//! - [`guides::working_with_units`] - Dimensional analysis
124//! - [`guides::error_handling`] - Working with [`ThalesError`]
125//!
126//! ## Feature Summary
127//!
128//! | Category | Features |
129//! |----------|----------|
130//! | **Parsing** | Expression parser, equation parser, LaTeX input/output |
131//! | **Solving** | Linear, quadratic, polynomial, transcendental, multi-equation systems |
132//! | **Calculus** | Differentiation, integration (by parts, substitution), limits, L'Hôpital |
133//! | **ODEs** | First-order (separable, linear), second-order (constant coefficient) |
134//! | **Series** | Taylor, Maclaurin, Laurent, asymptotic expansions, Big-O |
135//! | **Special** | Gamma, beta, error functions with derivation steps |
136//! | **Numerical** | Newton-Raphson, bisection, Brent's, secant, Levenberg-Marquardt |
137//! | **Transforms** | Cartesian ↔ Polar ↔ Spherical ↔ Cylindrical, complex operations |
138//! | **Units** | SI base/derived units, dimensional analysis, conversions |
139//! | **FFI** | Swift bindings via swift-bridge, iOS device + simulator |
140//!
141//! # Architecture Overview
142//!
143//! The library follows a modular design with clear separation of concerns:
144//!
145//! ```text
146//! ┌─────────────────────────────────────────────────────────┐
147//! │ Public API Layer │
148//! │ (parse_equation, SmartSolver, Cartesian2D, etc.) │
149//! └─────────────────────────────────────────────────────────┘
150//! │
151//! ┌────────────────┼────────────────┐
152//! ▼ ▼ ▼
153//! ┌──────────┐ ┌──────────┐ ┌──────────┐
154//! │ Parser │ │ Solver │ │Transform │
155//! │ (chumsky)│ │ (symbolic)│ │(nalgebra)│
156//! └──────────┘ └──────────┘ └──────────┘
157//! │ │ │
158//! └────────────────┼────────────────┘
159//! ▼
160//! ┌──────────┐
161//! │ AST │
162//! │(equation,│
163//! │ expr, │
164//! │variable) │
165//! └──────────┘
166//! │
167//! ┌────────────────┼────────────────┐
168//! ▼ ▼ ▼
169//! ┌──────────┐ ┌──────────┐ ┌──────────┐
170//! │Numerical │ │Resolution│ │Dimensions│
171//! │ (argmin) │ │ Path │ │ (units) │
172//! └──────────┘ └──────────┘ └──────────┘
173//! │
174//! ▼
175//! ┌──────────┐
176//! │ FFI │
177//! │ (Swift) │
178//! └──────────┘
179//! ```
180//!
181//! ## Module Responsibilities
182//!
183//! - [`ast`]: Core data structures for mathematical expressions, equations, variables,
184//! operators, and functions. All other modules build upon these types.
185//!
186//! - [`parser`]: String → AST conversion using the chumsky parser combinator library.
187//! Handles operator precedence, function calls, and complex number literals.
188//!
189//! - [`solver`]: Symbolic equation solving using algebraic manipulation. Includes
190//! specialized solvers for linear, quadratic, polynomial, and transcendental equations.
191//! The [`SmartSolver`] automatically dispatches to the appropriate solver.
192//!
193//! - [`numerical`]: Numerical root-finding methods for equations that cannot be solved
194//! symbolically. Integrates with symbolic differentiation from the AST module.
195//!
196//! - [`resolution_path`]: Records the step-by-step solution process for educational
197//! applications. Each transformation is recorded with its operation type.
198//!
199//! - [`dimensions`]: Dimensional analysis and unit conversion. Ensures physical
200//! equations maintain dimensional consistency.
201//!
202//! - [`transforms`]: Coordinate system conversions (Cartesian, Polar, Spherical,
203//! Cylindrical) and complex number operations. Built on nalgebra for linear algebra.
204//!
205//! - `ffi`: Foreign function interface for Swift via swift-bridge. Provides
206//! C-compatible bindings for iOS/macOS integration. Enabled with the `ffi` feature flag.
207//!
208//! # Safety Guarantees
209//!
210//! This library adheres to strict memory safety principles:
211//!
212//! - **No unsafe code in core logic**: All mathematical operations, parsing, solving,
213//! and transformations use only safe Rust.
214//!
215//! - **FFI boundary isolation**: The only `unsafe` code appears in the `ffi` module
216//! for C interoperability, which is:
217//! - Isolated behind the `ffi` feature flag
218//! - Managed by the swift-bridge library
219//! - Validated at the FFI boundary with explicit error handling
220//!
221//! - **Ownership guarantees**: The Rust type system prevents:
222//! - Use-after-free bugs
223//! - Data races in concurrent access
224//! - Null pointer dereferences
225//! - Buffer overflows
226//!
227//! - **Integer overflow protection**: All arithmetic operations use checked or saturating
228//! semantics where appropriate.
229//!
230//! - **Thread safety**: All public types are `Send + Sync` where semantically appropriate,
231//! with compile-time verification.
232//!
233//! # Performance Characteristics
234//!
235//! ## Time Complexity Guarantees
236//!
237//! | Operation | Complexity | Notes |
238//! |-----------|-----------|-------|
239//! | Parse expression | O(n) | Linear in input string length |
240//! | Variable lookup | O(1) | HashMap-based symbol table |
241//! | Coordinate transform | O(1) | Fixed number of trig operations |
242//! | Linear solve | O(1) | Constant number of operations |
243//! | Quadratic solve | O(1) | Discriminant calculation + sqrt |
244//! | Polynomial solve (degree d) | O(d²) | Companion matrix method |
245//! | Numerical solve (Newton) | O(k) | k iterations to convergence |
246//!
247//! ## Space Complexity
248//!
249//! - **AST storage**: O(n) where n is the number of expression nodes
250//! - **Resolution path**: O(k) where k is the number of solution steps
251//! - **Parser stack**: O(d) where d is maximum nesting depth
252//!
253//! ## Optimization Features
254//!
255//! Build configuration in release mode enables:
256//!
257//! - **Link-Time Optimization (LTO)**: Cross-module inlining and dead code elimination
258//! - **Single codegen unit**: Maximum optimization at cost of compile time
259//! - **opt-level=3**: Aggressive compiler optimizations
260//! - **Zero-cost abstractions**: Generic functions specialized at compile time
261//! - **SIMD auto-vectorization**: Compiler-generated vectorized code where applicable
262//!
263//! ```toml
264//! [profile.release]
265//! opt-level = 3
266//! lto = true
267//! codegen-units = 1
268//! ```
269//!
270//! Benchmark your performance-critical paths with:
271//!
272//! ```bash
273//! cargo bench
274//! ```
275//!
276//! # Platform Support
277//!
278//! ## Tier 1: Fully Supported
279//!
280//! - **iOS Devices** (`aarch64-apple-ios`): Native ARM64 execution on iPhone/iPad
281//! - **iOS Simulator on ARM** (`aarch64-apple-ios-sim`): M1/M2/M3 Mac simulator
282//! - **iOS Simulator on Intel** (`x86_64-apple-ios`): Intel Mac simulator
283//!
284//! Build for all iOS targets:
285//!
286//! ```bash
287//! # Add targets (one-time setup)
288//! rustup target add aarch64-apple-ios
289//! rustup target add aarch64-apple-ios-sim
290//! rustup target add x86_64-apple-ios
291//!
292//! # Build for device
293//! cargo build --release --target aarch64-apple-ios
294//!
295//! # Build for simulator (ARM)
296//! cargo build --release --target aarch64-apple-ios-sim
297//!
298//! # Build universal library with lipo
299//! lipo -create \
300//! target/aarch64-apple-ios-sim/release/libthales.a \
301//! target/x86_64-apple-ios/release/libthales.a \
302//! -output libthales_universal.a
303//! ```
304//!
305//! ## Tier 2: Standard Rust Targets
306//!
307//! The library uses only stable Rust features and should compile on any tier 1 Rust platform:
308//! - Linux (x86_64, aarch64)
309//! - macOS (x86_64, aarch64)
310//! - Windows (x86_64)
311//!
312//! ## FFI Integration
313//!
314//! Enable Swift bindings with the `ffi` feature:
315//!
316//! ```bash
317//! cargo build --release --features ffi --target aarch64-apple-ios
318//! ```
319//!
320//! This generates Swift bridge code and C headers for Xcode integration.
321//!
322//! ## Version History
323//!
324//! **Current: v0.3.0** - Advanced Calculus & API Stabilization
325//!
326//! - Second-order ODEs with characteristic equation method
327//! - Nonlinear system solver (Newton-Raphson for systems)
328//! - Taylor, Maclaurin, Laurent series expansions
329//! - Asymptotic expansions with Big-O notation
330//! - Special functions (gamma, beta, erf, erfc)
331//! - Small angle approximations with error bounds
332//! - Unified [`ThalesError`] type
333//! - 970+ tests including property-based tests
334//!
335//! See [CHANGELOG.md](https://github.com/ChrisGVE/thales/blob/main/CHANGELOG.md)
336//! for complete version history.
337//!
338//! ## Module Reference
339//!
340//! | Module | Description |
341//! |--------|-------------|
342//! | [`ast`] | Abstract syntax tree types for expressions and equations |
343//! | [`parser`] | String → AST conversion with chumsky |
344//! | [`solver`] | Symbolic equation solving |
345//! | [`equation_system`] | Multi-equation system solver |
346//! | [`numerical`] | Numerical root-finding methods |
347//! | [`integration`] | Symbolic integration |
348//! | [`limits`] | Limit evaluation with L'Hôpital's rule |
349//! | [`ode`] | First and second-order ODE solving |
350//! | [`series`] | Taylor, Laurent, asymptotic series |
351//! | [`special`] | Gamma, beta, error functions |
352//! | [`approximations`] | Small angle and scaled approximations |
353//! | [`transforms`] | Coordinate system conversions |
354//! | [`dimensions`] | Units and dimensional analysis |
355//! | [`pattern`] | Rule-based expression rewriting |
356//! | [`latex`] | LaTeX parsing and generation |
357//! | [`resolution_path`] | Step-by-step solution tracking |
358//! | [`guides`] | User tutorials and workflows |
359//!
360//! ## Running Tests
361//!
362//! ```bash
363//! cargo test # All tests
364//! cargo test --doc # Documentation examples only
365//! cargo test --release # Optimized build
366//! ```
367
368#![warn(missing_docs)]
369#![warn(clippy::all)]
370#![warn(clippy::pedantic)]
371#![allow(clippy::missing_errors_doc)]
372#![allow(clippy::missing_panics_doc)]
373
374// Public module exports
375pub mod approximations;
376pub mod ast;
377pub mod dimensions;
378pub mod equation_system;
379pub mod inequality;
380pub mod integration;
381pub mod latex;
382pub mod limits;
383pub mod matrix;
384pub mod numerical;
385pub mod ode;
386pub mod optimization;
387pub mod parser;
388pub mod partial_fractions;
389pub mod pattern;
390pub mod precision;
391pub mod resolution_path;
392pub mod series;
393pub mod solver;
394pub mod special;
395pub mod transforms;
396pub mod trigonometric;
397
398// User guides for common workflows
399pub mod guides;
400
401// FFI module (conditionally compiled for FFI builds)
402#[cfg(feature = "ffi")]
403pub mod ffi;
404
405// Re-export commonly used types at crate root for convenience
406pub use approximations::{
407 apply_small_angle_approx, compute_approximation_error, generate_approximation_step,
408 is_approximation_valid, optimize_pythagorean, select_exp_scaling, ApproxResult, ApproxType,
409 ScaledExpForm,
410};
411pub use ast::{BinaryOp, Equation, Expression, Function, UnaryOp, Variable};
412pub use dimensions::{Dimension, Quantity, Unit, UnitRegistry};
413pub use equation_system::{
414 broyden_system,
415 fixed_point_system,
416 newton_raphson_system,
417 residual_norm,
418 solve_linear_system_lu,
419 validate_jacobian,
420 BroydenSolver,
421 Constraint,
422 ConvergenceBehavior,
423 ConvergenceDiagnostics,
424 DependencyGraph,
425 EquationSystem,
426 EquationType,
427 FixedPointSolver,
428 IntegralInfo,
429 MultiEquationSolution,
430 MultiEquationSolver,
431 NamedEquation,
432 NewtonRaphsonSolver,
433 // Nonlinear system solver
434 NonlinearSystem,
435 NonlinearSystemConfig,
436 NonlinearSystemSolver,
437 NonlinearSystemSolverError,
438 NonlinearSystemSolverResult,
439 ODEInfo,
440 SmartNonlinearSystemSolver,
441 SolutionStrategy,
442 SolutionValue,
443 SolveMethod,
444 SolveStep,
445 SolverConfig,
446 StepResult,
447 SystemContext,
448 SystemError,
449 SystemOperation,
450 SystemResolutionPath,
451 SystemStep,
452};
453pub use inequality::{
454 solve_inequality, solve_system, Bound, Inequality, InequalityError, IntervalSolution,
455};
456pub use integration::{
457 definite_integral, definite_integral_with_fallback, definite_integral_with_steps,
458 improper_integral_to_infinity, integrate, integrate_by_parts, integrate_by_parts_with_steps,
459 integrate_by_substitution, integrate_with_substitution, numerical_integrate,
460 tabular_integration, IntegrationError,
461};
462pub use latex::{parse_latex, parse_latex_equation};
463pub use matrix::{BracketStyle, MatrixError, MatrixExpr};
464pub use numerical::{NumericalConfig, NumericalSolution, SmartNumericalSolver};
465pub use ode::{
466 solve_characteristic_equation, solve_ivp, solve_linear, solve_second_order_homogeneous,
467 solve_second_order_ivp, solve_separable, CharacteristicRoots, FirstOrderODE, ODEError,
468 ODESolution, RootType, SecondOrderODE, SecondOrderSolution,
469};
470pub use optimization::{
471 analyze_expression, find_multiplicative_chains, optimize_computation_order, to_manual_steps,
472 track_precision, ComputationStep, ManualStep, MultiplicativeChain, OperationConfig,
473 OperationType, PrecisionReport, StepOperand,
474};
475pub use parser::{parse_equation, parse_expression};
476pub use partial_fractions::{
477 decompose, is_polynomial, is_rational_function, DecomposeError, PartialFractionResult,
478 PartialFractionTerm,
479};
480pub use precision::{EvalContext, EvalError, PrecisionMode, RoundingMode, Value};
481pub use resolution_path::{
482 Operation, OperationCounts, PathStatistics, ResolutionPath, ResolutionPathBuilder,
483 ResolutionStep, Verbosity,
484};
485pub use series::{
486 arctan_series,
487 asymptotic,
488 binomial_series,
489 // Series arithmetic (composition and reversion)
490 compose_series,
491 compute_nth_derivative,
492 cos_series,
493 evaluate_at,
494 exp_series,
495 factorial,
496 factorial_expr,
497 find_singularities,
498 laurent,
499 limit_via_asymptotic,
500 ln_1_plus_x_series,
501 maclaurin,
502 pole_order,
503 residue,
504 reversion,
505 sin_series,
506 taylor,
507 // Asymptotic expansions
508 AsymptoticDirection,
509 AsymptoticSeries,
510 AsymptoticTerm,
511 BigO,
512 // Laurent series support
513 LaurentSeries,
514 RemainderTerm,
515 Series,
516 SeriesError,
517 SeriesResult,
518 SeriesTerm,
519 Singularity,
520 SingularityType,
521};
522pub use solver::{LinearSystem, SmartSolver, Solution, Solver, SystemSolution, SystemSolver};
523pub use special::{beta, erf, erfc, gamma, SpecialFunctionError, SpecialFunctionResult};
524pub use transforms::{
525 Cartesian2D, Cartesian3D, ComplexOps, Cylindrical, Polar, Spherical, Transform2D,
526};
527pub use trigonometric::{
528 all_trig_rules, double_angle_rules, inverse_rules, parity_rules, product_to_sum_rules,
529 pythagorean_rules, quotient_rules, simplify_double_angle, simplify_pythagorean,
530 simplify_quotient, simplify_trig, simplify_trig_step, simplify_trig_with_steps,
531 special_value_rules,
532};
533
534/// Library version information.
535pub const VERSION: &str = env!("CARGO_PKG_VERSION");
536
537/// Library name.
538pub const NAME: &str = env!("CARGO_PKG_NAME");
539
540/// Get library version string.
541pub fn version() -> &'static str {
542 VERSION
543}
544
545/// Check if library is compiled with FFI support.
546pub fn has_ffi_support() -> bool {
547 cfg!(feature = "ffi")
548}
549
550/// Unified error type for the thales library.
551///
552/// This enum provides a single error type that encompasses all possible errors
553/// that can occur within the library. It wraps error types from individual modules,
554/// allowing for consistent error handling across the entire library.
555///
556/// # Design
557///
558/// The `#[non_exhaustive]` attribute allows future versions to add new error variants
559/// without breaking existing code. Users should always include a wildcard match arm
560/// when matching on this type.
561///
562/// # Examples
563///
564/// ```rust
565/// use thales::{ThalesError, parse_expression};
566///
567/// match parse_expression("2 + x") {
568/// Ok(expr) => println!("Parsed: {:?}", expr),
569/// Err(errors) => {
570/// // parse_expression returns Vec<ParseError>, not ThalesError
571/// println!("Parse errors: {:?}", errors);
572/// }
573/// }
574/// ```
575///
576/// Future usage with unified error handling:
577///
578/// ```rust,ignore
579/// use thales::ThalesError;
580///
581/// fn process() -> Result<(), ThalesError> {
582/// // Future API will return ThalesError
583/// Ok(())
584/// }
585/// ```
586#[derive(Debug)]
587#[non_exhaustive]
588pub enum ThalesError {
589 /// Error from the parser module.
590 Parse(parser::ParseError),
591 /// Error from the solver module.
592 Solver(solver::SolverError),
593 /// Error from the series module.
594 Series(series::SeriesError),
595 /// Error from the matrix module.
596 Matrix(matrix::MatrixError),
597 /// Error from the integration module.
598 Integration(integration::IntegrationError),
599 /// Error from the numerical module.
600 Numerical(numerical::NumericalError),
601 /// Error from the limits module.
602 Limits(limits::LimitError),
603 /// Error from the ODE module.
604 ODE(ode::ODEError),
605 /// Error from the special functions module.
606 SpecialFunction(special::SpecialFunctionError),
607 /// Error from the inequality module.
608 Inequality(inequality::InequalityError),
609 /// Error from the precision module.
610 Evaluation(precision::EvalError),
611 /// Error from the partial fractions module.
612 PartialFractions(partial_fractions::DecomposeError),
613 /// Error from the LaTeX parser module.
614 LaTeXParse(latex::LaTeXParseError),
615 /// Error from the equation system module.
616 System(equation_system::SystemError),
617 /// Error from the nonlinear system solver.
618 NonlinearSystem(equation_system::NonlinearSystemSolverError),
619}
620
621impl std::fmt::Display for ThalesError {
622 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
623 match self {
624 ThalesError::Parse(e) => write!(f, "Parse error: {}", e),
625 ThalesError::Solver(e) => write!(f, "Solver error: {:?}", e),
626 ThalesError::Series(e) => write!(f, "Series error: {}", e),
627 ThalesError::Matrix(e) => write!(f, "Matrix error: {}", e),
628 ThalesError::Integration(e) => write!(f, "Integration error: {}", e),
629 ThalesError::Numerical(e) => write!(f, "Numerical error: {:?}", e),
630 ThalesError::Limits(e) => write!(f, "Limits error: {}", e),
631 ThalesError::ODE(e) => write!(f, "ODE error: {}", e),
632 ThalesError::SpecialFunction(e) => write!(f, "Special function error: {}", e),
633 ThalesError::Inequality(e) => write!(f, "Inequality error: {}", e),
634 ThalesError::Evaluation(e) => write!(f, "Evaluation error: {}", e),
635 ThalesError::PartialFractions(e) => write!(f, "Partial fractions error: {}", e),
636 ThalesError::LaTeXParse(e) => write!(f, "LaTeX parse error: {}", e),
637 ThalesError::System(e) => write!(f, "System error: {:?}", e),
638 ThalesError::NonlinearSystem(e) => write!(f, "Nonlinear system error: {:?}", e),
639 }
640 }
641}
642
643impl std::error::Error for ThalesError {
644 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
645 match self {
646 ThalesError::Parse(e) => Some(e),
647 ThalesError::Series(e) => Some(e),
648 ThalesError::Matrix(e) => Some(e),
649 ThalesError::Integration(e) => Some(e),
650 ThalesError::Limits(e) => Some(e),
651 ThalesError::ODE(e) => Some(e),
652 ThalesError::SpecialFunction(e) => Some(e),
653 ThalesError::Inequality(e) => Some(e),
654 ThalesError::Evaluation(e) => Some(e),
655 ThalesError::PartialFractions(e) => Some(e),
656 ThalesError::LaTeXParse(e) => Some(e),
657 // These error types don't implement std::error::Error
658 ThalesError::Solver(_) => None,
659 ThalesError::Numerical(_) => None,
660 ThalesError::System(_) => None,
661 ThalesError::NonlinearSystem(_) => None,
662 }
663 }
664}
665
666// Implement From conversions for each error type
667impl From<parser::ParseError> for ThalesError {
668 fn from(e: parser::ParseError) -> Self {
669 ThalesError::Parse(e)
670 }
671}
672
673impl From<solver::SolverError> for ThalesError {
674 fn from(e: solver::SolverError) -> Self {
675 ThalesError::Solver(e)
676 }
677}
678
679impl From<series::SeriesError> for ThalesError {
680 fn from(e: series::SeriesError) -> Self {
681 ThalesError::Series(e)
682 }
683}
684
685impl From<matrix::MatrixError> for ThalesError {
686 fn from(e: matrix::MatrixError) -> Self {
687 ThalesError::Matrix(e)
688 }
689}
690
691impl From<integration::IntegrationError> for ThalesError {
692 fn from(e: integration::IntegrationError) -> Self {
693 ThalesError::Integration(e)
694 }
695}
696
697impl From<numerical::NumericalError> for ThalesError {
698 fn from(e: numerical::NumericalError) -> Self {
699 ThalesError::Numerical(e)
700 }
701}
702
703impl From<limits::LimitError> for ThalesError {
704 fn from(e: limits::LimitError) -> Self {
705 ThalesError::Limits(e)
706 }
707}
708
709impl From<ode::ODEError> for ThalesError {
710 fn from(e: ode::ODEError) -> Self {
711 ThalesError::ODE(e)
712 }
713}
714
715impl From<special::SpecialFunctionError> for ThalesError {
716 fn from(e: special::SpecialFunctionError) -> Self {
717 ThalesError::SpecialFunction(e)
718 }
719}
720
721impl From<inequality::InequalityError> for ThalesError {
722 fn from(e: inequality::InequalityError) -> Self {
723 ThalesError::Inequality(e)
724 }
725}
726
727impl From<precision::EvalError> for ThalesError {
728 fn from(e: precision::EvalError) -> Self {
729 ThalesError::Evaluation(e)
730 }
731}
732
733impl From<partial_fractions::DecomposeError> for ThalesError {
734 fn from(e: partial_fractions::DecomposeError) -> Self {
735 ThalesError::PartialFractions(e)
736 }
737}
738
739impl From<latex::LaTeXParseError> for ThalesError {
740 fn from(e: latex::LaTeXParseError) -> Self {
741 ThalesError::LaTeXParse(e)
742 }
743}
744
745impl From<equation_system::SystemError> for ThalesError {
746 fn from(e: equation_system::SystemError) -> Self {
747 ThalesError::System(e)
748 }
749}
750
751impl From<equation_system::NonlinearSystemSolverError> for ThalesError {
752 fn from(e: equation_system::NonlinearSystemSolverError) -> Self {
753 ThalesError::NonlinearSystem(e)
754 }
755}
756
757// TODO: Add prelude module with commonly used imports
758// TODO: Add error types module with unified error handling
759// TODO: Add traits module with common trait definitions
760// TODO: Add macro module for expression DSL
761// TODO: Add serde support for serialization
762// TODO: Add wasm support for web usage
763// TODO: Add Python bindings via PyO3
764// TODO: Add comprehensive integration tests
765// TODO: Add performance benchmarks
766// TODO: Add documentation examples that compile and run
767
768#[cfg(test)]
769mod tests {
770 use super::*;
771
772 #[test]
773 fn test_thales_error_from_parse_error() {
774 let parse_err = parser::ParseError::UnexpectedCharacter { pos: 0, found: 'x' };
775 let thales_err: ThalesError = parse_err.clone().into();
776
777 match thales_err {
778 ThalesError::Parse(e) => assert_eq!(e, parse_err),
779 _ => panic!("Expected ThalesError::Parse"),
780 }
781 }
782
783 #[test]
784 fn test_thales_error_from_solver_error() {
785 let solver_err = solver::SolverError::NoSolution;
786 let thales_err: ThalesError = solver_err.clone().into();
787
788 match thales_err {
789 ThalesError::Solver(e) => assert_eq!(e, solver_err),
790 _ => panic!("Expected ThalesError::Solver"),
791 }
792 }
793
794 #[test]
795 fn test_thales_error_from_numerical_error() {
796 let num_err = numerical::NumericalError::NoConvergence;
797 let thales_err: ThalesError = num_err.clone().into();
798
799 match thales_err {
800 ThalesError::Numerical(e) => assert_eq!(e, num_err),
801 _ => panic!("Expected ThalesError::Numerical"),
802 }
803 }
804
805 #[test]
806 fn test_thales_error_display() {
807 let solver_err = solver::SolverError::NoSolution;
808 let thales_err: ThalesError = solver_err.into();
809 let display_str = format!("{}", thales_err);
810
811 assert!(display_str.contains("Solver error"));
812 assert!(display_str.contains("NoSolution"));
813 }
814
815 #[test]
816 fn test_thales_error_source() {
817 use std::error::Error;
818
819 let parse_err = parser::ParseError::UnexpectedCharacter { pos: 5, found: '!' };
820 let thales_err: ThalesError = parse_err.into();
821
822 assert!(thales_err.source().is_some());
823 }
824
825 #[test]
826 fn test_thales_error_from_integration_error() {
827 let int_err = integration::IntegrationError::DivisionByZero;
828 let thales_err: ThalesError = int_err.clone().into();
829
830 match thales_err {
831 ThalesError::Integration(e) => assert_eq!(e, int_err),
832 _ => panic!("Expected ThalesError::Integration"),
833 }
834 }
835
836 #[test]
837 fn test_thales_error_from_matrix_error() {
838 let matrix_err = matrix::MatrixError::EmptyMatrix;
839 let thales_err: ThalesError = matrix_err.clone().into();
840
841 match thales_err {
842 ThalesError::Matrix(e) => assert_eq!(e, matrix_err),
843 _ => panic!("Expected ThalesError::Matrix"),
844 }
845 }
846}