primitive_fixed_point_decimal 0.7.2

Primitive fixed-point decimal types.
Documentation
use crate::fpdec_inner::FpdecInner;
use int_div_cum_error::{checked_divide_with_cum_error, checked_divide_with_rounding, Rounding};

macro_rules! calc_mul_div_higher {
    (
        $a:expr, $b:expr, $c:expr,
        $rounding:expr, $cum_error:expr,
        $origin_type:ty, $higher_type:ty
    ) => {{
        match $cum_error {
            Some(cum_error) => {
                let mut higher_cum_error = *cum_error as $higher_type;
                let q = checked_divide_with_cum_error(
                    $a as $higher_type * $b as $higher_type,
                    $c as $higher_type,
                    $rounding,
                    &mut higher_cum_error,
                )?;

                *cum_error = higher_cum_error as $origin_type;
                <$origin_type>::try_from(q).ok()
            }
            None => {
                let q = checked_divide_with_rounding(
                    $a as $higher_type * $b as $higher_type,
                    $c as $higher_type,
                    $rounding,
                )?;
                <$origin_type>::try_from(q).ok()
            }
        }
    }};
}

impl FpdecInner for i8 {
    const MAX: Self = i8::MAX;
    const MIN: Self = i8::MIN;
    const MAX_POWERS: Self = 10_i8.pow(2);
    const DIGITS: u32 = 2;

    fn get_exp(i: usize) -> Option<Self> {
        const ALL_EXPS: [i8; 3] = [1, 10_i8.pow(1), 10_i8.pow(2)];

        ALL_EXPS.get(i).copied()
    }

    fn calc_mul_div(
        self,
        b: Self,
        c: Self,
        rounding: Rounding,
        cum_error: Option<&mut Self>,
    ) -> Option<Self> {
        calc_mul_div_higher!(self, b, c, rounding, cum_error, i8, i16)
    }
}

impl FpdecInner for i16 {
    const MAX: Self = i16::MAX;
    const MIN: Self = i16::MIN;
    const MAX_POWERS: Self = 10_i16.pow(4);
    const DIGITS: u32 = 4;

    fn get_exp(i: usize) -> Option<Self> {
        const ALL_EXPS: [i16; 5] = [
            1,
            10_i16.pow(1),
            10_i16.pow(2),
            10_i16.pow(3),
            10_i16.pow(4),
        ];

        ALL_EXPS.get(i).copied()
    }

    fn calc_mul_div(
        self,
        b: Self,
        c: Self,
        rounding: Rounding,
        cum_error: Option<&mut Self>,
    ) -> Option<Self> {
        calc_mul_div_higher!(self, b, c, rounding, cum_error, i16, i32)
    }
}

impl FpdecInner for i32 {
    const MAX: Self = i32::MAX;
    const MIN: Self = i32::MIN;
    const MAX_POWERS: Self = 10_i32.pow(9);
    const DIGITS: u32 = 9;

    fn get_exp(i: usize) -> Option<Self> {
        const ALL_EXPS: [i32; 10] = [
            1,
            10_i32.pow(1),
            10_i32.pow(2),
            10_i32.pow(3),
            10_i32.pow(4),
            10_i32.pow(5),
            10_i32.pow(6),
            10_i32.pow(7),
            10_i32.pow(8),
            10_i32.pow(9),
        ];

        ALL_EXPS.get(i).copied()
    }

    fn calc_mul_div(
        self,
        b: Self,
        c: Self,
        rounding: Rounding,
        cum_error: Option<&mut Self>,
    ) -> Option<Self> {
        calc_mul_div_higher!(self, b, c, rounding, cum_error, i32, i64)
    }
}

impl FpdecInner for i64 {
    const MAX: Self = i64::MAX;
    const MIN: Self = i64::MIN;
    const MAX_POWERS: Self = 10_i64.pow(18);
    const DIGITS: u32 = 18;

    fn get_exp(i: usize) -> Option<Self> {
        const ALL_EXPS: [i64; 19] = [
            1,
            10_i64.pow(1),
            10_i64.pow(2),
            10_i64.pow(3),
            10_i64.pow(4),
            10_i64.pow(5),
            10_i64.pow(6),
            10_i64.pow(7),
            10_i64.pow(8),
            10_i64.pow(9),
            10_i64.pow(10),
            10_i64.pow(11),
            10_i64.pow(12),
            10_i64.pow(13),
            10_i64.pow(14),
            10_i64.pow(15),
            10_i64.pow(16),
            10_i64.pow(17),
            10_i64.pow(18),
        ];

        ALL_EXPS.get(i).copied()
    }

    fn calc_mul_div(
        self,
        b: Self,
        c: Self,
        rounding: Rounding,
        cum_error: Option<&mut Self>,
    ) -> Option<Self> {
        calc_mul_div_higher!(self, b, c, rounding, cum_error, i64, i128)
    }
}