Skip to main content

Crate dsp_fixedpoint

Crate dsp_fixedpoint 

Source
Expand description

§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.

  • T is the storage type.
  • A is the widened accumulator type used for intermediate results.
  • F is 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, and from_f64 scale into the fixed-point domain.
  • from_bits is the raw-representation constructor.
use dsp_fixedpoint::Q8;

let scaled = Q8::<4>::from_int(3);
let raw = Q8::<4>::from_bits(3 << 4);

assert_eq!(scaled, raw);
assert_eq!(raw.into_bits(), 48);

§Operator semantics

The crate keeps addition-like operators conservative and multiplication-like operators efficient. Q means Q<T, A, F> unless shown otherwise.

OperationResultNotes
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 / QQ<T, A, F>Preserves the left-hand scale and quantizes the fixed-point result.
Q * TQ<A, T, F>Widened raw-integer multiplication; same as q.mul_wide(t).
T * QTApplies Q as a gain to T and quantizes; same as q.apply(t).
Q / TQ<T, A, F>Raw integer division of the stored representation.
T / QTDivides by Q as a fixed-point gain and quantizes.
Q *= Q, Q /= QQ<T, A, F>Assignment forms follow the left-hand scale.
Q *= T, Q /= TQ<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>::DELTA is rejected at compile time.
  • Q::<_, _, F>::one() and Q::<_, _, F>::ONE are rejected at compile time when the mathematical value 1 is 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 dsp_fixedpoint::Q32;

#[derive(Deserialize, Serialize)]
struct Config {
    #[serde(with = "dsp_fixedpoint::serde::as_f64")]
    gain: Q32<3>,
}

§Ecosystem Traits

Q implements a small set of generic numeric traits where the semantics stay clear:

  • Bounded forwards to the raw storage bounds.
  • ToPrimitive, FromPrimitive, and NumCast convert numeric values rather than raw bits.
  • Signed is implemented for signed Q/W families.
  • Hash follows 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 dsp_fixedpoint::Q8;

assert_eq!(
    format!("{:#b}", Q8::<3>::from_bits(0b01101001)),
    "0b1101.001"
);
assert_eq!(format!("{:x}", Q8::<4>::from_bits(-0x14)), "-1.4");

§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.

Modules§

serde
Serde adapters for fixed-point wire formats.

Structs§

Q
Fixed point integer

Traits§

Accu
Conversion trait between base and accumulator type
Shift
Shift summary trait

Type Aliases§

P8
Fixed point u8 with u16 accumulator
P16
Fixed point u16 with u32 accumulator
P32
Fixed point u32 with u64 accumulator
P64
Fixed point u64 with u128 accumulator
Q8
Fixed point i8 with i16 accumulator
Q16
Fixed point i16 with i32 accumulator
Q32
Fixed point i32 with i64 accumulator
Q64
Fixed point i64 with i128 accumulator
V8
Fixed point Wrapping< u8 > with Wrapping< u16 > accumulator
V16
Fixed point Wrapping< u16 > with Wrapping< u32 > accumulator
V32
Fixed point Wrapping< u32 > with Wrapping< u64 > accumulator
V64
Fixed point Wrapping< u64 > with Wrapping< u128 > accumulator
W8
Fixed point Wrapping< i8 > with Wrapping< i16 > accumulator
W16
Fixed point Wrapping< i16 > with Wrapping< i32 > accumulator
W32
Fixed point Wrapping< i32 > with Wrapping< i64 > accumulator
W64
Fixed point Wrapping< i64 > with Wrapping< i128 > accumulator