strict-num-extended
Type-safe constrained floating-point numbers for Rust
A Rust library providing zero-cost constrained floating-point types through the type system, guaranteeing safety by eliminating NaN and infinity values at compile time.
Features
- Type Safety - Catch floating-point errors at compile time, not runtime
- Zero-Cost Abstractions - No performance overhead compared to built-in types
- Comprehensive Constraints - Finite, Positive, Negative, NonZero, Normalized
- Composable Constraints - Combine multiple constraints (e.g., NonZeroPositive)
- Full Trait Implementation - PartialEq, Eq, PartialOrd, Ord, Display, Debug, arithmetic operators
- Const Support - Create compile-time constants with validation
- Option Types - Optional variants for graceful error handling
Quick Start
Add this to your Cargo.toml:
[]
= "0.1.0"
Basic Usage
use ;
// Create finite floating-point numbers (no NaN or infinity)
let finite = new.unwrap;
assert_eq!;
// Rejected: NaN and infinity are not allowed
assert!;
assert!;
// Positive numbers (>= 0)
let positive = new.unwrap;
assert!;
// Non-zero positive numbers (> 0)
let nonzero_pos = new.unwrap;
assert!;
// Arithmetic operations preserve constraints
let result = nonzero_pos + nonzero_pos;
assert_eq!;
Available Types
Single Constraint Types
| Type | Constraint | Valid Range | Example |
|---|---|---|---|
FinF32 / FinF64 |
Finite | All real numbers | -∞ < x < ∞ |
PositiveF32 / PositiveF64 |
Positive | x ≥ 0 |
0.0, 1.5, 100.0 |
NegativeF32 / NegativeF64 |
Negative | x ≤ 0 |
0.0, -1.5, -100.0 |
NonZeroF32 / NonZeroF64 |
NonZero | x ≠ 0 |
1.0, -1.0, 0.001 |
NormalizedF32 / NormalizedF64 |
Normalized | 0.0 ≤ x ≤ 1.0 |
0.0, 0.5, 1.0 |
Combined Constraint Types
| Type | Constraints | Valid Range | Example |
|---|---|---|---|
NonZeroPositiveF32 / NonZeroPositiveF64 |
Positive + NonZero | x > 0 |
0.001, 1.0, 100.0 |
NonZeroNegativeF32 / NonZeroNegativeF64 |
Negative + NonZero | x < 0 |
-0.001, -1.0, -100.0 |
How Constraints Work
All types automatically reject special floating-point values that could cause bugs:
use *;
// Finite: Excludes NaN and infinity
let valid = new; // ✓ Some(value)
let invalid = new; // ✗ None
// Positive: Finite AND non-negative
let valid = new; // ✓ Some(value)
let valid = new; // ✓ Some(value)
let invalid = new; // ✗ None (negative)
let invalid = new; // ✗ None (infinite)
// Normalized: Finite AND 0.0 ≤ value ≤ 1.0
let valid = new; // ✓ Some(value)
let invalid = new; // ✗ None (> 1.0)
let invalid = new; // ✗ None (< 0.0)
// Combined: NonZeroPositive = Positive AND NonZero
let valid = new; // ✓ Some(value)
let invalid = new; // ✗ None (zero)
let invalid = new; // ✗ None (negative)
Advanced Usage
Compile-Time Constants
use *;
const PI: FinF32 = new_const;
const ZERO: PositiveF32 = new_const;
const ONE_HUNDRED: NonZeroPositiveF64 = new_const;
assert_eq!;
Note: new_const will panic at compile time if the value violates constraints.
Option Types
use ;
let result = safe_divide;
assert!;
Development
Building
# Build the library
# Run tests
# Run linter
# Format code
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Built with ❤️ for type-safe Rust programming