satint 0.1.1

Saturating integer scalar wrappers for no_std Rust
Documentation
use rstest::rstest;
use satint::{
    Si8, Si16, Si32, Si64, Si128, Su8, Su16, Su32, Su64, Su128, si8, si16, si32, si64, si128, su8,
    su16, su32, su64, su128,
};

macro_rules! unsigned_operator_tests {
    ($module:ident, $scalar:ty, $ctor:ident, $primitive:ty) => {
        mod $module {
            use super::*;

            #[rstest]
            #[case::normal($ctor(10), $ctor(7), $ctor(17))]
            #[case::saturating(<$scalar>::MAX, $ctor(1), <$scalar>::MAX)]
            fn add_wrapper_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $scalar,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs + rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(10), 7 as $primitive, $ctor(17))]
            #[case::saturating(<$scalar>::MAX, 1 as $primitive, <$scalar>::MAX)]
            fn add_primitive_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $primitive,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs + rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(10), $ctor(7), $ctor(3))]
            #[case::saturating(<$scalar>::ZERO, $ctor(1), <$scalar>::ZERO)]
            fn sub_wrapper_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $scalar,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs - rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(10), 7 as $primitive, $ctor(3))]
            #[case::saturating(<$scalar>::ZERO, 1 as $primitive, <$scalar>::ZERO)]
            fn sub_primitive_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $primitive,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs - rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(6), $ctor(7), $ctor(42))]
            #[case::saturating(<$scalar>::MAX, $ctor(2), <$scalar>::MAX)]
            fn mul_wrapper_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $scalar,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs * rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(6), 7 as $primitive, $ctor(42))]
            #[case::saturating(<$scalar>::MAX, 2 as $primitive, <$scalar>::MAX)]
            fn mul_primitive_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $primitive,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs * rhs, expected);
            }

            #[test]
            fn assign_wrapper_rhs() {
                let mut add = $ctor(10);
                add += $ctor(7);
                assert_eq!(add, $ctor(17));

                let mut add_saturating = <$scalar>::MAX;
                add_saturating += $ctor(1);
                assert_eq!(add_saturating, <$scalar>::MAX);

                let mut sub = $ctor(10);
                sub -= $ctor(7);
                assert_eq!(sub, $ctor(3));

                let mut sub_saturating = <$scalar>::ZERO;
                sub_saturating -= $ctor(1);
                assert_eq!(sub_saturating, <$scalar>::ZERO);

                let mut mul = $ctor(6);
                mul *= $ctor(7);
                assert_eq!(mul, $ctor(42));

                let mut mul_saturating = <$scalar>::MAX;
                mul_saturating *= $ctor(2);
                assert_eq!(mul_saturating, <$scalar>::MAX);
            }

            #[test]
            fn assign_primitive_rhs() {
                let mut add = $ctor(10);
                add += 7 as $primitive;
                assert_eq!(add, $ctor(17));

                let mut add_saturating = <$scalar>::MAX;
                add_saturating += 1 as $primitive;
                assert_eq!(add_saturating, <$scalar>::MAX);

                let mut sub = $ctor(10);
                sub -= 7 as $primitive;
                assert_eq!(sub, $ctor(3));

                let mut sub_saturating = <$scalar>::ZERO;
                sub_saturating -= 1 as $primitive;
                assert_eq!(sub_saturating, <$scalar>::ZERO);

                let mut mul = $ctor(6);
                mul *= 7 as $primitive;
                assert_eq!(mul, $ctor(42));

                let mut mul_saturating = <$scalar>::MAX;
                mul_saturating *= 2 as $primitive;
                assert_eq!(mul_saturating, <$scalar>::MAX);
            }

            #[test]
            fn checked_div_rem() {
                assert_eq!($ctor(20).checked_div($ctor(3)), Some($ctor(6)));
                assert_eq!($ctor(20).checked_rem($ctor(3)), Some($ctor(2)));
                assert_eq!($ctor(20).checked_div($ctor(0)), None);
                assert_eq!($ctor(20).checked_rem($ctor(0)), None);
            }
        }
    };
}

