fastnum2 0.3.6

fork of Fast decimal numbers library
Documentation
macro_rules! test_impl {
    (D, $bits: literal) => {
        paste::paste! { test_impl!(SIGNED: $bits, [< dec $bits >], [<D $bits>]); }
    };
    (UD, $bits: literal) => {
        paste::paste! { test_impl!(UNSIGNED: $bits, [< udec $bits >], [<UD $bits>]); }
    };
    (UNSIGNED: $bits: tt, $dec: ident, $D: ident) => {
        mod $dec {
            use rstest::*;
            use fastnum::{$dec, $D};

            super::test_impl!(COMMON:: $bits, $dec, $D, THIS);
            super::test_impl!(UNSIGNED:: $bits, $dec, $D, THIS);
        }
    };
    (SIGNED: $bits: tt, $dec: ident, $D: ident) => {
        mod $dec {
            use rstest::*;
            use fastnum::{$dec, $D};

            super::test_impl!(COMMON:: $bits, $dec, $D, THIS);
            super::test_impl!(SIGNED:: $bits, $dec, $D, THIS);
        }
    };
    (COMMON:: 512, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(COMMON:: 256, $dec, $D);
    };
    (UNSIGNED:: 512, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(UNSIGNED:: 256, $dec, $D);
    };
    (SIGNED:: 512, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(SIGNED:: 256, $dec, $D);
    };


    (COMMON:: 256, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(COMMON:: 256, $dec, $D);
    };
    (COMMON:: 256, $dec: ident, $D: ident) => {
        super::test_impl!(COMMON:: 128, $dec, $D);

        #[rstest(::trace)]
        #[case($dec!(340282366920938463463374607431768211455), $dec!(0.1), $dec!(340282366920938463463374607431768211454.9))]
        #[case($dec!(340282366920938463463374607431768211455), $dec!(0.5), $dec!(340282366920938463463374607431768211454.5))]
        #[case($dec!(170141183460469231731687303715884105727), $dec!(0.1), $dec!(170141183460469231731687303715884105726.9))]
        #[case($dec!(170141183460469231731687303715884105727), $dec!(0.5), $dec!(170141183460469231731687303715884105726.5))]
        fn test_sub_256(#[case] a: $D, #[case] b: $D, #[case] expected: $D) {
            let res = a - b;

            assert_eq!(res, expected);
            assert_eq!(res.fractional_digits_count(), expected.fractional_digits_count());
            assert!(res.is_op_ok());

            let mut a = a;

            a -= b;
            assert_eq!(a, expected);
            assert_eq!(a.fractional_digits_count(), expected.fractional_digits_count());
            assert!(a.is_op_ok());
        }
    };
    (UNSIGNED:: 256, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(UNSIGNED:: 256, $dec, $D);
    };
    (UNSIGNED:: 256, $dec: ident, $D: ident) => {
        super::test_impl!(UNSIGNED:: 128, $dec, $D);
    };
    (SIGNED:: 256, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(SIGNED:: 256, $dec, $D);
    };
    (SIGNED:: 256, $dec: ident, $D: ident) => {
        super::test_impl!(SIGNED:: 128, $dec, $D);

        #[rstest(::trace)]
        #[case($dec!(-340282366920938463463374607431768211455), $dec!(-0.1), $dec!(-340282366920938463463374607431768211454.9))]
        #[case($dec!(-340282366920938463463374607431768211455), $dec!(-0.5), $dec!(-340282366920938463463374607431768211454.5))]
        #[case($dec!(-170141183460469231731687303715884105727), $dec!(-0.1), $dec!(-170141183460469231731687303715884105726.9))]
        #[case($dec!(-170141183460469231731687303715884105727), $dec!(-0.5), $dec!(-170141183460469231731687303715884105726.5))]
        fn test_sub_256_signed(#[case] a: $D, #[case] b: $D, #[case] expected: $D) {
            let res = a - b;

            assert_eq!(res, expected);
            assert_eq!(res.fractional_digits_count(), expected.fractional_digits_count());
            assert!(res.is_op_ok());

            let mut a = a;

            a -= b;
            assert_eq!(a, expected);
            assert_eq!(a.fractional_digits_count(), expected.fractional_digits_count());
            assert!(a.is_op_ok());
        }
    };

    (COMMON:: 128, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(COMMON:: 128, $dec, $D);

        #[rstest(::trace)]
        #[case($D::from(u128::MAX), $dec!(0.1), $D::from(u128::MAX))]
        #[case($D::from(u128::MAX), $dec!(0.5), $D::from(u128::MAX))]
        #[case($dec!(340282366920938463463374607431768211455), $dec!(0.5), $dec!(340282366920938463463374607431768211455))]
        #[case($dec!(340282366920938463463374607431768211455), $dec!(0.1), $dec!(340282366920938463463374607431768211455))]
        #[case($dec!(34028236692093846346337460743176821145), $dec!(0.01), $dec!(34028236692093846346337460743176821145.0))]
        #[case($dec!(1), $dec!(0.000000000000000000000000000000000000001), $dec!(100000000000000000000000000000000000000e-38))]
        #[case($dec!(1), $dec!(0.0000000000000000000000000000000000000001), $dec!(100000000000000000000000000000000000000e-38))]
        fn test_sub_128_inexact(#[case] a: $D, #[case] b: $D, #[case] expected: $D) {
            let res = a - b;
            assert_eq!(res, expected);
            assert_eq!(res.fractional_digits_count(), expected.fractional_digits_count());

            assert!(res.is_op_inexact());
            assert!(res.is_op_rounded());
        }

        #[rstest(::trace)]
        #[case($dec!(184467440737e3380), $dec!(0), $dec!(184467440737000000000000000000000000000e3353))]
        fn test_sub_128_clamped(#[case] a: $D, #[case] b: $D, #[case] expected: $D) {
            let res = a - b;
            assert_eq!(res, expected);
            assert_eq!(res.fractional_digits_count(), expected.fractional_digits_count());

            assert!(!res.is_op_inexact());
            assert!(res.is_op_clamped());
        }
    };
    (COMMON:: 128, $dec: ident, $D: ident) => {
        #[rstest(::trace)]
        #[case($dec!(0), $dec!(0), $dec!(0))]
        #[case($dec!(1), $dec!(1), $dec!(0))]
        #[case($dec!(1), $dec!(0), $dec!(1))]
        #[case($dec!(2), $dec!(1), $dec!(1))]
        #[case($dec!(2), $dec!(2), $dec!(0))]
        #[case($dec!(3), $dec!(2), $dec!(1))]
        #[case($dec!(11), $dec!(1), $dec!(10))]
        #[case($dec!(10), $dec!(1), $dec!(9))]
        #[case($dec!(9), $dec!(1), $dec!(8))]
        #[case($dec!(5.75), $dec!(3.3), $dec!(2.45))]
        #[case($dec!(0.7), $dec!(0.3), $dec!(0.4))]
        #[case($dec!(1.3), $dec!(0.3), $dec!(1.0))]
        #[case($dec!(1.25), $dec!(1.25), $dec!(0.00))]
        #[case($dec!(1.0), $dec!(0), $dec!(1.0))]
        #[case($dec!(1), $dec!(0.75), $dec!(0.25))]
        #[case($dec!(12.34), $dec!(1.234), $dec!(11.106))]
        #[case($dec!(1234e6), $dec!(1234e-6), $dec!(1233999999.998766))]
        #[case($dec!(85616001e4), $dec!(0), $dec!(856160010000))]
        #[case($dec!(11), $dec!(1), $dec!(10))]
        #[case($dec!(10), $dec!(1), $dec!(9))]
        #[case($dec!(9), $dec!(1), $dec!(8))]
        #[case($dec!(1), $dec!(1), $dec!(0))]
        #[case($dec!(5.75), $dec!(3.3), $dec!(2.45))]
        #[case($dec!(0.7), $dec!(0.3), $dec!(0.4))]
        #[case($dec!(1.3), $dec!(0.3), $dec!(1.0))]
        #[case($dec!(1.25), $dec!(1.25), $dec!(0.00))]
        // ------------

        #[case($dec!(10.23456789), $dec!(10.23456789), $dec!(0E-8))]
        #[case($dec!(10.23456790), $dec!(10.23456789), $dec!(1E-8))]
        #[case($dec!(10.23456791), $dec!(10.23456789), $dec!(2E-8))]
        #[case($dec!(10.23456792), $dec!(10.23456789), $dec!(3E-8))]
        #[case($dec!(10.23456793), $dec!(10.23456789), $dec!(4E-8))]
        #[case($dec!(10.23456794), $dec!(10.23456789), $dec!(5E-8))]
        #[case($dec!(10.23456786), $dec!(10.23456786), $dec!(0E-8))]
        #[case($dec!(10.23456787), $dec!(10.23456786), $dec!(1E-8))]
        #[case($dec!(10.23456788), $dec!(10.23456786), $dec!(2E-8))]
        #[case($dec!(10.23456789), $dec!(10.23456786), $dec!(3E-8))]
        #[case($dec!(10.23456790), $dec!(10.23456786), $dec!(4E-8))]
        #[case($dec!(10.23456791), $dec!(10.23456786), $dec!(5E-8))]
        #[case($dec!(1), $dec!(0.999999999), $dec!(1E-9))]
        // ------------
        #[case($dec!(0.9998), $dec!(0.0000), $dec!(0.9998))]
        #[case($dec!(0.9998), $dec!(0.0001), $dec!(0.9997))]
        #[case($dec!(0.9998), $dec!(0.0002), $dec!(0.9996))]
        #[case($dec!(0.9998), $dec!(0.0003), $dec!(0.9995))]
        // ------------
        fn test_sub(#[case] a: $D, #[case] b: $D, #[case] expected: $D) {
            let res = a - b;

            assert_eq!(res, expected);
            assert_eq!(res.fractional_digits_count(), expected.fractional_digits_count());
            assert!(res.is_op_ok());

            let mut a = a;

            a -= b;
            assert_eq!(a, expected);
            assert_eq!(a.fractional_digits_count(), expected.fractional_digits_count());
            assert!(a.is_op_ok());
        }

        #[rstest(::trace)]
        #[case($D::NAN, $dec!(1))]
        #[case($dec!(1), $D::NAN)]
        #[case($D::NAN, $D::NAN)]
        #[case($D::NAN, $D::INFINITY)]
        #[case($D::INFINITY, $D::NAN)]
        #[case($D::INFINITY, $D::INFINITY)]
        #[should_panic(expected = "(fastnum) invalid operation")]
        fn test_sub_nan(#[case] a: $D, #[case] b: $D) {
            let _ = a - b;
        }
    };
    (UNSIGNED:: 128, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(UNSIGNED:: 128, $dec, $D);
    };
    (UNSIGNED:: 128, $dec: ident, $D: ident) => {
        #[rstest(::trace)]
        #[case($dec!(0), $dec!(2))]
        #[case($dec!(0.003), $dec!(0.3))]
        #[should_panic(expected = "(fastnum) invalid operation")]
        fn test_sub_negative_panic(#[case] a: $D, #[case] b: $D) {
            let _ = a - b;
        }
    };
    (SIGNED:: 128, $dec: ident, $D: ident, THIS) => {
        super::test_impl!(SIGNED:: 128, $dec, $D);

        #[rstest(::trace)]
        #[case($D::from(i128::MAX), $dec!(0.1), $D::from(i128::MAX))]
        #[case($D::from(i128::MAX), $dec!(0.5), $D::from(i128::MAX))]
        #[case($dec!(0.000000001), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.000001), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.1), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.4), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.49), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.499999), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.499999999), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.5), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.500000001), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211455))]
        #[case($dec!(0.500001), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(0.5001), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(0.51), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(0.6), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(0.9), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(0.99999), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(0.999999999), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(1.000000001), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(1.00001), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        #[case($dec!(1.1), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        fn test_sub_128_inexact_signed(#[case] a: $D, #[case] b: $D, #[case] expected: $D) {
            let res = a - b;

            assert_eq!(res, expected);
            assert_eq!(res.fractional_digits_count(), expected.fractional_digits_count());

            assert!(res.is_op_inexact());
            assert!(res.is_op_rounded());
        }
    };
    (SIGNED:: 128, $dec: ident, $D: ident) => {
        #[rstest(::trace)]
        #[case($dec!(0), $dec!(0), $dec!(0))]
        #[case($dec!(1), $dec!(2), $dec!(-1))]
        #[case($dec!(-0), $dec!(0), $dec!(-0))]
        #[case($dec!(0), $dec!(-0), $dec!(0))]
        #[case($dec!(0), $dec!(1), $dec!(-1))]
        #[case($dec!(1), $dec!(-1), $dec!(2))]
        #[case($dec!(1), $dec!(-2), $dec!(3))]
        #[case($dec!(-1), $dec!(0), $dec!(-1))]
        #[case($dec!(-1), $dec!(1), $dec!(-2))]
        #[case($dec!(-1), $dec!(2), $dec!(-3))]
        #[case($dec!(2), $dec!(-1), $dec!(3))]
        #[case($dec!(2), $dec!(-2), $dec!(4))]
        #[case($dec!(2), $dec!(3), $dec!(-1))]
        #[case($dec!(2), $dec!(-3), $dec!(5))]
        #[case($dec!(-2), $dec!(1), $dec!(-3))]
        #[case($dec!(-2), $dec!(2), $dec!(-4))]
        #[case($dec!(-3), $dec!(2), $dec!(-5))]
        #[case($dec!(-2), $dec!(3), $dec!(-5))]
        #[case($dec!(-1), $dec!(0.75), $dec!(-1.75))]
        #[case($dec!(0), $dec!(2), $dec!(-2))]
        #[case($dec!(3), $dec!(-2), $dec!(5))]
        #[case($dec!(-9), $dec!(1), $dec!(-10))]
        #[case($dec!(-10), $dec!(1), $dec!(-11))]
        #[case($dec!(-11), $dec!(1), $dec!(-12))]
        #[case($dec!(5), $dec!(-3), $dec!(8))]
        #[case($dec!(-5), $dec!(-3), $dec!(-2))]
        #[case($dec!(-3), $dec!(-5), $dec!(2))]
        #[case($dec!(-7), $dec!(2.5), $dec!(-9.5))]
        #[case($dec!(0.003), $dec!(0.3), $dec!(-0.297))]
        #[case($dec!(12.34), $dec!(-1.234), $dec!(13.574))]
        #[case($dec!(1234e-6), $dec!(1234e6), $dec!(-1233999999.998766))]
        #[case($dec!(712911676e-6), $dec!(4856259269250829), $dec!(-4856259269250116.088324))]
        #[case($dec!(0), $dec!(5207.07672), $dec!(-520707672e-5))]
        #[case($dec!(99291289e5), $dec!(0), $dec!(9929128900000))]
        #[case($dec!(0.7051277471570131), $dec!(1), $dec!(-0.2948722528429869))]
        #[case($dec!(40686030.22763836), $dec!(-10), $dec!(40686040.22763836))]
        #[case($dec!(0), $dec!(1), $dec!(-1))]
        #[case($dec!(-1), $dec!(1), $dec!(-2))]
        #[case($dec!(-9), $dec!(1), $dec!(-10))]
        #[case($dec!(-10), $dec!(1), $dec!(-11))]
        #[case($dec!(-11), $dec!(1), $dec!(-12))]
        #[case($dec!(5), $dec!(-3), $dec!(8))]
        #[case($dec!(-5), $dec!(-3), $dec!(-2))]
        #[case($dec!(-7), $dec!(2.5), $dec!(-9.5))]
        #[case($D::INFINITY, $D::NEG_INFINITY, $D::INFINITY)]
        #[case($D::NEG_INFINITY, $D::INFINITY, $D::NEG_INFINITY)]
        #[case($dec!(1), $D::INFINITY, $D::NEG_INFINITY)]
        #[case($dec!(1000), $D::INFINITY, $D::NEG_INFINITY)]
        #[case($D::INFINITY, $dec!(1000), $D::INFINITY)]
        #[case($D::NEG_INFINITY, $dec!(1000), $D::NEG_INFINITY)]
        // ---------
        #[case($dec!(10.23456784), $dec!(10.23456789), $dec!(-5E-8))]
        #[case($dec!(10.23456785), $dec!(10.23456789), $dec!(-4E-8))]
        #[case($dec!(10.23456786), $dec!(10.23456789), $dec!(-3E-8))]
        #[case($dec!(10.23456787), $dec!(10.23456789), $dec!(-2E-8))]
        #[case($dec!(10.23456788), $dec!(10.23456789), $dec!(-1E-8))]
        #[case($dec!(10.23456781), $dec!(10.23456786), $dec!(-5E-8))]
        #[case($dec!(10.23456782), $dec!(10.23456786), $dec!(-4E-8))]
        #[case($dec!(10.23456783), $dec!(10.23456786), $dec!(-3E-8))]
        #[case($dec!(10.23456784), $dec!(10.23456786), $dec!(-2E-8))]
        #[case($dec!(10.23456785), $dec!(10.23456786), $dec!(-1E-8))]
        #[case($dec!(0), $dec!(1231234567456789), $dec!(-1231234567456789))]
        // ---------
        #[case($dec!(0.999999999), $dec!(1), $dec!(-1E-9))]
        #[case($dec!(-10.23456780), $dec!(-10.23456786), $dec!(6E-8))]
        #[case($dec!(-10.23456790), $dec!(-10.23456786), $dec!(-4E-8))]
        #[case($dec!(-10.23456791), $dec!(-10.23456786), $dec!(-5E-8))]
        // ---------
        #[case($dec!(0.9998), $dec!(-0.0000), $dec!(0.9998))]
        #[case($dec!(0.9998), $dec!(-0.0001), $dec!(0.9999))]
        #[case($dec!(0.9998), $dec!(-0.0002), $dec!(1.0000))]
        #[case($dec!(0.9998), $dec!(-0.0003), $dec!(1.0001))]
        #[case($dec!(1), $dec!(340282366920938463463374607431768211455), $dec!(-340282366920938463463374607431768211454))]
        fn test_sub_signed(#[case] a: $D, #[case] b: $D, #[case] expected: $D) {
            let res = a - b;

            assert_eq!(res, expected);
            assert_eq!(res.fractional_digits_count(), expected.fractional_digits_count());
            assert!(res.is_op_ok());

            let mut a = a;

            a -= b;
            assert_eq!(a, expected);
            assert_eq!(a.fractional_digits_count(), expected.fractional_digits_count());
            assert!(a.is_op_ok());
        }

        #[rstest(::trace)]
        #[case($D::NAN, $dec!(-1))]
        #[case($dec!(-1), $D::NAN)]
        #[case($D::NEG_INFINITY, $D::NEG_INFINITY)]
        #[case($D::NAN, $D::NEG_INFINITY)]
        #[case($D::NEG_INFINITY, $D::NAN)]
        #[should_panic(expected = "(fastnum) invalid operation")]
        fn test_sub_nan_signed(#[case] a: $D, #[case] b: $D) {
            let _ = a - b;
        }
    };
}

pub(crate) use test_impl;