Expand description
This crate provides fixed-point arithmetic with statically verified overflow safety and bit shift correctness.
Fixed-point arithmetic represents fractional values as integers with
an implicit bit shift. For example, the decimal number 2.375 (in base 2: 10.011) could
be represented in fixed-point as the integer 0b10011
(decimal 19) with an implicit bit shift of 3. It is
the programmer’s responsibility to keep track of all the bit shifts used in a program,
ensure they are consistent with each other, and avoid any overflows during
arithmetic operations.
In contrast, floating-point numbers automatically adjust the “bit shift” (i.e. the exponent) to provide the largest possible resolution which will not overflow. They are easy to use, and they do the right thing most of the time. However, they can cause subtle rounding bugs which are famously difficult to identify and prevent. In the immortal words of Professor Gerald Sussman, “Nothing brings fear to my heart more than a floating-point number.”
This crate uses the Rust type system to provide fixed-point numbers with compile-time bit shift checking and overflow protection. Each fixed-point type has two const generic parameters, one describing the bit shift and one describing the maximum number of bits which could be nonzero. Each arithmetic operation is implemented with an output type which correctly reflects the bits and shift of the result. For example, the result of multiplying a 10-bit number (shifted by 2) and a 12-bit number (shifted by 3) is a 22-bit number (shifted by 5).
The trait Num
represents any fixed-point number stored as an
integer, and the structs NumXxx<const BITS: u32, const SHIFT: i32>
implement the
Num
trait for each integer type Xxx
. Arithmetic operations on the fixed-point
types are guaranteed to provide correctness and overflow safety with zero runtime
overhead.
It is necessary to use nightly Rust in order to enable the unstable
generic_const_exprs
feature. Otherwise it would not be possible to specify
the correct return type from most operations.
Structs§
- I8
#[repr(transparent)]
struct containingi8
interpreted as a fixed-point number.- I16
#[repr(transparent)]
struct containingi16
interpreted as a fixed-point number.- I32
#[repr(transparent)]
struct containingi32
interpreted as a fixed-point number.- I64
#[repr(transparent)]
struct containingi64
interpreted as a fixed-point number.- I128
#[repr(transparent)]
struct containingi128
interpreted as a fixed-point number.- Isize
#[repr(transparent)]
struct containingisize
interpreted as a fixed-point number.- U8
#[repr(transparent)]
struct containingu8
interpreted as a fixed-point number.- U16
#[repr(transparent)]
struct containingu16
interpreted as a fixed-point number.- U32
#[repr(transparent)]
struct containingu32
interpreted as a fixed-point number.- U64
#[repr(transparent)]
struct containingu64
interpreted as a fixed-point number.- U128
#[repr(transparent)]
struct containingu128
interpreted as a fixed-point number.- Usize
#[repr(transparent)]
struct containingusize
interpreted as a fixed-point number.
Enums§
Traits§
- Num
- A fixed-point number, stored as type
Raw
, where only theBITS
least-significant bits may be nonzero. The raw value is divided by2.pow(SHIFT)
to obtain the logical value.