FixedP

Struct FixedP 

Source
pub struct FixedP<const P: Precision> { /* private fields */ }
Expand description

A Copy type representing an unsigned, fixed point value, supporting const context evaluation.

Equality and comparisons are fast operations.

Note: This type currently only supports addition and subtraction, and all operations must happen between equivalent types, ie. can’t mix FixedP<5> with FixedP<4>, although in some cases you can convert from/to different precision types.

§Examples

/// Create 11.50 and 1.05 as fixed point values
let fixed_point_11_5 = FixedP::<2>::from_units_frac(11, 50)?;
let fixed_point_1_05 = FixedP::<2>::from_units_frac(1, 5)?;

/// Assert that the addition equals 12.55
let addition = fixed_point_11_5 + fixed_point_1_05;
assert_eq!(addition.units(), 12);
assert_eq!(addition.frac(), 55);
assert_eq!(&format!("{}", addition), "12.55");

The example below fails because we are specifying a fractional part that cannot be represented with the given precision:

/// The fractional part cannot represent 3 digits.
let fixed_point_1_123 = FixedP::<2>::from_units_frac(1, 123)?;

The following example should fail to compile because the requirements on the precision of the fractional part are so big that the units can no longer represent FixedP::<P>::MIN_UNIT_SCALE:

/// Try to create a fixed-point value with too much precision
/// so that the remaining integer part becomes too small.
let fixed_point_1_123 = FixedP::<16>::from_units_frac(1, 1)?;

Conversely, trying to create a fixed point value with a precision of zero digits also fails to compile:

let fixed_point_1_123 = FixedP::<0>::from_units(1)?;

If you ever have two fixed point values with different precision there are still options for you to operate with them as long as you can convert one to the other:

let fp500_15_p2 = FixedP::<2>::from_units_frac(500, 15)?;
let fp1_00001_p5 = FixedP::<5>::from_units_frac(1, 1)?;

let fp500_15_p5 = FixedP::<5>::try_from_fixed(fp500_15_p2)?;
let addition = fp500_15_p5 + fp1_00001_p5;
assert_eq!(addition, FixedP::<5>::from_units_frac(501, 15001)?);

The example below shows how you could use this type in a const context. Note that the ergonomics are not great currently due to lacking the ability to panic in such contexts, not being able to use ?, and in general needing to call fallible functions. However, there are ways to force compilation to fail on unexpected assumptions - this crate (ab)uses those to hold its own guarantees:

const ONE: FixedP<4> = match FixedP::from_units(1) {
    Ok(one) => one,
/// _ => unreachable!(), // not yet available on stable
};
const TEN_N_HALF: FixedP<4> = match FixedP::from_units_frac(10, 5000) {
    Ok(n) => n,
/// _ => unreachable!(), // not yet available on stable
};
const ELEVEN_N_HALF: FixedP<4> = match ONE.checked_add(TEN_N_HALF) {
    Some(n) => n,
/// _ => unreachable!(), // not yet available on stable
};

Implementations§

Source§

impl<const P: Precision> FixedP<P>

Source

pub const MIN_UNIT_SCALE: u64 = 100_000_000_000u64

Minimum number of integers that should be representable, arbitrarily set to 100 billion.

Source

pub const fn precision() -> Precision

Returns the precision for the fractional part of this fixed point type.

Source

pub const fn unit_bits() -> u32

Returns the bits taken for the integer part of this fixed point type.

Source

pub const fn frac_bits() -> u32

Returns the bits taken for the fractional part of this fixed point type.

Source

pub const fn unit_max() -> u64

Returns the maximum integer representable by this fixed point type.

Source

pub const fn frac_max() -> u64

Returns the maximum fractional part representable by this fixed point type.

Source

pub const fn zero() -> Self

Returns a fixed point value representing the number zero.

Source

pub const fn min() -> Self

Returns the minimum value for this fixed point type.

Source

pub const fn max() -> Self

Returns the maximum value for this fixed point type.

Source

pub const fn from_units_frac(units: u64, frac: u64) -> Result<Self, Error<P>>

Constructs a fixed point value from separate integer and fractional parts.

Source

pub const fn from_units(units: u64) -> Result<Self, Error<P>>

Constructs a fixed point value from an integer and a fractional part of 0.

Source

pub const fn units(&self) -> u64

Returns the integer part of a fixed point value.

Source

pub const fn frac(&self) -> u64

Returns the fractional part of a fixed point value.

Source

pub const fn split(&self) -> (u64, u64)

Returns the integer and fractional as a tuple of (units, frac).

Source

pub const fn checked_add(self, rhs: Self) -> Option<Self>

Checked integer addition. Computes self + rhs, returning None if overflow occurred.

/// Create 1.95 and 1.05 as fixed point values
let fixed_point_1_95 = FixedP::<2>::from_units_frac(1, 95)?;
let fixed_point_1_05 = FixedP::<2>::from_units_frac(1, 5)?;

/// Assert that the addition equals 3.00
let addition = fixed_point_1_95 + fixed_point_1_05;
assert_eq!(addition.units(), 3);
assert_eq!(addition.frac(), 0);
assert_eq!(&format!("{}", addition), "3.00");
Source

