Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Nonanti/mathcore/llms.txt

Use this file to discover all available pages before exploring further.

The mathcore::solver module provides symbolic and numerical equation solving through the Solver struct. Given any Expr representing a polynomial expression, Solver::solve dispatches to the appropriate exact or numerical algorithm based on the polynomial degree, returning all discovered real and complex roots. A companion factor method attempts to rewrite a polynomial as a product of its linear factors.

pub struct Solver

A zero-sized unit struct that groups all solver operations as associated functions. No instance is needed.
pub struct Solver;

solve

Solves the equation expr = 0 for the given variable, returning a Vec<Expr> containing all discovered roots. Before solving, the expression is normalized to the form expr - 0. Dispatch is based on the polynomial degree of expr in var:
DegreeStrategyOutput type
0 (constant)Evaluates the constant; infinite solutions → Err, no solutions → Ok(vec![])
1 (linear)Exact closed-form: x = -b / aExpr::Number
2 (quadratic)Quadratic formula with full discriminant analysisExpr::Number (real) or Expr::Complex (complex conjugate pair)
≥ 3Newton-Raphson starting from multiple seed points across [-100, 100]; duplicates within 1e-6 are deduplicatedExpr::Number
For the Newton-Raphson path, symbolic differentiation (via Calculus::differentiate) is used to compute the derivative analytically. Convergence tolerance is 1e-10 with a maximum of 100 iterations per seed.
pub fn solve(equation: &Expr, var: &str) -> Result<Vec<Expr>, MathError>
equation
&Expr
required
The expression to set equal to zero. This may be a raw polynomial expression such as x^2 - 4, or an explicit subtraction node of the form lhs - rhs representing lhs = rhs. The solver normalises both forms automatically.
var
&str
required
The name of the variable to solve for. All other Expr::Symbol nodes in the expression are treated as parameters.
Returns Ok(Vec<Expr>) containing the roots (possibly empty if no real roots exist), or Err(MathError::SolverError) in degenerate cases such as infinite solutions for a zero-degree expression.
use mathcore::solver::Solver;
use mathcore::parser::Parser;
use mathcore::types::Expr;

// Linear: 2*x + 6 = 0  →  x = -3
let linear = Parser::parse("2*x + 6").unwrap();
let roots = Solver::solve(&linear, "x").unwrap();
if let Expr::Number(r) = roots[0] {
    assert!((r - (-3.0)).abs() < 1e-10);
}

// Quadratic: x^2 - 5*x + 6 = 0  →  x = 3, x = 2
let quad = Parser::parse("x^2 - 5*x + 6").unwrap();
let roots = Solver::solve(&quad, "x").unwrap();
assert_eq!(roots.len(), 2);

// Quadratic with complex roots: x^2 + 1 = 0  →  ±i
let complex_quad = Parser::parse("x^2 + 1").unwrap();
let roots = Solver::solve(&complex_quad, "x").unwrap();
for root in &roots {
    if let Expr::Complex(c) = root {
        println!("root: {} + {}i", c.re, c.im);
    }
}

// Higher-degree: x^3 - 6*x^2 + 11*x - 6 = 0  →  x ≈ 1, 2, 3
let cubic = Parser::parse("x^3 - 6*x^2 + 11*x - 6").unwrap();
let roots = Solver::solve(&cubic, "x").unwrap();
println!("Cubic roots: {:?}", roots);

factor

Attempts to express expr as a product of its linear factors. For quadratic expressions in a single variable, the roots are found via solve and the result is returned as (x - r1) * (x - r2). Expressions that are not quadratics in a single variable, or quadratics whose roots are not purely real Expr::Number values, are returned unchanged.
pub fn factor(expr: &Expr) -> Result<Expr, MathError>
expr
&Expr
required
The polynomial expression to factor. Must be an Expr::Binary node with Add or Subtract at the top level; other forms are returned as-is without error.
Returns Ok(Expr) containing either the factored product (x - r1) * (x - r2) for a factorable quadratic, or the original expression unchanged when factoring is not applicable.
use mathcore::solver::Solver;
use mathcore::parser::Parser;

// Factor x^2 - 5*x + 6  →  (x - 3) * (x - 2)
let expr = Parser::parse("x^2 - 5*x + 6").unwrap();
let factored = Solver::factor(&expr).unwrap();
println!("{}", factored); // (x - 3) * (x - 2)

// Non-factorable over the reals is returned unchanged
let expr2 = Parser::parse("x^2 + 1").unwrap();
let result = Solver::factor(&expr2).unwrap();
println!("{}", result); // x^2 + 1

// Multi-variable expressions are returned unchanged
let expr3 = Parser::parse("x^2 + y^2").unwrap();
let result3 = Solver::factor(&expr3).unwrap();
println!("{}", result3);

Build docs developers (and LLMs) love