rinia 0.0.9

Portable scalar abstractions for game and simulation math.
Documentation
macro_rules! route_float_fn {
    (unary, $ty:ident, $value:expr, $std_method:ident, $libm_base:ident $(, $suffix:ident)?) => {{
        #[cfg(feature = "std")]
        {
            ::std::primitive::$ty::$std_method($value)
        }

        #[cfg(not(feature = "std"))]
        {
            ::pastey::paste! {
                $crate::external::libm::[<$libm_base $($suffix)?>]($value)
            }
        }
    }};

    (binary, $ty:ident, $value:expr, $arg:expr, $std_method:ident, $libm_base:ident $(, $suffix:ident)?) => {{
        #[cfg(feature = "std")]
        {
            ::std::primitive::$ty::$std_method($value, $arg)
        }

        #[cfg(not(feature = "std"))]
        {
            ::pastey::paste! {
                $crate::external::libm::[<$libm_base $($suffix)?>]($value, $arg)
            }
        }
    }};

    (ternary, $ty:ident, $value:expr, $arg1:expr, $arg2:expr, $std_method:ident, $libm_base:ident $(, $suffix:ident)?) => {{
        #[cfg(feature = "std")]
        {
            ::std::primitive::$ty::$std_method($value, $arg1, $arg2)
        }

        #[cfg(not(feature = "std"))]
        {
            ::pastey::paste! {
                $crate::external::libm::[<$libm_base $($suffix)?>]($value, $arg1, $arg2)
            }
        }
    }};
}

