libbeef: Pure Rust Arbitrary-Precision Floating-Point

Fabrice Bellard's libbf is a tiny, high-performance arbitrary-precision floating-point library written in C. Now it has a Rust port: libbeef ("Beeg Float"). The library provides full IEEE 754 semantics, transcendental functions, and decimal floating-point, all in pure Rust with zero dependencies and no_std compatibility.

What libbeef Offers

libbeef implements the same algorithms as libbf: NTT-based multiplication, Newton iteration for division/sqrt, and AGM/binary-splitting for transcendentals. It supports:

  • Full IEEE 754: signed zeros, NaN, infinities, configurable exponent width, subnormals, all five rounding modes, and all five status flags.
  • Transcendental functions: exp, log, pow, sin, cos, tan, atan, atan2, asin, acos.
  • Decimal floating point (BigDecimal) with independent base-10 arithmetic.
  • no_std compatible (requires alloc).
  • Pure Rust with zero dependencies.

Quick Example

use libbeef::format::formats;
use libbeef::Float;

type Quad = Float;

fn main() {
    let a: Quad = "3.14159265358979323846".parse().unwrap();
    let b: Quad = "2.71828182845904523536".parse().unwrap();
    let result = (a * b).sin();
    println!("{result}");
    // 0.773942685266708278263054855332479932...
}

The Float type pairs a value with a compile-time format, so arithmetic and transcendental operations automatically use the specified precision and rounding mode—no format argument at every call site.

Performance Benchmarks

libbeef tracks the C libbf's throughput with constant-factor overhead from Rust's bounds checking and allocation model. Below are key benchmarks from the project's documentation:

op256 bits30,000 bits300,000 bitsvs libbfvs rug (GMP/MPFR)
mul6.784100 ns/limb1.3–2.0×0.9–1.3×
div17.3515659 ns/limb1.1–1.4×2.6–3.5×
sqrt38.3384597 ns/limb1.2–1.3×3.2–4.3×
sin1051— ns/limb0.7× (faster)3.6×

The mul row is the most informative: a quadratic algorithm would show ~10× growth per decade of operand size, but libbeef grows 4.2× then 1.2×—the O(n log n) NTT envelope. At 300k bits, libbeef is ~2× libbf and 1.3× GMP, while being 4× faster than num-bigint's schoolbook/Toom multiplication.

For transcendentals, libbeef matches or beats the C libbf on sin/cos/tan/pow and is within 15% on log/atan. The uniform 3–5× gap to MPFR is algorithmic (MPFR uses different, better algorithms; the C libbf shows the same gap). Division and sqrt show a larger constant-factor gap to GMP/MPFR (~3×) due to libbf's Newton-reciprocal approach vs. GMP's tuned divide-and-conquer.

Why libbeef?

  1. Pure Rust, no system dependencies. rug/GMP requires a C compiler, system GMP/MPFR libraries, and a build script. libbeef is a single cargo add with no build.rs, -lm, or pkg-config. It builds on any target rustc supports—including WASM, embedded, and cross-compilation—with zero configuration.

  2. Small binary footprint. With GMP/MPFR statically linked, a trivial program that multiplies two numbers and computes sin produces:

LibraryBinary size (stripped)
libbeef482 KiB
num-bigint (integers only, no trig)448 KiB
malachite (integers only, no trig)658 KiB
rug (GMP + MPFR statically linked)680 KiB

libbeef delivers full floating-point arithmetic and transcendentals in less space than malachite or rug need for integers alone.

  1. Correct and complete. libbeef passes libbf's own verification suite across every operation, precision, and rounding mode. It implements IEEE 754 correctly-rounded arithmetic with configurable exponent width and subnormals.

  2. no_std ready. Only requires alloc. No file I/O, no threads, no system calls beyond allocation.

  3. More permissive license. libbeef is MIT-licensed, while GMP/MPFR are LGPL. This makes it a better choice for license-sensitive projects.

When to Use Something Else

  • Maximum throughput at large precisions (>10k bits): GMP/MPFR (via rug) has a heavily tuned FFT and Toom-Cook stack with ~2–3× better constants for multiplication and ~3× for division. If raw ns/op at million-bit precision is the bottleneck, use rug.
  • Integer-only workloads: If you never need floating point, rounding, or transcendentals, num-bigint or malachite give you a simpler API focused purely on integers.
  • Decimal arithmetic at scale: libbeef's decimal path is functional but not yet performance-tuned (it routes through binary conversion rather than native base-10⁹ kernels).

Build & Test

cargo build                    # build (default features: std)
cargo test                     # run all tests
cargo test --test bftest       # libbf verification suite (quick, single-seed)
cargo doc --open               # generate and view API docs

Features

FeatureDescription
std (default)Enables std support
num-traitsTrait impls for the num ecosystem
num-integerAdditional num integer traits
serdeSerialization support

Next Steps

Try libbeef in your next Rust project that needs arbitrary-precision floating-point. If you're currently using rug/GMP, evaluate whether the convenience of a pure Rust dependency outweighs the performance edge at very high precisions. For most applications below 10k bits, libbeef offers competitive performance with zero build complexity.