ordecimal
A Rust implementation of the decimalInfinite encoding by Ghislain Fourny. It encodes arbitrary-precision decimals into variable-length byte strings that preserve numerical ordering under lexicographic comparison — useful anywhere you need decimal sort keys (database indexes, range queries, etc.).
use Decimal;
let a: Decimal = "-103.2".parse.unwrap;
let b: Decimal = "0.707106".parse.unwrap;
let c = from;
// encoded bytes compare in the same order as the numbers
assert!;
assert!;
// zero-copy access to the encoded bytes
let key: & = c.as_bytes;
// round-trip back from bytes
let d = from_bytes.unwrap;
assert_eq!;
How it works
The encoding uses a STEM format (Sign, exponent sign (T), Exponent, Mantissa):
| Field | Size | Description |
|---|---|---|
| S | 2 bits | 00 = negative, 01 = −0, 10 = +0 or positive, 11 = +∞ / NaN |
| T | 1 bit | Exponent sign (flipped for negatives to preserve order) |
| E | variable | Exponent, modified Elias Gamma code (offset +2) |
| M | variable | Significand: first digit as 4-bit tetrade, then groups of 3 digits packed into 10-bit declets |
Negative significands use a 10 − m complement so that byte ordering is preserved without any post-processing.
Example encodings from the paper:
| Decimal | Binary |
|---|---|
| 0 | 10 |
| 1 | 10 100 0001 |
| −103.2 | 00 001 11 1000 1111001000 |
| 0.707106 | 10 01 0 0111 0001000111 0000111100 |
API
use ;
// from strings (plain or scientific notation)
let d: Decimal = "123.456".parse.unwrap;
let d: Decimal = "6.022e23".parse.unwrap;
// from numeric types (no intermediate string, stack-only)
let d = from;
let d = from;
let d = from;
// special values
let _ = infinity;
let _ = neg_infinity;
let _ = nan;
let _ = zero;
// inspect components
if let Some = d.decode
// raw bytes
let bytes = d.as_bytes; // &[u8], zero-copy
let owned = d.into_bytes; // Vec<u8>
decode() returns None for special values (±0, ±∞, NaN) — check with
is_zero(), is_nan(), is_infinity() instead.
NaN ordering
Unlike IEEE 754, Decimal gives NaN a deterministic position in the total order:
NaN == NaN is true, and NaN sorts after everything else (including +∞). This is
intentional for sort-key use cases where every value needs a well-defined position.
Serde
Enable the serde feature for Serialize / Deserialize:
= { = "0.2", = ["serde"] }
Decimals serialize as their string representation in human-readable formats (JSON, TOML) and as raw bytes in binary formats (bincode).
Reference
Ghislain Fourny. "decimalInfinite — All Decimals In Bits. No Loss. Same Order. Simple." arXiv:1506.01598, June 2015.
License
MIT OR Apache-2.0