#![warn(missing_docs)]
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_panics_doc)]
pub mod approximations;
pub mod ast;
pub mod dimensions;
pub mod equation_system;
pub mod fourier;
pub mod inequality;
pub mod integration;
pub mod latex;
pub mod limits;
pub mod mathlex_bridge;
pub mod matrix;
pub mod numerical;
pub mod ode;
pub mod ode_higher;
pub mod optimization;
pub mod parser;
pub mod partial_fractions;
pub mod pattern;
pub mod precision;
pub mod resolution_path;
pub mod runge_kutta;
pub mod series;
pub mod simplification_rules;
pub mod solver;
pub mod special;
pub mod transforms;
pub mod trigonometric;
pub mod guides;
#[cfg(feature = "lapack")]
pub mod lapack;
#[cfg(feature = "ffi")]
pub mod ffi;
pub use approximations::{
apply_small_angle_approx, compute_approximation_error, generate_approximation_step,
is_approximation_valid, optimize_pythagorean, select_exp_scaling, ApproxResult, ApproxType,
ScaledExpForm,
};
pub use ast::{BinaryOp, Equation, Expression, Function, UnaryOp, Variable};
pub use dimensions::{Dimension, Quantity, Unit, UnitRegistry};
pub use equation_system::{
broyden_system,
fixed_point_system,
newton_raphson_system,
residual_norm,
solve_linear_system_lu,
validate_jacobian,
BroydenSolver,
Constraint,
ConvergenceBehavior,
ConvergenceDiagnostics,
DependencyGraph,
EquationSystem,
EquationType,
FixedPointSolver,
IntegralInfo,
MultiEquationSolution,
MultiEquationSolver,
NamedEquation,
NewtonRaphsonSolver,
NonlinearSystem,
NonlinearSystemConfig,
NonlinearSystemSolver,
NonlinearSystemSolverError,
NonlinearSystemSolverResult,
ODEInfo,
SmartNonlinearSystemSolver,
SolutionStrategy,
SolutionValue,
SolveMethod,
SolveStep,
SolverConfig,
StepResult,
SystemContext,
SystemError,
SystemOperation,
SystemResolutionPath,
SystemStep,
};
pub use fourier::{fourier_series, FourierSeries, FourierSeriesError, FourierSeriesResult};
pub use inequality::{
solve_inequality, solve_system, Bound, Inequality, InequalityError, IntervalSolution,
};
pub use integration::{
definite_integral, definite_integral_with_fallback, definite_integral_with_steps,
improper_integral_to_infinity, integrate, integrate_by_parts, integrate_by_parts_with_steps,
integrate_by_substitution, integrate_with_substitution, numerical_integrate,
tabular_integration, IntegrationError,
};
pub use latex::{parse_latex, parse_latex_equation};
pub use matrix::{BracketStyle, MatrixError, MatrixExpr};
pub use numerical::{
BisectionMethod, BrentsMethod, NewtonRaphson, NumericalConfig, NumericalError, NumericalResult,
NumericalSolution, SmartNumericalSolver,
};
pub use ode::{
solve_characteristic_equation, solve_ivp, solve_linear, solve_second_order_homogeneous,
solve_second_order_ivp, solve_separable, CharacteristicRoots, FirstOrderODE, ODEError,
ODESolution, RootType, SecondOrderODE, SecondOrderSolution,
};
pub use optimization::{
analyze_expression, find_multiplicative_chains, optimize_computation_order, to_manual_steps,
track_precision, ComputationStep, ManualStep, MultiplicativeChain, OperationConfig,
OperationType, PrecisionReport, StepOperand,
};
pub use parser::{parse_equation, parse_equation_system, parse_expression};
pub use partial_fractions::{
decompose, is_polynomial, is_rational_function, DecomposeError, PartialFractionResult,
PartialFractionTerm,
};
pub use precision::{EvalContext, EvalError, PrecisionMode, RoundingMode, Value};
pub use resolution_path::{
Operation, OperationCounts, PathStatistics, ResolutionPath, ResolutionPathBuilder,
ResolutionStep, Verbosity,
};
pub use series::{
arctan_series,
asymptotic,
binomial_series,
compose_series,
compute_nth_derivative,
cos_series,
evaluate_at,
exp_series,
factorial,
factorial_expr,
find_singularities,
laurent,
limit_via_asymptotic,
ln_1_plus_x_series,
maclaurin,
pole_order,
residue,
reversion,
sin_series,
taylor,
AsymptoticDirection,
AsymptoticSeries,
AsymptoticTerm,
BigO,
LaurentSeries,
RemainderTerm,
Series,
SeriesError,
SeriesResult,
SeriesTerm,
Singularity,
SingularityType,
};
pub use solver::{LinearSystem, SmartSolver, Solution, Solver, SystemSolution, SystemSolver};
pub use special::{beta, erf, erfc, gamma, SpecialFunctionError, SpecialFunctionResult};
pub use transforms::{
Cartesian2D, Cartesian3D, ComplexOps, Cylindrical, Polar, Spherical, Transform2D,
};
pub use trigonometric::{
all_trig_rules, double_angle_rules, inverse_rules, parity_rules, product_to_sum_rules,
pythagorean_rules, quotient_rules, simplify_double_angle, simplify_pythagorean,
simplify_quotient, simplify_trig, simplify_trig_step, simplify_trig_with_steps,
special_value_rules,
};
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const NAME: &str = env!("CARGO_PKG_NAME");
pub fn version() -> &'static str {
VERSION
}
pub fn has_ffi_support() -> bool {
cfg!(feature = "ffi")
}
#[derive(Debug)]
#[non_exhaustive]
pub enum ThalesError {
Parse(parser::ParseError),
Solver(solver::SolverError),
Series(series::SeriesError),
Matrix(matrix::MatrixError),
Integration(integration::IntegrationError),
Numerical(numerical::NumericalError),
Limits(limits::LimitError),
ODE(ode::ODEError),
SpecialFunction(special::SpecialFunctionError),
Inequality(inequality::InequalityError),
Evaluation(precision::EvalError),
PartialFractions(partial_fractions::DecomposeError),
LaTeXParse(latex::LaTeXParseError),
System(equation_system::SystemError),
NonlinearSystem(equation_system::NonlinearSystemSolverError),
}
impl std::fmt::Display for ThalesError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ThalesError::Parse(e) => write!(f, "Parse error: {}", e),
ThalesError::Solver(e) => write!(f, "Solver error: {:?}", e),
ThalesError::Series(e) => write!(f, "Series error: {}", e),
ThalesError::Matrix(e) => write!(f, "Matrix error: {}", e),
ThalesError::Integration(e) => write!(f, "Integration error: {}", e),
ThalesError::Numerical(e) => write!(f, "Numerical error: {:?}", e),
ThalesError::Limits(e) => write!(f, "Limits error: {}", e),
ThalesError::ODE(e) => write!(f, "ODE error: {}", e),
ThalesError::SpecialFunction(e) => write!(f, "Special function error: {}", e),
ThalesError::Inequality(e) => write!(f, "Inequality error: {}", e),
ThalesError::Evaluation(e) => write!(f, "Evaluation error: {}", e),
ThalesError::PartialFractions(e) => write!(f, "Partial fractions error: {}", e),
ThalesError::LaTeXParse(e) => write!(f, "LaTeX parse error: {}", e),
ThalesError::System(e) => write!(f, "System error: {:?}", e),
ThalesError::NonlinearSystem(e) => write!(f, "Nonlinear system error: {:?}", e),
}
}
}
impl std::error::Error for ThalesError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ThalesError::Parse(e) => Some(e),
ThalesError::Series(e) => Some(e),
ThalesError::Matrix(e) => Some(e),
ThalesError::Integration(e) => Some(e),
ThalesError::Limits(e) => Some(e),
ThalesError::ODE(e) => Some(e),
ThalesError::SpecialFunction(e) => Some(e),
ThalesError::Inequality(e) => Some(e),
ThalesError::Evaluation(e) => Some(e),
ThalesError::PartialFractions(e) => Some(e),
ThalesError::LaTeXParse(e) => Some(e),
ThalesError::Solver(_) => None,
ThalesError::Numerical(_) => None,
ThalesError::System(_) => None,
ThalesError::NonlinearSystem(_) => None,
}
}
}
impl From<parser::ParseError> for ThalesError {
fn from(e: parser::ParseError) -> Self {
ThalesError::Parse(e)
}
}
impl From<solver::SolverError> for ThalesError {
fn from(e: solver::SolverError) -> Self {
ThalesError::Solver(e)
}
}
impl From<series::SeriesError> for ThalesError {
fn from(e: series::SeriesError) -> Self {
ThalesError::Series(e)
}
}
impl From<matrix::MatrixError> for ThalesError {
fn from(e: matrix::MatrixError) -> Self {
ThalesError::Matrix(e)
}
}
impl From<integration::IntegrationError> for ThalesError {
fn from(e: integration::IntegrationError) -> Self {
ThalesError::Integration(e)
}
}
impl From<numerical::NumericalError> for ThalesError {
fn from(e: numerical::NumericalError) -> Self {
ThalesError::Numerical(e)
}
}
impl From<limits::LimitError> for ThalesError {
fn from(e: limits::LimitError) -> Self {
ThalesError::Limits(e)
}
}
impl From<ode::ODEError> for ThalesError {
fn from(e: ode::ODEError) -> Self {
ThalesError::ODE(e)
}
}
impl From<special::SpecialFunctionError> for ThalesError {
fn from(e: special::SpecialFunctionError) -> Self {
ThalesError::SpecialFunction(e)
}
}
impl From<inequality::InequalityError> for ThalesError {
fn from(e: inequality::InequalityError) -> Self {
ThalesError::Inequality(e)
}
}
impl From<precision::EvalError> for ThalesError {
fn from(e: precision::EvalError) -> Self {
ThalesError::Evaluation(e)
}
}
impl From<partial_fractions::DecomposeError> for ThalesError {
fn from(e: partial_fractions::DecomposeError) -> Self {
ThalesError::PartialFractions(e)
}
}
impl From<latex::LaTeXParseError> for ThalesError {
fn from(e: latex::LaTeXParseError) -> Self {
ThalesError::LaTeXParse(e)
}
}
impl From<equation_system::SystemError> for ThalesError {
fn from(e: equation_system::SystemError) -> Self {
ThalesError::System(e)
}
}
impl From<equation_system::NonlinearSystemSolverError> for ThalesError {
fn from(e: equation_system::NonlinearSystemSolverError) -> Self {
ThalesError::NonlinearSystem(e)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_thales_error_from_parse_error() {
let parse_err = parser::ParseError::UnexpectedCharacter { pos: 0, found: 'x' };
let thales_err: ThalesError = parse_err.clone().into();
match thales_err {
ThalesError::Parse(e) => assert_eq!(e, parse_err),
_ => panic!("Expected ThalesError::Parse"),
}
}
#[test]
fn test_thales_error_from_solver_error() {
let solver_err = solver::SolverError::NoSolution;
let thales_err: ThalesError = solver_err.clone().into();
match thales_err {
ThalesError::Solver(e) => assert_eq!(e, solver_err),
_ => panic!("Expected ThalesError::Solver"),
}
}
#[test]
fn test_thales_error_from_numerical_error() {
let num_err = numerical::NumericalError::NoConvergence;
let thales_err: ThalesError = num_err.clone().into();
match thales_err {
ThalesError::Numerical(e) => assert_eq!(e, num_err),
_ => panic!("Expected ThalesError::Numerical"),
}
}
#[test]
fn test_thales_error_display() {
let solver_err = solver::SolverError::NoSolution;
let thales_err: ThalesError = solver_err.into();
let display_str = format!("{}", thales_err);
assert!(display_str.contains("Solver error"));
assert!(display_str.contains("NoSolution"));
}
#[test]
fn test_thales_error_source() {
use std::error::Error;
let parse_err = parser::ParseError::UnexpectedCharacter { pos: 5, found: '!' };
let thales_err: ThalesError = parse_err.into();
assert!(thales_err.source().is_some());
}
#[test]
fn test_thales_error_from_integration_error() {
let int_err = integration::IntegrationError::DivisionByZero;
let thales_err: ThalesError = int_err.clone().into();
match thales_err {
ThalesError::Integration(e) => assert_eq!(e, int_err),
_ => panic!("Expected ThalesError::Integration"),
}
}
#[test]
fn test_thales_error_from_matrix_error() {
let matrix_err = matrix::MatrixError::EmptyMatrix;
let thales_err: ThalesError = matrix_err.clone().into();
match thales_err {
ThalesError::Matrix(e) => assert_eq!(e, matrix_err),
_ => panic!("Expected ThalesError::Matrix"),
}
}
}