Rust port of rsc/fpfmt, a floating-point formatting algorithm.
Provides shortest-representation and fixed-width formatting of f64 values, as well as parsing decimal strings back to f64.
short(f: f64) -> (u64, i32)— shortest decimal that round-trips back to fparse(d: u64, p: i32) -> f64— roundd * 10^pto nearest f64parse_text(s: &[u8]) -> Option<f64>— parse a decimal string to f64fixed_width(f: f64, n: i32) -> (u64, i32)— n-digit decimal formfmt_float(s: &mut [u8], d: u64, p: i32, nd: i32) -> usize— format into bufferdigits(d: u64) -> i32— number of decimal digits
Regenerate the power-of-10 table:
cargo run -p pow10genThe core algorithm needs 10^p as a 128-bit normalized mantissa for each
exponent p in −348..=347. By default, all 696 entries are stored in a flat
lookup table (696 × 16 = 11 KB).
The small feature decomposes the lookup using 10^p = 10^(27q) × 10^r
where p = 27q + r and 0 ≤ r < 27. This replaces the single table with:
POW10_COARSE: 26 entries of(u64, u64)for10^(27q)— 416 bytesPOW10_FINE: 27 entries ofu64for10^r— 216 bytes
Fine entries need only one u64 (not two) because 10^r for r ≤ 26 is
exact at 128 bits and the low 64 bits are always zero.
At runtime, prescale multiplies the two factors back together with u128
arithmetic instead of doing a direct table lookup. This reduces Wasm binary
size from 14 KB to 4 KB with a modest formatting slowdown (~1.6x),
while parsing is unaffected. Still 2.4x faster than ryu for formatting.
fpfmt = { version = "0.2", features = ["small"] }Formatting and parsing 8 representative f64 values (1.0, 0.1, 3.14, PI, E, 1e23, 5e-324, 1.7976931348623157e308).
Measured on Apple M3 Pro, macOS 15.7.3 (aarch64):
| Task | fpfmt | fpfmt small |
ryu | stdlib |
|---|---|---|---|---|
| format (f64 → string) | 63 ns | 99 ns | 239 ns | 529 ns |
| parse (string → f64) | 690 ns | 700 ns | — | 675 ns |
cargo bench -p bench
cargo bench -p bench --features small| Configuration | Size |
|---|---|
| default | 14,379 bytes |
small |
4,175 bytes |
cargo build --target wasm32-unknown-unknown --release -p wasm-size
cargo build --target wasm32-unknown-unknown --release -p wasm-size --features small
wc -c target/wasm32-unknown-unknown/release/wasm_size.wasmSame as the original: BSD-style. See LICENSE.