macro_rules! impl_float_for_type {
    (
        $ty:ident,
        $zero:expr,
        $one:expr
        $(,
            $suffix:ident
        )?
    ) => {
        ::pastey::paste! {
            impl $crate::ops::Abs for $ty {
                type Output = Self;

                #[inline]
                fn abs(self) -> Self::Output {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, abs, fabs $(, $suffix)?)
                }
            }

            impl $crate::ops::Zero for $ty {
                const ZERO: Self = $zero;

                #[inline]
                fn is_zero(self) -> bool {
                    self == Self::ZERO
                }
            }

            impl $crate::ops::One for $ty {
                const ONE: Self = $one;
            }

            impl $crate::ops::Rounding for $ty {
                #[inline]
                fn floor(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, floor, floor $(, $suffix)?)
                }

                #[inline]
                fn ceil(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, ceil, ceil $(, $suffix)?)
                }

                #[inline]
                fn trunc(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, trunc, trunc $(, $suffix)?)
                }

                #[inline]
                fn round(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, round, round $(, $suffix)?)
                }

                #[inline]
                fn fract(self) -> Self {
                    #[cfg(feature = "std")]
                    {
                        ::std::primitive::$ty::fract(self)
                    }

                    #[cfg(not(feature = "std"))]
                    {
                        ::pastey::paste! {
                            $crate::external::libm::[<modf $($suffix)?>](self).0
                        }
                    }
                }
            }

            impl $crate::ops::NaN for $ty {
                const NAN: Self = <$ty>::NAN;

                #[inline]
                fn is_nan(self) -> bool {
                    <$ty>::is_nan(self)
                }
            }

            impl $crate::ops::Infinity for $ty {
                const INFINITY: Self = <$ty>::INFINITY;
                const NEG_INFINITY: Self = <$ty>::NEG_INFINITY;

                #[inline]
                fn is_finite(self) -> bool {
                    <$ty>::is_finite(self)
                }

                #[inline]
                fn is_infinite(self) -> bool {
                    <$ty>::is_infinite(self)
                }
            }

            impl $crate::scalar::Float for $ty {
                #[inline]
                fn sin(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, sin, sin $(, $suffix)?)
                }

                #[inline]
                fn cos(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, cos, cos $(, $suffix)?)
                }

                #[inline]
                fn tan(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, tan, tan $(, $suffix)?)
                }

                #[inline]
                fn sin_cos(self) -> (Self, Self) {
                    (self.sin(), self.cos())
                }

                #[inline]
                fn sqrt(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, sqrt, sqrt $(, $suffix)?)
                }

                #[inline]
                fn exp(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, exp, exp $(, $suffix)?)
                }

                #[inline]
                fn ln(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, ln, log $(, $suffix)?)
                }

                #[inline]
                fn powf(self, exp: Self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(binary, $ty, self, exp, powf, pow $(, $suffix)?)
                }

                #[inline]
                fn signum(self) -> Self {
                    <$ty>::signum(self)
                }

                #[inline]
                fn copysign(self, sign: Self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(binary, $ty, self, sign, copysign, copysign $(, $suffix)?)
                }

                #[inline]
                fn mul_add(self, a: Self, b: Self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(
                        ternary,
                        $ty,
                        self,
                        a,
                        b,
                        mul_add,
                        fma
                        $(, $suffix)?
                    )
                }

                #[inline]
                fn div_euclid(self, rhs: Self) -> Self {
                    #[cfg(feature = "std")]
                    {
                        ::std::primitive::$ty::div_euclid(self, rhs)
                    }

                    #[cfg(not(feature = "std"))]
                    {
                        let q = self / rhs;
                        if rhs > $zero {
                            $crate::scalar::macros_float::route_float_fn!(unary, $ty, q, floor, floor $(, $suffix)?)
                        } else {
                            $crate::scalar::macros_float::route_float_fn!(unary, $ty, q, ceil, ceil $(, $suffix)?)
                        }
                    }
                }

                #[inline]
                fn rem_euclid(self, rhs: Self) -> Self {
                    #[cfg(feature = "std")]
                    {
                        ::std::primitive::$ty::rem_euclid(self, rhs)
                    }

                    #[cfg(not(feature = "std"))]
                    {
                        let r = ::pastey::paste! {
                            $crate::external::libm::[<fmod $($suffix)?>](self, rhs)
                        };
                        if r < $zero {
                            r + <$ty as $crate::ops::Abs>::abs(rhs)
                        } else {
                            r
                        }
                    }
                }

                #[inline]
                fn powi(self, n: i32) -> Self {
                    #[cfg(feature = "std")]
                    {
                        ::std::primitive::$ty::powi(self, n)
                    }

                    #[cfg(not(feature = "std"))]
                    {
                        $crate::scalar::macros_float::route_float_fn!(binary, $ty, self, n as $ty, powf, pow $(, $suffix)?)
                    }
                }

                #[inline]
                fn exp2(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, exp2, exp2 $(, $suffix)?)
                }

                #[inline]
                fn log(self, base: Self) -> Self {
                    #[cfg(feature = "std")]
                    {
                        ::std::primitive::$ty::log(self, base)
                    }

                    #[cfg(not(feature = "std"))]
                    {
                        $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, ln, log $(, $suffix)?)
                            / $crate::scalar::macros_float::route_float_fn!(unary, $ty, base, ln, log $(, $suffix)?)
                    }
                }

                #[inline]
                fn log2(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, log2, log2 $(, $suffix)?)
                }

                #[inline]
                fn log10(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, log10, log10 $(, $suffix)?)
                }

                #[inline]
                fn cbrt(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, cbrt, cbrt $(, $suffix)?)
                }

                #[inline]
                fn hypot(self, other: Self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(binary, $ty, self, other, hypot, hypot $(, $suffix)?)
                }

                #[inline]
                fn asin(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, asin, asin $(, $suffix)?)
                }

                #[inline]
                fn acos(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, acos, acos $(, $suffix)?)
                }

                #[inline]
                fn atan(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, atan, atan $(, $suffix)?)
                }

                #[inline]
                fn atan2(self, other: Self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(binary, $ty, self, other, atan2, atan2 $(, $suffix)?)
                }

                #[inline]
                fn exp_m1(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, exp_m1, expm1 $(, $suffix)?)
                }

                #[inline]
                fn ln_1p(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, ln_1p, log1p $(, $suffix)?)
                }

                #[inline]
                fn sinh(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, sinh, sinh $(, $suffix)?)
                }

                #[inline]
                fn cosh(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, cosh, cosh $(, $suffix)?)
                }

                #[inline]
                fn tanh(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, tanh, tanh $(, $suffix)?)
                }

                #[inline]
                fn asinh(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, asinh, asinh $(, $suffix)?)
                }

                #[inline]
                fn acosh(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, acosh, acosh $(, $suffix)?)
                }

                #[inline]
                fn atanh(self) -> Self {
                    $crate::scalar::macros_float::route_float_fn!(unary, $ty, self, atanh, atanh $(, $suffix)?)
                }
            }

            impl $crate::ops::Select for $ty {
                #[inline]
                fn min_val(self, other: Self) -> Self {
                    <$ty>::min(self, other)
                }

                #[inline]
                fn max_val(self, other: Self) -> Self {
                    <$ty>::max(self, other)
                }
            }

            impl $crate::ops::Negate for $ty {
                #[inline]
                fn negate(self) -> Self {
                    -self
                }
            }

        }
    };
}

pub(crate) use impl_float_for_type;
pub(crate) use route_float_fn;