macro_rules! signed_operator_tests {
    ($module:ident, $scalar:ty, $ctor:ident, $primitive:ty) => {
        mod $module {
            use super::*;

            #[rstest]
            #[case::normal($ctor(10), $ctor(-7), $ctor(3))]
            #[case::saturating(<$scalar>::MAX, $ctor(1), <$scalar>::MAX)]
            fn add_wrapper_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $scalar,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs + rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(10), -7 as $primitive, $ctor(3))]
            #[case::saturating(<$scalar>::MAX, 1 as $primitive, <$scalar>::MAX)]
            fn add_primitive_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $primitive,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs + rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(10), $ctor(7), $ctor(3))]
            #[case::saturating(<$scalar>::MIN, $ctor(1), <$scalar>::MIN)]
            fn sub_wrapper_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $scalar,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs - rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(10), 7 as $primitive, $ctor(3))]
            #[case::saturating(<$scalar>::MIN, 1 as $primitive, <$scalar>::MIN)]
            fn sub_primitive_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $primitive,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs - rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(6), $ctor(-7), $ctor(-42))]
            #[case::positive_saturating(<$scalar>::MAX, $ctor(2), <$scalar>::MAX)]
            #[case::negative_saturating(<$scalar>::MIN, $ctor(2), <$scalar>::MIN)]
            fn mul_wrapper_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $scalar,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs * rhs, expected);
            }

            #[rstest]
            #[case::normal($ctor(6), -7 as $primitive, $ctor(-42))]
            #[case::positive_saturating(<$scalar>::MAX, 2 as $primitive, <$scalar>::MAX)]
            #[case::negative_saturating(<$scalar>::MIN, 2 as $primitive, <$scalar>::MIN)]
            fn mul_primitive_rhs(
                #[case] lhs: $scalar,
                #[case] rhs: $primitive,
                #[case] expected: $scalar,
            ) {
                assert_eq!(lhs * rhs, expected);
            }

            #[test]
            fn assign_wrapper_rhs() {
                let mut add = $ctor(10);
                add += $ctor(-7);
                assert_eq!(add, $ctor(3));

                let mut add_saturating = <$scalar>::MAX;
                add_saturating += $ctor(1);
                assert_eq!(add_saturating, <$scalar>::MAX);

                let mut sub = $ctor(10);
                sub -= $ctor(7);
                assert_eq!(sub, $ctor(3));

                let mut sub_saturating = <$scalar>::MIN;
                sub_saturating -= $ctor(1);
                assert_eq!(sub_saturating, <$scalar>::MIN);

                let mut mul = $ctor(6);
                mul *= $ctor(-7);
                assert_eq!(mul, $ctor(-42));

                let mut mul_saturating = <$scalar>::MIN;
                mul_saturating *= $ctor(2);
                assert_eq!(mul_saturating, <$scalar>::MIN);
            }

            #[test]
            fn assign_primitive_rhs() {
                let mut add = $ctor(10);
                add += -7 as $primitive;
                assert_eq!(add, $ctor(3));

                let mut add_saturating = <$scalar>::MAX;
                add_saturating += 1 as $primitive;
                assert_eq!(add_saturating, <$scalar>::MAX);

                let mut sub = $ctor(10);
                sub -= 7 as $primitive;
                assert_eq!(sub, $ctor(3));

                let mut sub_saturating = <$scalar>::MIN;
                sub_saturating -= 1 as $primitive;
                assert_eq!(sub_saturating, <$scalar>::MIN);

                let mut mul = $ctor(6);
                mul *= -7 as $primitive;
                assert_eq!(mul, $ctor(-42));

                let mut mul_saturating = <$scalar>::MIN;
                mul_saturating *= 2 as $primitive;
                assert_eq!(mul_saturating, <$scalar>::MIN);
            }

            #[test]
            fn checked_div_rem() {
                assert_eq!($ctor(20).checked_div($ctor(3)), Some($ctor(6)));
                assert_eq!($ctor(20).checked_rem($ctor(3)), Some($ctor(2)));
                assert_eq!($ctor(20).checked_div($ctor(0)), None);
                assert_eq!($ctor(20).checked_rem($ctor(0)), None);
                assert_eq!(<$scalar>::MIN.checked_div($ctor(-1)), None);
                assert_eq!(<$scalar>::MIN.checked_rem($ctor(-1)), None);
            }

            #[test]
            fn neg() {
                assert_eq!(-$ctor(5), $ctor(-5));
                assert_eq!(-<$scalar>::MIN, <$scalar>::MAX);
            }
        }
    };
}

