unsigned-float
Unsigned floating-point types for values that can never be negative.
unsigned-float provides compact unsigned float newtypes with IEEE-like
exponent and mantissa fields, but no sign bit. The missing sign bit buys either
extra precision or range, removes negative zero, and makes total ordering as
simple as comparing the raw integer representation.
This crate is young and experimental. The current behavior prioritizes a small, clear API and predictable bit layouts over exhaustive IEEE 754 compatibility.
Formats
| Alias | Concrete layout type | Layout | Storage | Native compute path |
|---|---|---|---|---|
Uf8 |
Uf8E4M4 |
E4M4 | u8 |
LUT by default, nightly f16 optional |
Uf8E5M3 |
E5M3 | u8 |
LUT by default, nightly f16 optional |
|
Uf16 |
Uf16E5M11 |
E5M11 | u16 |
promote to f32 |
Uf16E6M10 |
E6M10 | u16 |
promote to f32 |
|
Uf32 |
Uf32E8M24 |
E8M24 | u32 |
promote to f64 |
Uf64 |
Uf64E11M52 |
E11M52 | u64 |
promote to nightly f128 |
The all-ones exponent is reserved for infinity and NaN, following the usual IEEE-style convention. Negative native inputs encode to NaN. Operations whose mathematical result is negative also produce NaN.
Uf8, Uf16, and Uf32 are ergonomic aliases for the default concrete layout
types. Layout-specific names are exported for every format because changing the
exponent/mantissa split changes the numeric contract. Use E4M4/E5M11 when
precision near 1.0 matters more; use E5M3/E6M10 when range matters more.
Uf64 is available only with the f128 feature.
Install
[]
= "0.1"
Example
use ;
let a = from_f32;
let b = from_f32;
let product = a * b;
assert_eq!;
let small = from_f32;
let large = from_f32;
assert!;
assert_eq!;
let wide = from_f64;
assert_eq!;
let wider_range = from_f32;
assert_eq!;
Raw Ordering
Unsigned floats are ordered by their raw bits:
use Uf16;
let values = ;
let mut sorted = values;
sorted.sort;
assert_eq!;
assert_eq!;
Because there is no sign bit and no negative zero, Ord and PartialOrd are
implemented as simple unsigned integer comparisons of the underlying bits. NaN
payloads therefore sort after infinity rather than behaving like IEEE
f32::partial_cmp.
Conversions
Use the explicit constructors when you want IEEE-like encoding behavior:
use Uf8;
assert!;
assert!;
Use TryFrom/TryInto when you want to reject values outside the finite,
non-negative domain:
use ;
assert_eq!;
assert_eq!;
assert_eq!;
The crate implements fallible conversions from f64 and primitive integer
types. With the f16 feature enabled, from_f16, to_f16,
From<f16>, and Into<f16> are also available.
Features
| Feature | Default | Description |
|---|---|---|
f16 |
No | Uses nightly primitive f16 for Uf8 arithmetic dispatch. Requires nightly Rust. |
f128 |
No | Enables Uf64/Uf64E11M52 and promotes its arithmetic through nightly primitive f128. |
nightly |
No | Convenience feature enabling both f16 and f128. |
soft-float |
No | Forces the software/LUT dispatch path where available. If combined with f16, soft-float wins for Uf8. |
The default Uf8 arithmetic path uses generated 256x256 lookup tables for
Add, Sub, Mul, and Div. These tables are generated by build.rs into
Cargo's OUT_DIR and embedded with include_bytes!, so they do not need to be
checked in.
no_std
The library is #![no_std]. The build script and benchmarks use std, but the
crate API itself does not require allocation or the standard library.
Benchmarks
The benchmark suite uses nightly's built-in test harness and covers
conversions, arithmetic, and raw-bit ordering for all exported layouts.
Each command benchmarks the dispatch path selected by that feature set. For
example, --features f16 measures the Uf8 primitive-f16 path, while the
default command measures the generated LUT path.
Status
Implemented:
Uf8,Uf16, andUf32transparent newtypes- explicit concrete layout names:
Uf8E4M4,Uf8E5M3,Uf16E5M11,Uf16E6M10,Uf32E8M24, and feature-gatedUf64E11M52 - raw bit constructors and extractors
- native float conversions
- fallible conversions from
f64and primitive integers Add,Sub,Mul, andDiv- raw-bit
Ord/PartialOrd - generated UF8 arithmetic lookup tables
- benchmarks across conversions, arithmetic, and ordering
Still worth exploring:
- native baseline benchmarks against
f32andf64 - configurable UF8 dispatch for direct LUT versus promote-to-native comparisons
- SIMD bulk operations
- more explicit NaN payload policy
- broader property tests for all finite
Uf16layout edge cases
License
See LICENSE.