functionx

A powerful equation parser and solver for Dart โ€” f(x) for your code.

pub package License: MIT

Features

  • ๐Ÿงฎ Expression Parsing - Strictly explicit parsing (e.g. 2*x, m*a) for maximum predictability
  • ๐Ÿ“Š Variable Extraction - Intelligently extract variables while filtering constants
  • ๐Ÿ”ข Expression Evaluation - Multi-mode evaluation (Real, Complex, and Mixed)
  • โšก Equation Solving - Algebraic and numerical solvers
  • ๐Ÿ”— System Solver - Solve systems of non-linear equations (Real & Complex)
  • ๐Ÿ“ˆ Symbolic Calculus - Differentiation and integration
  • ๐Ÿ”ฌ Auto-resolve Constants - Automatic identification of symbols like SOL, PC and BC
  • ๐Ÿ‡ฌ๐Ÿ‡ท LaTeX Support - Greek letters and subscripts, via EquationParser

Installation

Add to your pubspec.yaml:

dependencies:
  functionx: ^2.0.3

Two API tiers

This is the thing to understand before anything else.

Tier Class Use when
Primary EquationParser Almost always. Handles LaTeX, Greek letters and natural constants, and returns exact values where it can.
Core components ExpressionParser, Evaluator, Solver, SystemSolver, Cas You want one specific stage on already-clean input.

EquationParser is a faรงade over the core components that adds LaTeX cleaning and constant resolution. The lower tier does not understand LaTeX:

EquationParser.extractVariables(r'\Delta E = h*\nu');   // [DeltaE, h, nu]
ExpressionParser.extractVariables(r'\Delta E = h*\nu'); // []  โ† no LaTeX handling

The two also differ in precision. The core Solver falls back to numerical methods:

Solver.solve('F = m*a', {'F': 10, 'm': 2}, solveFor: 'a').value;
// 5.000000000032756  โ† numerically approximated

EquationParser.solve('F = m*a', {'F': 10, 'm': 2}, solveFor: 'a').solvedValue;
// 5.0                โ† exact

Quick Start

import 'package:functionx/functionx.dart';

void main() {
  // Extract variables from an equation
  final vars = EquationParser.extractVariables('y = m*x + b');
  print(vars); // [b, m, x, y]

  // Evaluate an expression
  final result = EquationParser.evaluate('x^2 + 2*x + 1', {'x': 3});
  print(result); // 16.0

  // Solve for an unknown
  final solution = EquationParser.solve(
    'F = m*a',
    {'F': 10, 'm': 2},
    solveFor: 'a',
  );
  print(solution.solvedValue); // 5.0

  // Solve a system of equations
  final system = SystemSolver.solve(['x^2 + y^2 = 1', 'y = x']);
  print(system.values); // {x: 0.7071, y: 0.7071}

  // Use physical constants
  final c = EquationParser.getConstant('SOL');
  print('${c?.name}: ${c?.value} ${c?.unit}'); // Speed of Light: 299792458.0 m/s
}

EquationParser

The primary API. Every method is static.

// Variables โ€” `excludeConstants` drops recognised constant keys
EquationParser.extractVariables('F = m*a');                          // [F, a, m]
EquationParser.extractVariables('E = m*SOL^2', excludeConstants: true);

// Evaluate (supports complex results, e.g. sqrt(-1))
EquationParser.evaluate('x^2 + y', {'x': 3, 'y': 5});                // 14.0

// Solve. Give every known value; name the unknown with `solveFor`.
final r = EquationParser.solve('y = 2*x + 3', {'x': 5.0}, solveFor: 'y');
r.solvedValue;   // the answer
r.allValues;     // every root, when there is more than one
r.steps;         // List<SolutionStep> derivation
r.error;         // non-null if solving failed

// Systems โ€” takes the equations *and* a map of already-known values
EquationParser.solveSystem(['x + y = 10', 'x - y = 2'], {}); // solvedValue: 6.0

// Constants appearing in an equation, pre-filled and ready to substitute
EquationParser.getPrefilledValues('E = m*SOL^2');                    // {SOL: 299792458.0}
EquationParser.getConstant('GC');                                   // NaturalConstant
EquationParser.naturalConstants;                                    // the whole map

// Strip LaTeX down to plain notation
EquationParser.cleanLatex(r'\Delta E = h*\nu');

solveFor is effectively required. Without it, solve returns a result whose solvedValue is null and whose error is also null โ€” it does not infer the unknown from a missing map entry.

EquationResult

Field Type Meaning
solvedValue dynamic The computed value (double or Complex)
allValues List<dynamic>? All roots, where applicable
steps List<SolutionStep> Derivation steps (type + data map)
error String? Message if solving failed

NaturalConstant

Fields: value, name, unit, symbol.

EquationParser.naturalConstants carries its own set of 37 keys, which is not the same set as the Constants class below โ€” it additionally includes the parser tokens PI, EN, IN and INF.

Expression Syntax

This parser is designed to be ergonomic but strictly explicit:

โœ… Notation ๐Ÿ“ Example
Explicit 2*x + 3*y
Parentheses 3*(x+1)*(x-1)
Complex (1+IN)*IN โ†’ -1 + i
Greek (via EquationParser) \Delta E = h*\nu
Subscripts x_1 + x_2