macro_rules! widening_operator_tests {
    ($module:ident, $lhs:ty, $lhs_ctor:ident, $rhs:ty, $rhs_ctor:ident) => {
        mod $module {
            use super::*;

            #[test]
            fn add_sub_wrapper_rhs() {
                assert_eq!($lhs_ctor(40) + $rhs_ctor(2), $lhs_ctor(42));
                assert_eq!($lhs_ctor(40) - $rhs_ctor(2), $lhs_ctor(38));

                let mut add = $lhs_ctor(40);
                add += $rhs_ctor(2);
                assert_eq!(add, $lhs_ctor(42));

                let mut sub = $lhs_ctor(40);
                sub -= $rhs_ctor(2);
                assert_eq!(sub, $lhs_ctor(38));
            }
        }
    };
}

unsigned_operator_tests!(su8_ops, Su8, su8, u8);
unsigned_operator_tests!(su16_ops, Su16, su16, u16);
unsigned_operator_tests!(su32_ops, Su32, su32, u32);
unsigned_operator_tests!(su64_ops, Su64, su64, u64);
unsigned_operator_tests!(su128_ops, Su128, su128, u128);

signed_operator_tests!(si8_ops, Si8, si8, i8);
signed_operator_tests!(si16_ops, Si16, si16, i16);
signed_operator_tests!(si32_ops, Si32, si32, i32);
signed_operator_tests!(si64_ops, Si64, si64, i64);
signed_operator_tests!(si128_ops, Si128, si128, i128);

widening_operator_tests!(su16_su8_ops, Su16, su16, Su8, su8);
widening_operator_tests!(su32_su8_ops, Su32, su32, Su8, su8);
widening_operator_tests!(su32_su16_ops, Su32, su32, Su16, su16);
widening_operator_tests!(su64_su8_ops, Su64, su64, Su8, su8);
widening_operator_tests!(su64_su16_ops, Su64, su64, Su16, su16);
widening_operator_tests!(su64_su32_ops, Su64, su64, Su32, su32);
widening_operator_tests!(su128_su8_ops, Su128, su128, Su8, su8);
widening_operator_tests!(su128_su16_ops, Su128, su128, Su16, su16);
widening_operator_tests!(su128_su32_ops, Su128, su128, Su32, su32);
widening_operator_tests!(su128_su64_ops, Su128, su128, Su64, su64);

widening_operator_tests!(si16_si8_ops, Si16, si16, Si8, si8);
widening_operator_tests!(si32_si8_ops, Si32, si32, Si8, si8);
widening_operator_tests!(si32_si16_ops, Si32, si32, Si16, si16);
widening_operator_tests!(si64_si8_ops, Si64, si64, Si8, si8);
widening_operator_tests!(si64_si16_ops, Si64, si64, Si16, si16);
widening_operator_tests!(si64_si32_ops, Si64, si64, Si32, si32);
widening_operator_tests!(si128_si8_ops, Si128, si128, Si8, si8);
widening_operator_tests!(si128_si16_ops, Si128, si128, Si16, si16);
widening_operator_tests!(si128_si32_ops, Si128, si128, Si32, si32);
widening_operator_tests!(si128_si64_ops, Si128, si128, Si64, si64);