Skip to main content

Decimal32

Struct Decimal32 

Source
pub struct Decimal32<const PRECISION: u32>(/* private fields */);
Expand description

A 32-bit lossless number with const-defined decimal precision.

§Design

There are different ways to represent a floating point number with wrapping and saturating semantics. This design basically takes the bounds of an i32 and sticks a decimal point somewhere. So the type itself serves primarily for self-documentation and convenience.

IEEE 754 floating point debauchery keeps the lossless range of an f32 in signed 2^24. So an equally valid design could lock the inner value within that range and use that bound for wrapping, saturating, and checked operations. The benefit is that get could return an f32 without loss of precision. The cost is hardware support for arithmetic. Since wrapping arithmetic is the primary motivation for Decimal32, this was not chosen.

A Decimal64 type is not (yet) exposed because at that point, the Decimal crate might be a better fit for your use case.

Implementations§

Source§

impl<const PRECISION: u32> Decimal32<PRECISION>

Source

pub const ZERO: Self

Source

pub const MAX: Self

The greatest positive value this type can contain.

Source

pub const MIN: Self

The most negative value this type can contain.

Source

pub const MIN_UNIT: Self

The smallest positive value this type can contain.

Source

pub const fn cast(value: f64) -> Self

Constructor that accepts any input. Truncates toward zero when the input has more decimal places than PRECISION. Use Self::checked to detect when precision is lost.

This function takes an f64 to prevent sneaky loss of precision. f32 only has a 24-bit mantissa, so values between 2^24 and and 2^31 require an f64 to be constructed.

use high_roller::decimal::D2;

let num = D2::cast(0.125_f64);
assert_eq!(num.get(), 0.12_f64);

If this f64 situation is annoying for your use case, you can still escape it entirely at compile time.

use high_roller::decimal::D3;

const MY_F32: f32 = D3::cast(0.321_f64).get() as f32;
assert_eq!(MY_F32, 0.321);
Source

pub const fn checked(value: f64) -> Option<Self>

Const constructor that prevents loss of precision from the input value.

§Succeeds
use high_roller::decimal::D5;

const GOOD: D5 = D5::checked(-100.12345).unwrap();
§Fails
use high_roller::decimal::D9;

const BAD: D9 = D9::checked(-100.)
    .expect("There isn't space in 32 bits for 9 decimal places after -100");
Source

pub const fn get(self) -> f64

Returns the inner value as an f64. This conversion is lossless because f64’s 53-bit mantissa can represent every i32 value exactly.

For f32 output use f32::try_from, which returns Err(Lossy) when the inner value exceeds f32’s 24-bit mantissa.

use high_roller::decimal::D1;

assert_eq!(D1::cast(1.0_f64).get(), 1.0_f64);

Trait Implementations§

Source§

impl<const P: u32> Add for Decimal32<P>

Source§

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

Uses wrapping addition.

Source§

type Output = Decimal32<P>

The resulting type after applying the + operator.
Source§

impl<const P: u32> CheckedAdd for Decimal32<P>

Source§

fn checked_add(&self, v: &Self) -> Option<Self>

Adds two numbers, checking for overflow. If overflow happens, None is returned.
Source§

impl<const P: u32> CheckedSub for Decimal32<P>

Source§

fn checked_sub(&self, v: &Self) -> Option<Self>

Subtracts two numbers, checking for underflow. If underflow happens, None is returned.
Source§

impl<const PRECISION: u32> Clone for Decimal32<PRECISION>

Source§

fn clone(&self) -> Decimal32<PRECISION>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl<const P: u32> Debug for Decimal32<P>

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<const P: u32> Default for Decimal32<P>

Source§

fn default() -> Self

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

impl<const P: u32> Display for Decimal32<P>

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<const P: u32> From<Decimal32<P>> for f64

Source§

fn from(val: Decimal32<P>) -> Self

Converts to this type from the input type.
Source§

impl<const PRECISION: u32> Hash for Decimal32<PRECISION>

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: u32> Neg for Decimal32<P>

Source§

fn neg(self) -> Self::Output

Uses wrapping negation.

Source§

type Output = Decimal32<P>

The resulting type after applying the - operator.
Source§

impl<const PRECISION: u32> Ord for Decimal32<PRECISION>

Source§

fn cmp(&self, other: &Decimal32<PRECISION>) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

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

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

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

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

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

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

impl<const PRECISION: u32> PartialEq for Decimal32<PRECISION>

Source§

fn eq(&self, other: &Decimal32<PRECISION>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · 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 PRECISION: u32> PartialOrd for Decimal32<PRECISION>

Source§

fn partial_cmp(&self, other: &Decimal32<PRECISION>) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · 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 (const: unstable) · 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 (const: unstable) · 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 (const: unstable) · 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: u32> Sub for Decimal32<P>

Source§

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

Uses wrapping subtraction.

Source§

type Output = Decimal32<P>

The resulting type after applying the - operator.
Source§

impl<const P: u32> TryFrom<Decimal32<P>> for f32

Source§

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

Converts to f32. Returns Err(Lossy) when the inner value exceeds f32’s 24-bit mantissa. Use Decimal32::get if unchecked lossless output is required.

Source§

type Error = DecimalErr

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

impl<const P: u32> TryFrom<f32> for Decimal32<P>

Source§

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

Constructs a Decimal32 from an f32 or returns Err(DecimalErr::Lossy) if the conversion would lose precision. This might occur if the input literal specifies more decimal places than the underlyingDecimal32 type.

use high_roller::decimal::D2;

D2::try_from(0.123).expect("resulting decimal is 0.12");

But take care not to lose precision when constructing the f32 input into this function. Since f32 has a 24-bit mantissa, it cannot represent some values that Decimal32 can.

In the example below, rustc abbreviates the float before this function even sees it. Decimal32::cast solves this case by using an f64 constructor.

use high_roller::decimal::D9;

const INPUT: f32 = 2.147483647;
let expected = D9::try_from(INPUT).unwrap();

assert_eq!(INPUT, f32::try_from(expected).unwrap());
assert_eq!(INPUT, 2.1474836, "two places were dropped");
Source§

type Error = DecimalErr

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

impl<const P: u32> WrappingAdd for Decimal32<P>

Source§

fn wrapping_add(&self, v: &Self) -> Self

Wrapping (modular) addition. Computes self + other, wrapping around at the boundary of the type.
Source§

impl<const P: u32> WrappingSub for Decimal32<P>

Source§

fn wrapping_sub(&self, v: &Self) -> Self

Wrapping (modular) subtraction. Computes self - other, wrapping around at the boundary of the type.
Source§

impl<const PRECISION: u32> Copy for Decimal32<PRECISION>

Source§

impl<const PRECISION: u32> Eq for Decimal32<PRECISION>

Source§

impl<const PRECISION: u32> StructuralPartialEq for Decimal32<PRECISION>

Auto Trait Implementations§

§

impl<const PRECISION: u32> Freeze for Decimal32<PRECISION>

§

impl<const PRECISION: u32> RefUnwindSafe for Decimal32<PRECISION>

§

impl<const PRECISION: u32> Send for Decimal32<PRECISION>

§

impl<const PRECISION: u32> Sync for Decimal32<PRECISION>

§

impl<const PRECISION: u32> Unpin for Decimal32<PRECISION>

§

impl<const PRECISION: u32> UnsafeUnpin for Decimal32<PRECISION>

§

impl<const PRECISION: u32> UnwindSafe for Decimal32<PRECISION>

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.