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.

MathCore has first-class support for complex numbers throughout its expression system. Complex values are represented by the Expr::Complex variant, backed by num_complex::Complex64 — a pair of 64-bit floats for the real and imaginary parts. You can write complex literals directly in expression strings, perform arithmetic on them through evaluate, and receive complex results automatically when solving equations whose roots are not real, all without any special configuration.

The Expr::Complex variant

The core expression type in MathCore is the Expr enum defined in mathcore::types. Its Complex variant wraps a num_complex::Complex64 value:
use mathcore::types::Expr;
use num_complex::Complex64;

// Construct a complex Expr directly
let z = Expr::Complex(Complex64::new(3.0, 4.0));
println!("{}", z); // 3+4i
Complex64 is an alias for Complex<f64>, so it carries the full num-complex trait implementations including Add, Sub, Mul, Div, Norm, and Conj.

Parsing complex literals

The MathCore parser recognises complex literals in the form a+bi or a-bi directly inside expression strings. No wrapper or special prefix is required.
LiteralReal partImaginary part
3+4i3.04.0
2-1i2.0-1.0
0+1i0.01.0
5i0.05.0
use mathcore::MathCore;

let expr = MathCore::parse("3+4i").unwrap();
println!("{}", expr); // 3+4i

Evaluating complex expressions

Use MathCore::evaluate (which returns Result<Expr, MathError>) rather than MathCore::calculate when working with complex numbers. evaluate can return any Expr variant, including Expr::Complex, whereas calculate returns f64 and will error if the result is not a real number.
use mathcore::MathCore;

let math = MathCore::new();

// Complex multiplication: (3+4i)(2-i) = 6 - 3i + 8i - 4i² = 10 + 5i
let result = math.evaluate("(3+4i) * (2-i)").unwrap();
println!("{}", result); // 10+5i
MathCore::calculate returns Result<f64, MathError> and will return Err(MathError::InvalidOperation) if the evaluated result is an Expr::Complex. Always use evaluate when your expression may produce a complex value.

Complex roots from solve

MathCore::solve automatically returns Expr::Complex roots when the discriminant of a quadratic is negative. You do not need to opt in — complex roots are part of the standard Vec<Expr> return value.
use mathcore::MathCore;

// x^2 + 1 = 0 has no real roots; MathCore returns complex conjugate pair
let roots = MathCore::solve("x^2 + 1", "x").unwrap();
// roots: [Complex(0+1i), Complex(0-1i)]

for root in &roots {
    println!("{}", root);
}
// 0+1i
// 0-1i
The complex roots for a quadratic with negative discriminant Δ = b² - 4ac are computed as:
real = -b / (2a)
imag = √(-Δ) / (2a)
roots = [real + imag·i,  real - imag·i]

Full example

use mathcore::MathCore;

let math = MathCore::new();

// Parse and display a complex literal
let z = MathCore::parse("3+4i").unwrap();
println!("Parsed: {}", z); // 3+4i

// Arithmetic on complex expressions
let result = math.evaluate("(3+4i) * (2-i)").unwrap();
println!("{}", result); // 10+5i

let result = math.evaluate("(1+2i) + (3-4i)").unwrap();
println!("{}", result); // 4-2i

// Solve equations with complex roots
let roots = MathCore::solve("x^2 + 1", "x").unwrap();
println!("Roots of x^2 + 1 = 0:");
for root in &roots {
    println!("  {}", root);
}
// 0+1i
// 0-1i

How complex numbers are displayed

Expr::Complex implements Display. The sign between the real and imaginary parts follows the sign of the imaginary component directly from the source:
// From types/mod.rs
Expr::Complex(c) => {
    if c.im >= 0.0 {
        write!(f, "{}+{}i", c.re, c.im)
    } else {
        write!(f, "{}{}i", c.re, c.im)  // negative sign is part of c.im
    }
}
ValueDisplay
Complex64::new(3.0, 4.0)3+4i
Complex64::new(3.0, -4.0)3-4i
Complex64::new(0.0, 1.0)0+1i
Complex64::new(0.0, -1.0)0-1i

Using Complex64 directly alongside MathCore

Since MathCore re-exports through num_complex, you can use Complex64 directly in your own code and pass constructed values back into Expr:
use mathcore::types::Expr;
use num_complex::Complex64;

// Build a complex Expr from a known value
let magnitude = 5.0_f64;
let angle = std::f64::consts::FRAC_PI_4; // 45 degrees
let z = Complex64::new(magnitude * angle.cos(), magnitude * angle.sin());

let expr = Expr::Complex(z);
println!("{}", expr); // approximately 3.535...+3.535...i
num_complex::Complex64 implements norm() (the modulus |z|) and conj() (the conjugate). If you need these operations on the result of MathCore::evaluate, pattern-match on Expr::Complex(c) to extract the Complex64 and call those methods directly.

Pattern-matching on complex results

When you need to branch on whether a result is real or complex, match on the Expr variants returned by evaluate or solve:
use mathcore::{MathCore, Expr};

let roots = MathCore::solve("x^2 + 4", "x").unwrap();

for root in roots {
    match root {
        Expr::Number(n) => println!("Real root: {}", n),
        Expr::Complex(c) => println!("Complex root: {} + {}i", c.re, c.im),
        _ => {}
    }
}
// Complex root: 0 + 2i
// Complex root: 0 + -2i
MathCore::calculate and evaluate_with_vars both return f64 and will surface a MathError::InvalidOperation error if the result is complex. Use MathCore::evaluate (returns Expr) whenever there is a chance the expression evaluates to a complex number.

Build docs developers (and LLMs) love