[00]Overview

Math expressions,
arbitrary precision.

A Rust library and CLI. Fractions stay exact, integers have no ceiling, and the big ones run tens of times faster than GNU bc.

cargo add yarer

Downloads
9,522
vs GNU bc
30x to 55x
Dependencies
41 crates
yarer 0.4.1
2^64/3*3
18446744073709551616
52!/(5!*47!)
2598960
(1+1/1000000)^1000000
Eval error: the result would need about 40000000 bits, over the size limit of 1048576 bits
  (1+1/1000000)^1000000
               ^

[01]Properties

Exact, unbounded, branchless.

2^64/3 6148914691236517000
2^64/3*3 18446744073709551616

Decimals are exact

Fractions are kept as exact rationals, not floats. The printed number is rounded and ends in three zeros it does not have. The value behind it is not, so multiplying by three gives 2^64 back to the digit.

100! 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Integers have no ceiling

Whole numbers are BigInt, so 100! prints all 158 digits. And 52!/(5!*47!) gives exactly 2598960, the number of poker hands, through 68-digit numbers on the way.

S=120; K=100 (S > K) * (S - K) + (K > S) * (K - S) 20

Comparisons are numbers

A comparison gives 1 or 0, as in GNU bc. Multiply by it and you get a branch without having one. Both halves are computed, one is zeroed, and the answer is 20 either way.

[02]Usage

In a program, or in a shell.

Library

use yarer::{Expression, Session};

fn main() -> Result<(), yarer::Error> {
    let session = Session::init();
    let expr = Expression::compile("1/cos(x^2)")?;

    session.set("x", 1)?;
    println!("{}", expr.eval(&session)?);
    Ok(())
}

Compile once, evaluate as often as you like, against any value of x.

Command line

yarer -e '16*atan(1/5)-4*atan(1/239)'
3.1415926535897936
printf '2^64/3*3\n52!/(5!*47!)\n' | yarer
18446744073709551616
2598960

Machin's formula for pi. Piped input runs a line at a time, as in GNU bc, and repeated -e flags share one session. Values go to stdout, errors to stderr.

cargo install yarer builds the command line. cargo add yarer --no-default-features gives a program the evaluator alone: 41 crates instead of 74.

[03]Worked example

Black-Scholes, one line at a time.

Variables live in the session, so a formula can be built a line at a time and every step stays available. This is a European call priced with Black-Scholes.

The refusal at the top of the page is the same idea from the other side. (1+1/1000000)^1000000 needs forty million bits, and yarer knows it before computing any of them. You get an error, not a hang.

Version 0.4.1 is production ready: 196 tests, a fuzz corpus replayed on every push, and no way past the size guards.

S=100;K=100;T=1;r=0.05;sigma=0.2;
0.2
d1=(ln(S/K)+(r+sigma^2/2)*T)/(sigma*sqrt(T))
0.35
d2=d1-sigma*sqrt(T)
0.15
S*cdf(d1)-K*exp(-r*T)*cdf(d2)
10.45058357218556

[04]Reference

The whole language, on one screen.

Precedence, weakest to strongest

  1. =right
  2. orxorleft
  3. andleft
  4. notright, prefix
  5. <><=>===<>left
  6. +-left
  7. */modleft
  8. ^right
  9. - unaryright
  10. ! factorialleft, postfix
  • There is no !=. Since ! is the postfix factorial, 5!=3 would be ambiguous, so the spelling is <>.
  • and, or, xor, not and mod are reserved words in every casing, and cannot name a variable.
  • Nothing short-circuits. 0 and 1/0 is a division error, not 0, because a stack machine holds both operands before it sees the operator.
  • Precision is unbounded for arithmetic and not for functions. sqrt, ln, sin and the rest go through f64, so sqrt(2)^2 is 2.0000000000000004. Add, subtract, multiply, divide and raise to an integer power, and nothing is rounded.

Functions

  • sin
  • cos
  • tan
  • asin
  • acos
  • atan
  • ln
  • log
  • abs
  • sqrt
  • max
  • min
  • floor
  • ceil
  • round
  • exp
  • pdf
  • cdf

Matched case-insensitively. Arguments are always parenthesised.

Constants

pi
3.14159265
e
2.71828182
tau
6.28318530
phi
1.61803398
gamma
0.57721566

Held as exact rationals, not as the decimals shown here.