Subscripts may be words, not just digits: ATP_total = ATP_gly + ATP_etc parses fine.

Supported Operators

Operator Description
+ Addition
- Subtraction
* Multiplication
/ Division
^ Exponentiation

Supported Functions

All verified working: sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), sqrt(x), abs(x), log(x), ln(x), exp(x), pow(x, n).

Note that log is the natural logarithm, identical to ln โ€” log(EN) is 1.0.

Parser Tokens

Token Value
PI 3.14159...
EN 2.71828...
INF Infinity
IN i (โˆš-1)

Reserved Words & Aliases

To avoid ambiguity (like c for the speed of light vs c for a variable), functionx uses strict constant lookup. You must use the specific keys below for a symbol to resolve to a constant; common letters like c, g and h stay plain variables.

  • Functions: sin, cos, tan, asin, acos, atan, sqrt, abs, log, ln, exp, pow
  • Parser tokens: PI, EN, INF, IN
  • Natural constants (keys): SOL (Speed of Light), GC (Gravitational), PC (Planck), SG (Standard Gravity), AN (Avogadro), BC (Boltzmann), and others listed below

Avogadro's key is AN, not NA. NA is its symbol; Constants.get('NA') returns null.

Core Components

Use these when you want a single stage and your input is already plain notation.

ExpressionParser

final result = ExpressionParser.parse('y = m*x + b');
print(result.isEquation); // true
// also: result.expression, result.left, result.right

ExpressionParser.extractVariables('F = m*a'); // [F, a, m]

Evaluator

Evaluator.evaluate('x^2 + y', {'x': 3, 'y': 5}); // 14.0  (returns double)
Evaluator.evaluateNumeric('2 + 3 * 4');          // 14.0
Evaluator.evaluateMixed('(1+IN)*IN');            // -1 + i
Evaluator.canEvaluate('x + 1', {'x': 1});        // true

Solver

Returns a SolveResult with value, variable, steps (List<String>), isNumeric, error and success. Results are numerically approximated โ€” compare with a tolerance rather than for equality.

final result = Solver.solve('2*x + 5 = 11', {'x': null});
print(result.value);   // 2.9999999999752447
print(result.success); // true

SystemSolver

Returns a SystemSolveResult with values (a Map<String, Complex>), success, error and iterations.

final system = SystemSolver.solve(['x^2 + y^2 = 1', 'y = x']);
print(system.values); // {x: 0.7071, y: 0.7071}

Cas (Computer Algebra System)

Symbolic differentiation and integration. Output is unsimplified, so expect mathematically correct but verbose results:

Cas.differentiate('x^2', 'x'); // ((x^2.0) * (2.0 * (1.0 / x)))
Cas.differentiate('x^3', 'x'); // ((x^3.0) * (3.0 * (1.0 / x)))
Cas.integrate('x', 'x');       // 0.5*x^2
Cas.simplify('x + x');         // (x + x)   โ† does not collect like terms
Cas.evaluate('2 + 3');         // (2.0 + 3.0) โ† also unevaluated

Cas.simplify currently normalises structure rather than reducing an expression; do not rely on it to collapse x + x into 2*x.

Constants

A separate collection of physical and mathematical constants, indexed by key.

final c = Constants.speedOfLight;
print(c.value);  // 299792458.0
print(c.symbol); // c
print(c.unit);   // m/s
print(c.name);   // Speed of Light

Constants.get('GC')?.value;          // 6.6743e-11
Constants.search('mass');            // 6 matches

// byCategory returns Constant objects, not keys
Constants.byCategory('fundamental').map((c) => c.key); // (SOL, PC, HBAR, GC)

Categories

Category Keys
mathematical PI, EN, IN, PHI, SQRT2
fundamental SOL, PC, HBAR, GC
electromagnetic EC, VP, VPM, CC
atomic ME, MP, MN, BR, FSC, RYD, BM, NM, PEM
thermodynamic BC, AN, RG, ATM, SBC, WIE, C1, C2
quantum MFQ, CQ, JC, VK
electrochemical FC
earth SG, EM, ER
celestial SM, SR, AU, LY

INF is a parser token only โ€” it is not in Constants, and Constants.get('INF') returns null.

Common Constants

Property Key Symbol Value
Constants.speedOfLight SOL c 299792458.0 m/s
Constants.planck PC h 6.62607015e-34 Jโ‹…s
Constants.gravitationalConstant GC G 6.6743e-11 Nโ‹…mยฒ/kgยฒ
Constants.boltzmann BC kB 1.380649e-23 J/K
Constants.avogadro AN NA 6.02214076e23 1/mol
Constants.faraday FC F 96485.33212 C/mol
Constants.rydberg RYD Rโˆž 10973731.56816 1/m
Constants.standardGravity SG g 9.80665 m/sยฒ
Constants.elementaryCharge EC e 1.602176634e-19 C
Constants.coulomb CC k 8987551792.3 Nโ‹…mยฒ/Cยฒ
Constants.pi PI ฯ€ 3.141592653589793
Constants.e EN e 2.718281828459045
Constants.imaginaryUnit IN i โˆš-1 (.value is NaN)

License

MIT License - see LICENSE for details.

Libraries

functionx
A powerful math expression parser and equation solver for Dart.