pub const fn checked_sub(self, rhs: Self) -> Option<Self>

Checked integer subtraction. Computes self - rhs, returning None if underflow occurred.

/// Create 11.50 and 1.05 as fixed point values
let fixed_point_11_5 = FixedP::<3>::from_units_frac(11, 500)?;
let fixed_point_1_05 = FixedP::<3>::from_units_frac(1, 50)?;

/// Assert that the subtraction equals 10.45
let subtraction = fixed_point_11_5 - fixed_point_1_05;
assert_eq!(subtraction.units(), 10);
assert_eq!(subtraction.frac(), 450);
assert_eq!(&format!("{}", subtraction), "10.450");
Source

pub const fn try_from_fixed<const Q: Precision>( value: FixedP<Q>, ) -> Result<Self, Error<P>>

This method will convert (whenever possible) a FixedP<Q> to a FixedP<P>.

Such a conversion is only possible in the below circumstances:

Q to P relationInteger valueFraction value
EqualIndifferentIndifferent
SmallerSmaller scaleIndifferent
BiggerIndifferentQ-P last digits are 0

Essentially the conversion will be possible whenever a loss of precision in the fractional part or loss of scale in the integer part can still accomodate the same exact number.

So a FixedP with a precision equal to another one can always be converted, but one that has higher precision can only be converted if the extra precision in the fractional part is not really used, that is, the extra digits are not significant, ie. 0, and one with lower precision can only be converted if the integer value fits in the reduced scale of the higher precision one.

Note: currently Rust won’t allow us to write the TryFrom implementation because of limitations in the places where const generic types can appear, but more importantly, because there is a blanket impl<U, T> TryFrom<U> for T where U: Into<T> that will conflict with the impl<const Q, const P> TryFrom<FixedP<Q>> for FixedP<P> when P == Q.

This means we can’t have TryFrom implemented for different precision values for the time being, but we can still implement this inherent method that does exactly that.

Trait Implementations§

Source§

impl<const P: Precision> Add for FixedP<P>

Source§

fn add(self, rhs: Self) -> Self::Output

Add two FixedP’s.

§Panics

This function panics if the addition would overflow the bit space reserved for the integer part.

Source§

type Output = FixedP<P>

The resulting type after applying the + operator.
Source§

impl<const P: Precision> AddAssign for FixedP<P>

Source§

fn add_assign(&mut self, rhs: Self)

Performs the += operation. Read more
Source§

impl<const P: Precision> Clone for FixedP<P>

Source§

fn clone(&self) -> FixedP<P>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<const P: Precision> Debug for FixedP<P>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

The Debug implementation for fixed point values will show the allocated bits for the integral and fractional parts as well as the maximum values for each and the internal representation.

Source§

impl<const P: Precision> Default for FixedP<P>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<const P: Precision> Display for FixedP<P>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

The Display implementation will display the integral part, followed by a dot . and the fractional part with the chosen precision, even if the fixed point value has a fractional part of zero.

Source§

impl<const P: Precision> FromStr for FixedP<P>

Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

This function will parse a fixed point value out of a string slice. An error will be returned if the string cannot be parsed as a fixed point number, or if the integral or the fractional part are not representable with the chosen decimal precision.

Source§

type Err = Error<P>

The associated error which can be returned from parsing.
Source§

impl<const P: Precision> Hash for FixedP<P>

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<const P: Precision> Ord for FixedP<P>

Source§

fn cmp(&self, other: &FixedP<P>) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl<const P: Precision> PartialEq for FixedP<P>

Source§

fn eq(&self, other: &FixedP<P>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<const P: Precision> PartialOrd for FixedP<P>

Source§

fn partial_cmp(&self, other: &FixedP<P>) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<const P: Precision> Sub for FixedP<P>

Source§

fn sub(self, rhs: Self) -> Self::Output

Subtract two FixedP’s.

§Panics

This function panics if the subtraction would result in a negative integer part.

Source§

type Output = FixedP<P>

The resulting type after applying the - operator.
Source§

impl<const P: Precision> SubAssign for FixedP<P>

Source§

fn sub_assign(&mut self, rhs: Self)

Performs the -= operation. Read more
Source§

impl<const P: Precision> TryFrom<i128> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: i128) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<i16> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: i16) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<i32> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: i32) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<i64> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: i64) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<i8> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: i8) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<u128> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: u128) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<u16> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: u16) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<u32> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: u32) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<u64> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: u64) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> TryFrom<u8> for FixedP<P>

Source§

type Error = Error<P>

The type returned in the event of a conversion error.
Source§

fn try_from(value: u8) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<const P: Precision> Copy for FixedP<P>

Source§

impl<const P: Precision> Eq for FixedP<P>

Source§

impl<const P: Precision> StructuralPartialEq for FixedP<P>

Auto Trait Implementations§

§

impl<const P: u8> Freeze for FixedP<P>

§

impl<const P: u8> RefUnwindSafe for FixedP<P>

§

impl<const P: u8> Send for FixedP<P>

§

impl<const P: u8> Sync for FixedP<P>

§

impl<const P: u8> Unpin for FixedP<P>

§

impl<const P: u8> UnwindSafe for FixedP<P>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.