fixdec
High-performance fixed-point decimal arithmetic for financial calculations and cryptocurrency.
fixdec provides two blazingly fast decimal types with fixed precision, optimized for performance-critical applications where the precision requirements are known at compile time. If you need configurable precision at runtime, use rust_decimal. If you need maximum speed with fixed precision, use fixdec.
When to Use fixdec
✅ Use fixdec when:
- You need maximum performance in financial calculations
- Your precision requirements are fixed and known (8 or 12 decimal places)
- You're building high-frequency trading systems
- You're working with cryptocurrency (DeFi, DEX, pricing engines)
- You need
no_stdsupport for embedded or WASM - You want exact decimal arithmetic without floating-point errors
❌ Don't use fixdec when:
- You need configurable precision at runtime
- You need more than 12 decimal places
- You need arbitrary precision arithmetic
- Performance is not a critical concern
Performance
fixdec is designed for speed. Here's how it compares to rust_decimal:
| Operation | D64 | rust_decimal | Speedup |
|---|---|---|---|
| Addition | 0.62 ns | 7.51 ns | 12x faster |
| Subtraction | 0.60 ns | 7.53 ns | 12.5x faster |
| Multiplication | 1.24 ns | 7.57 ns | 6x faster |
| Division | 3.70 ns | 21.29 ns | 5.7x faster |
| Square root | 102.87 ns | 750.89 ns | 7.3x faster |
| Power (powi) | 5.15 ns | 42.67 ns | 8.3x faster |
| Bincode serialize | 6.0 ns | 62.9 ns | 10.5x faster |
Benchmarks run on [your system specs]. See benches/ for details.
Types
D64 - Traditional Finance
- Storage: 64-bit (8 bytes)
- Precision: 8 decimal places (0.00000001)
- Range: ±92,233,720,368.54775807 (±92 billion)
- Use cases: Traditional financial applications & trading systems
D96 - Cryptocurrency
- Storage: 128-bit (16 bytes, but only 96 bits used)
- Precision: 12 decimal places (0.000000000001)
- Range: ±39,614,081,257,132.168796771975 (±39 trillion)
- Use cases: Cryptocurrency pricing, DeFi protocols, gas calculations, extreme price ranges
Quick Start
Add to your Cargo.toml:
[]
= "0.1"
Basic Usage
use D64;
use FromStr;
// Create from strings
let price = D64from_str?;
let quantity = D64from_i32;
// Fast arithmetic
let total = price * quantity;
assert_eq!;
// Checked arithmetic
let result = price.checked_mul.ok_or?;
// Financial operations
let fee = total.percent_of?; // 0.1% fee
Cryptocurrency Example
use D96;
use FromStr;
// High precision for crypto
let eth_price = D96from_str?;
let amount = D96from_str?;
let total_value = eth_price * amount;
// Built-in crypto constants
let gas_price = D96from_i64 * D96GWEI; // 50 gwei
let tx_value = D96from_str?; // 1 satoshi equivalent
Features
Core Features
- Fixed precision, maximum speed: Compile-time precision means zero runtime overhead
- Exact decimal math: No floating-point rounding errors
- Comprehensive arithmetic: Checked, saturating, and wrapping variants
- Financial constants: Basis points, bond fractions (32nds, 64ths), percentages
- Crypto constants: Satoshi, gwei, microGwei for blockchain applications
Optimizations
- Reciprocal multiplication: Uses "magic division" with precomputed constants
- Fast string parsing: SWAR (SIMD Within A Register) techniques
- Branchless validation: Optimized digit checking
- Binary serialization: Raw integer encoding for minimal overhead
Platform Support
no_stdcompatible: Works in embedded systems and WebAssembly- Optional
alloc: ForVecandStringsupport - Optional
std: ForErrortrait and standard library features - Serde support: Efficient JSON and binary serialization
Feature Flags
[]
= { = "0.1", = ["serde"] }
| Feature | Description |
|---|---|
default |
No additional features (pure no_std) |
alloc |
Enable Vec and String support |
std |
Enable standard library and Error trait |
serde |
Enable Serde serialization (requires alloc) |
full |
Enable all features |
API Overview
Construction
// From integers
D64from_i32 // Always succeeds
D64from_i64? // Checked, may overflow
D64from_u64? // Checked
// From strings (exact)
D64from_str? // Errors if > 8 decimals
D64from_str_lossy? // Rounds to 8 decimals
// From floats (lossy)
D64from_f64? // May lose precision
// From raw scaled values (advanced)
D64from_raw // 123.45 in raw form
// From mantissa and scale (rust_decimal compatibility)
D64with_scale? // 123.45 (mantissa=12345, scale=2)
Arithmetic Operations
// Standard operators (panic on overflow)
let z = x + y;
let z = x - y;
let z = x * y;
let z = x / y;
// Checked (returns Option)
x.checked_add?
x.checked_sub?
x.checked_mul?
x.checked_div?
// Saturating (clamps to min/max)
x.saturating_add
x.saturating_sub
x.saturating_mul
x.saturating_div
// Wrapping (wraps on overflow)
x.wrapping_add
x.wrapping_sub
x.wrapping_mul
x.wrapping_div
// Fast integer multiplication (quantity * price)
price.mul_i64?
// Fused multiply-add (one rounding step)
x.mul_add? // (x * y) + z
Rounding
let x = D64from_str?;
x.floor // 123.00000000
x.ceil // 124.00000000
x.round // 123.00000000 (banker's rounding)
x.round_dp // 123.46000000 (round to 2 decimals)
x.trunc // 123.00000000 (truncate)
x.fract // 0.45678900 (fractional part)
Financial Operations
// Basis points (1 bp = 0.0001)
let rate = D64from_basis_points?; // 0.005 (50 bps)
let bps = rate.to_basis_points; // 50
// Percentage calculations
let tax = price.percent_of?; // 8.5% of price
let with_markup = price.add_percent?; // price * 1.10
// Financial constants
D64BASIS_POINT // 0.0001 (1 bp)
D64HALF_BASIS_POINT // 0.00005
D64THIRTY_SECOND // 0.03125 (US Treasury bond tick)
D64SIXTY_FOURTH // 0.015625
D64CENT // 0.01 (1 cent)
D64PERCENT // 0.01 (1%)
Mathematical Operations
// Square root
let sqrt = x.sqrt?;
// Integer powers
let squared = x.powi?;
let cubed = x.powi?;
// Reciprocal
let recip = x.recip?; // 1/x
// Absolute value
let abs = x.abs;
// Sign
let sign = x.signum; // -1, 0, or 1
Serialization
With the serde feature enabled:
use ;
// JSON: uses string representation for precision
let json = to_string?;
// {"price":"1234.56","quantity":"100.00000000"}
// Bincode: uses raw i64 (extremely fast)
let bytes = serialize?;
// Just 16 bytes (8 bytes per D64)
Constants
D64 Constants
D64ZERO // 0
D64ONE // 1.0
D64TEN // 10.0
D64HUNDRED // 100.0
D64THOUSAND // 1000.0
// Currency
D64CENT // 0.01
D64MIL // 0.001
// Basis points
D64BASIS_POINT // 0.0001
D64HALF_BASIS_POINT // 0.00005
// Bond pricing
D64THIRTY_SECOND // 1/32
D64SIXTY_FOURTH // 1/64
// Legacy equity fractions
D64EIGHTH // 1/8
D64SIXTEENTH // 1/16
D96 Constants (includes all D64 constants plus)
// Cryptocurrency
D96SATOSHI // 0.00000001 (Bitcoin)
D96GWEI // 0.000000001 (Ethereum gas unit)
D96MICRO_GWEI // 0.000000000001 (minimum precision)
D96KILO_WEI // 0.000000000001 (1000 wei)
no_std Usage
fixdec works in no_std environments by default:
use D64;
// All core operations work without std
let x = D64from_i32;
let y = D64from_i32;
let z = x / y;
// String formatting requires alloc
extern crate alloc;
Real-World Examples
Portfolio P&L Calculation
use D64;
let pos = Position ;
let pnl = calculate_pnl;
assert_eq!; // $5,500 profit
DeFi Token Swap Calculation
use D96;
let amount_out = calculate_swap_output?;
Bond Price Calculation (32nds)
use D64;
// US Treasury bonds are quoted in 32nds
// e.g., "99-16" means 99 + 16/32 = 99.5
let price = parse_bond_price;
assert_eq!;
Comparison with rust_decimal
| Feature | fixdec | rust_decimal |
|---|---|---|
| Precision | Fixed (8 or 12 decimals) | Configurable (0-28 decimals) |
| Performance | 6-12x faster | Slower due to flexibility |
| Use case | Performance-critical with known precision | General purpose, configurable precision |
| no_std | ✅ Full support | ✅ Full support |
| Serialization | ✅ Optimized for binary | ✅ General purpose |
| API similarity | High (easy migration) | - |
fixdec is built for speed when you know your precision requirements. rust_decimal is built for flexibility when you need configurable precision.
Safety and Correctness
- Overflow behavior: All arithmetic operations have
checked,saturating, andwrappingvariants - No unsafe code: Pure safe Rust (except in tests)
- Extensive testing: Property-based tests with
proptestverify correctness against baseline implementations - Banker's rounding: IEEE 754 round-half-to-even for tie-breaking
Contributing
Contributions are welcome! Areas of interest:
- Performance optimizations
- Additional financial operations
- Documentation improvements
- Bug reports and fixes
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.