Fixed point primitives
dsp-fixedpoint provides small no_std fixed-point primitives with explicit
integer storage and widening accumulators.
Model
Q<T, A, F> stores a raw integer T and interprets it as scaled by 2^F.
Tis the storage type.Ais the widened accumulator type used for intermediate results.Fis the number of fractional bits.
Type aliases cover the common signed, unsigned, and wrapping pairs:
Q8/Q16/Q32/Q64, P8/P16/P32/P64, W8/W16/W32/W64, and V8/V16/V32/V64.
Construction
There are two construction modes:
from_int,from_f32, andfrom_f64scale into the fixed-point domain.from_bitsis the raw-representation constructor.
use Q8;
let scaled = Q8::from_int;
let raw = Q8::from_bits;
assert_eq!;
assert_eq!;
Operator semantics
The crate keeps addition-like operators conservative and multiplication-like
operators efficient. Q means Q<T, A, F> unless shown otherwise.
| Operation | Result | Notes |
|---|---|---|
Q<F> + Q<F>, Q<F> - Q<F>, Q<F> % Q<F> |
Q<T, A, F> |
Requires the same F; use .scale::<F1>() explicitly when scales differ. |
Q * Q, Q / Q |
Q<T, A, F> |
Preserves the left-hand scale and quantizes the fixed-point result. |
Q * T |
Q<A, T, F> |
Widened raw-integer multiplication; same as q.mul_wide(t). |
T * Q |
T |
Applies Q as a gain to T and quantizes; same as q.apply(t). |
Q / T |
Q<T, A, F> |
Raw integer division of the stored representation. |
T / Q |
T |
Divides by Q as a fixed-point gain and quantizes. |
Q *= Q, Q /= Q |
Q<T, A, F> |
Assignment forms follow the left-hand scale. |
Q *= T, Q /= T |
Q<T, A, F> |
Assignment forms operate on the raw stored representation. |
The mixed multiplication and division asymmetry is intentional: operand order
chooses whether the result remains wide or is quantized immediately. Use
mul_wide() and apply() when spelling that choice explicitly is clearer than
relying on operand order.
Scale restrictions
F is an i8, but not every i8 value is meaningful everywhere.
Q::<_, _, -128>::DELTAis rejected at compile time.Q::<_, _, F>::one()andQ::<_, _, F>::ONEare rejected at compile time when the mathematical value1is not exactly representable by the storage type and scale.
use dsp_fixedpoint::Q8;
use num_traits::One;
let _ = Q8::<7>::one();
Serialization
With feature = "serde", Q serializes transparently as its raw representation.
For lossy scaled values, use dsp_fixedpoint::serde::as_f32 or
dsp_fixedpoint::serde::as_f64.
# use ;
use Q32;
Ecosystem Traits
Q implements a small set of generic numeric traits where the semantics stay
clear:
Boundedforwards to the raw storage bounds.ToPrimitive,FromPrimitive, andNumCastconvert numeric values rather than raw bits.Signedis implemented for signedQ/Wfamilies.Hashfollows the raw representation.
Signed inherits One, so the existing representability restriction still
applies: operations that need an exact 1, such as signum(), are only usable
when F >= 0.
Formatting
Display shows decimal notation. Binary/Octal/UpperHex/LowerHex show dot
notation.
use Q8;
assert_eq!;
assert_eq!;
defmt
With feature = "defmt", Q implements defmt::Format and logs as a decimal
value using f32. This keeps the target-side implementation compact for
embedded use. Exact radix-dot formatting remains available through the standard
Binary, Octal, and hex format traits.
bytemuck
With feature = "bytemuck", Q derives Pod, Zeroable, and
TransparentWrapper. That makes zero-copy buffer casts and wrapper conversions
available when the underlying storage and accumulator types also satisfy the
corresponding bytemuck bounds.