Skip to content
Basic

Literals: fixed!

A constant in Q15 or in steps of 3.3 V / 4096 is a number nobody wants to work out by hand. fixed! writes it as the decimal it means:

use exact_units::{Fixed, Q15, fixed, prefix::{Milli, Pow2}, units::{Ratio, Volt}};

const HALF: Q15<Ratio> = fixed!(0.5);
const BUSY: Fixed<Ratio, Pow2<-30>, i64> = fixed!(0.1);
const LIMIT: Fixed<Volt, Milli, u16> = fixed!(3.3);

assert_eq!(HALF.get(), 16384);        // 0.5 · 2¹⁵
assert_eq!(BUSY.get(), 107_374_182);  // 0.1 · 2³⁰ = 107374182.4, rounded
assert_eq!(LIMIT.get(), 3300);        // 3.3 V in mV

What it does

  • The literal is in the unit U of the type it goes into: fixed!(3.3) of a Fixed<Volt, Milli, u16> is 3.3 V.
  • The stored value is worked out at compile time from the exact fraction. Nothing runs at run time.
  • An integer storage takes the nearest integer, ties to even:
\[ n = \operatorname{round}_{\text{even}}\!\left(\frac{x}{\text{scale}}\right) \]
  • A float storage takes the nearest float.
  • An exponent works: fixed!(2.5e-3).

What doesn't compile

A value that doesn't fit the storage, a negative one of an unsigned storage, or one outside the bounds:

use exact_units::{Q15, fixed, units::Ratio};

const TOO_BIG: Q15<Ratio> = fixed!(1.0); // Q15 ends at 1 − 2⁻¹⁵
use exact_units::{Fixed, fixed, prefix::Milli, units::Volt};

const NEGATIVE: Fixed<Volt, Milli, u16> = fixed!(-0.5);

A scale with π or a root in it has no decimal stored values, so fixed! refuses it too.

Not a literal

For a decimal that isn't a literal (a Decimal built in a const), Fixed::from_decimal is the same as a const fn. Levels in dB have their own literal, db!.