Crate q_num

source ·
Expand description

§Q Number

This library provides a macro to define a binary fixed-point number type for a specified number of integer bits and fractional bits.

§Summary

This library provides the define_q_num! procedural macro (evaluated at compile time) to define a signed/unsigned binary fixed-point number type. It uses ARM-style Q notation: Qm.n (signed) or UQm.n (unsigned), where:

  • m is the number of integer bits, and
  • n is the number of fractional bits.

Internally, the macro chooses the narrowest primitive integer type that can hold m + n bits, up to u64 (unsigned) and i64 (signed). More internal details are discussed below.

§Q Number Value

A Q number’s value is the ratio of the stored number (having n + m bits) and a fixed denominator (equal to 2 ^ n).

For example, using the UQ3.2 specification, the bit pattern 0b10111 represents the value 5.75. Keeping in mind the denominator is 2 ^ 2 = 4, there are two ways to see this:

  • 0b10111 / 4 == 23 / 4 == 5.75
  • 0b101 + 0b11 / 4 == 5 + 3/4 == 5.75

§Example Macro Usage

Here is one example:

define_q_num!(X, Q6.2);
let a = X::try_from(13.75).unwrap();
let b = X::try_from(-2.25).unwrap();
let c = X::try_from(11.5).unwrap();
assert_eq!(a + b, c);

This defines a new type named MyQ, a signed fixed-point number represented internally with 8 bits:

  • 6 bits for the integer part
  • 2 bits for the fractional part

§Also Defined: Associated Methods

The example above also defines the following floating-point conversions:

  • MyQ::from(f64) -> MyQ
  • f64::from(MyQ) -> f64

It also defines the following getter and setter to access the internal representation:

  • MyQ.to_bits() -> i8
  • MyQ::from_bits(i8) -> MyQ

§Macro Variations

Variations include (a) signed vs. unsigned, and (b) visibility.

§Unsigned Variation

Use UQ to define an unsigned fixed-point number:

define_q_num!(MyNum, UQ11.5);

The integer part uses two’s complement representation.

§Visibility

A caller can optionally include a visibility modifier for the new type:

define_q_num!(pub MyNum, UQ11.5);

§Numerical Properties

The value of a Q number is the ratio of the storage number and a fixed denominator.

§Internals

The define_q! procedural macro defines a struct wrapping a primitive integer. This is an example of the newtype pattern.

For example, define_q!(MyNum, Q6.2) defines struct MyNum(i8).

The macro selects the narrowest primitive integer type that can hold the necessary number of bits. (For signed numbers, the integer part uses two’s complement representation, meaning that the sign bit is already counted towards the integer part.)

§See Also

https://en.wikipedia.org/wiki/Q_(number_format)

Macros§