fastnum 0.7.4

Fast decimal numbers library
Documentation
macro_rules! ops_impl {
    ($Ty: ident, U, $Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident) => {
        ops_impl!(@ $Ty, U, $Op, $op, $OpAssign, $op_assign, [u8, u16, u32, u64, usize, i8 #TRY, i16 #TRY, i32 #TRY, i64 #TRY, i128 #TRY, u128 #TRY, isize #TRY, f32 #TRY, f64 #TRY]);
    };
    ($Ty: ident, I, $Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident) => {
        ops_impl!(@ $Ty, I, $Op, $op, $OpAssign, $op_assign, [u8, u16, u32, u64, usize, i8, i16, i32, i64, i128 #TRY, u128 #TRY, isize, f32, f64]);
    };
    (@ $Ty: ident, $sign: ident, $Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident, [$($ty: ident $(#$try: ident)?),*]) => {
        impl<const N: usize> $Op for $Ty<N> {
            type Output = Self;

            #[inline(always)]
            fn $op(self, rhs: Self) -> Self::Output {
                self.$op(rhs)
            }
        }

        impl<const N: usize> $OpAssign for $Ty<N> {
            #[inline(always)]
            fn $op_assign(&mut self, rhs: Self) {
                let res = $Op::<$Ty<N>>::$op(*self, rhs);
                *self = res;
            }
        }

        $(
            ops_impl!(@@ $($try)? $Ty, $ty, $Op, $op, $OpAssign, $op_assign);
        )*
    };
    (@@ $Ty: ident, $ty: ident, $Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident) => {
        impl<const N: usize> $Op<$ty> for $Ty<N> {
            type Output = Self;

            #[inline(always)]
            fn $op(self, rhs: $ty) -> Self::Output {
                let rhs = $Ty::from(rhs);
                $Op::<$Ty<N>>::$op(self, rhs)
            }
        }

        impl<const N: usize> $Op<$Ty<N>> for $ty {
            type Output = $Ty<N>;

            #[inline(always)]
            fn $op(self, rhs: $Ty<N>) -> Self::Output {
                let this = $Ty::from(self);
                $Op::<$Ty<N>>::$op(this, rhs)
            }
        }

        impl<const N: usize> $OpAssign<$ty> for $Ty<N> {
            #[inline(always)]
            fn $op_assign(&mut self, rhs: $ty) {
                let rhs = $Ty::from(rhs);
                self.$op_assign(rhs);
            }
        }
    };
    (@@ TRY $Ty: ident, $ty: ident, $Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident) => {
        impl<const N: usize> $Op<$ty> for $Ty<N> {
            type Output = Self;

            #[inline(always)]
            fn $op(self, rhs: $ty) -> $Ty<N> {
                let Ok(rhs) = $Ty::try_from(rhs) else {
                    #[cfg(debug_assertions)]
                    panic!(crate::utils::err_msg!(concat!("attempt to ", stringify!($op), " with invalid ", stringify!($ty))));

                    #[cfg(not(debug_assertions))]
                    return self;
                };

                $Op::<$Ty<N>>::$op(self, rhs)
            }
        }

        impl<const N: usize> $Op<$Ty<N>> for $ty {
            type Output = $Ty<N>;

            #[inline(always)]
            fn $op(self, rhs: $Ty<N>) -> Self::Output {
                let Ok(this) = $Ty::try_from(self) else {
                    #[cfg(debug_assertions)]
                    panic!(crate::utils::err_msg!(concat!("attempt to ", stringify!($op), " with invalid ", stringify!($ty))));

                    #[cfg(not(debug_assertions))]
                    return rhs;
                };

                $Op::<$Ty<N>>::$op(this, rhs)
            }
        }

        impl<const N: usize> $OpAssign<$ty> for $Ty<N> {
            #[inline(always)]
            fn $op_assign(&mut self, rhs: $ty) {
                let Ok(rhs) = $Ty::try_from(rhs) else {
                    #[cfg(debug_assertions)]
                    panic!(crate::utils::err_msg!(concat!("attempt to ", stringify!($op), " with invalid ", stringify!($ty))));

                    #[cfg(not(debug_assertions))]
                    return;
                };

                self.$op_assign(rhs);
            }
        }
    };
}

pub(crate) use ops_impl;