diff --git a/sprout/math/abs.hpp b/sprout/math/abs.hpp index af8aee66..8cb594ac 100644 --- a/sprout/math/abs.hpp +++ b/sprout/math/abs.hpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace sprout { namespace math { @@ -15,7 +16,7 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType abs(FloatType x) { - return x < 0 ? -x : x; + return sprout::math::fabs(x); } } // namespace detail diff --git a/sprout/math/atan2.hpp b/sprout/math/atan2.hpp index 1faef1ff..791e8e8c 100644 --- a/sprout/math/atan2.hpp +++ b/sprout/math/atan2.hpp @@ -37,8 +37,8 @@ namespace sprout { atan2(FloatType y, FloatType x) { return sprout::math::isnan(y) ? sprout::math::isnan(x) - ? sprout::math::signbit(y) && sprout::math::signbit(x) ? -std::numeric_limits::quiet_NaN() - : std::numeric_limits::quiet_NaN() + ? sprout::math::signbit(y) && sprout::math::signbit(x) ? -std::numeric_limits::quiet_NaN() + : std::numeric_limits::quiet_NaN() : y : sprout::math::isnan(x) ? x : x == -std::numeric_limits::infinity() diff --git a/sprout/math/cbrt.hpp b/sprout/math/cbrt.hpp index f23865fd..8b89df68 100644 --- a/sprout/math/cbrt.hpp +++ b/sprout/math/cbrt.hpp @@ -5,24 +5,38 @@ #include #include #include -#include +#include #include +#include +#include #include namespace sprout { namespace math { namespace detail { + template + inline SPROUT_CONSTEXPR T + cbrt_impl(T x) { + return x < 0 ? -sprout::pow(-x, sprout::math::third()) + : sprout::pow(x, sprout::math::third()) + ; + } + template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR FloatType cbrt(FloatType x) { - return x == 0 ? FloatType(0) + return sprout::math::isnan(x) ? x : x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() : x == -std::numeric_limits::infinity() ? -std::numeric_limits::infinity() - : x < 0 ? -sprout::pow(-x, sprout::math::third()) - : sprout::pow(x, sprout::math::third()) +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::cbrt(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::cbrt_impl(static_cast::type>(x))) +#endif ; } @@ -36,7 +50,7 @@ namespace sprout { } } // namespace detail - using NS_SPROUT_MATH_DETAIL::cbrt; + using sprout::math::detail::cbrt; } // namespace math using sprout::math::cbrt; diff --git a/sprout/math/erf.hpp b/sprout/math/erf.hpp index 3778d6c9..ee8830d1 100644 --- a/sprout/math/erf.hpp +++ b/sprout/math/erf.hpp @@ -4,11 +4,12 @@ #include #include #include +#include #include #include +#include #include #include -#include #include namespace sprout { @@ -102,13 +103,13 @@ namespace sprout { template inline SPROUT_CONSTEXPR T erf_impl_2_a(T x, T w, T t) { - return sprout::math::detail::erf_impl_2_a_1(x, w, sprout::fractional_part(t), sprout::math::itrunc(t)); + return sprout::math::detail::erf_impl_2_a_1(x, w, sprout::math::fractional_part(t), sprout::math::itrunc(t)); } template inline SPROUT_CONSTEXPR T erf_impl_1(T x, T w) { return w < T(2.2) ? sprout::math::detail::erf_impl_2_a(x, w, w * w) - : w < T(6.9) ? sprout::math::detail::erf_impl_2_b(x, w, sprout::fractional_part(w), sprout::math::itrunc(w) - 2) + : w < T(6.9) ? sprout::math::detail::erf_impl_2_b(x, w, sprout::math::fractional_part(w), sprout::math::itrunc(w) - 2) : sprout::math::detail::erf_impl_3(x, T(1)) ; } @@ -124,14 +125,17 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType erf(FloatType x) { - typedef typename sprout::math::detail::float_compute::type type; - return x == 0 ? FloatType(0) + return sprout::math::isnan(x) ? x : x == std::numeric_limits::infinity() ? FloatType(1) : x == -std::numeric_limits::infinity() ? FloatType(-1) - : static_cast(sprout::math::detail::erf_impl(static_cast(x))) +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::erf(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::erf_impl(static_cast::type>(x))) +#endif ; } - template< typename IntType, typename sprout::enabler_if::value>::type = sprout::enabler @@ -142,7 +146,7 @@ namespace sprout { } } // namespace detail - using NS_SPROUT_MATH_DETAIL::erf; + using sprout::math::detail::erf; } // namespace math using sprout::math::erf; diff --git a/sprout/math/erfc.hpp b/sprout/math/erfc.hpp index ee221a0b..2cff9ace 100644 --- a/sprout/math/erfc.hpp +++ b/sprout/math/erfc.hpp @@ -4,24 +4,36 @@ #include #include #include +#include +#include #include #include namespace sprout { namespace math { namespace detail { + template + inline SPROUT_CONSTEXPR T + erfc_impl(T x) { + return T(1) - sprout::math::erf(x); + } + template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR FloatType erfc(FloatType x) { - return x == std::numeric_limits::infinity() ? FloatType(0) + return sprout::math::isnan(x) ? x + : x == std::numeric_limits::infinity() ? FloatType(0) : x == -std::numeric_limits::infinity() ? FloatType(2) - : FloatType(1) - sprout::erf(x) +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::erfc(x) +#else + : static_cast(sprout::math::detail::erfc_impl(static_cast::type>(x))) +#endif ; } - template< typename IntType, typename sprout::enabler_if::value>::type = sprout::enabler @@ -32,7 +44,7 @@ namespace sprout { } } // namespace detail - using NS_SPROUT_MATH_DETAIL::erfc; + using sprout::math::detail::erfc; } // namespace math using sprout::math::erfc; diff --git a/sprout/math/fabs.hpp b/sprout/math/fabs.hpp index 6c95b36a..c40ba71b 100644 --- a/sprout/math/fabs.hpp +++ b/sprout/math/fabs.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -16,7 +17,10 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType fabs(FloatType x) { - return sprout::math::copysign(x, FloatType(0)); + return sprout::math::isnan(x) ? std::numeric_limits::quiet_NaN() + : x == 0 ? FloatType(0) + : sprout::math::copysign(x, FloatType(0)) + ; } template< typename IntType, diff --git a/sprout/math/float2_exponent.hpp b/sprout/math/float2_exponent.hpp index 56db179d..2398cefe 100644 --- a/sprout/math/float2_exponent.hpp +++ b/sprout/math/float2_exponent.hpp @@ -19,9 +19,9 @@ namespace sprout { > inline SPROUT_CONSTEXPR int float2_exponent(FloatType x) { - return x == 0 ? 0 + return sprout::math::isnan(x) ? 0 + : x == 0 ? 0 : x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() ? 0 - : sprout::math::isnan(x) ? FP_ILOGBNAN : sprout::math::ilogb2(x) + 1 ; } diff --git a/sprout/math/float2_sig_exp.hpp b/sprout/math/float2_sig_exp.hpp index 527cac5a..d633ef9f 100644 --- a/sprout/math/float2_sig_exp.hpp +++ b/sprout/math/float2_sig_exp.hpp @@ -29,9 +29,9 @@ namespace sprout { inline SPROUT_CONSTEXPR sprout::pair float2_sig_exp(FloatType x) { typedef sprout::pair type; - return x == std::numeric_limits::infinity() ? type(std::numeric_limits::infinity(), 0) + return sprout::math::isnan(x) ? type(x, 0) + : x == std::numeric_limits::infinity() ? type(std::numeric_limits::infinity(), 0) : x == -std::numeric_limits::infinity() ? type(-std::numeric_limits::infinity(), 0) - : sprout::math::isnan(x) ? type(std::numeric_limits::quiet_NaN(), FP_ILOGBNAN) : x == 0 ? type(x, 0) : sprout::math::detail::float2_sig_exp_impl(x, sprout::math::ilogb2(x) + 1) ; diff --git a/sprout/math/float2_significand.hpp b/sprout/math/float2_significand.hpp index 458ad711..c812a93c 100644 --- a/sprout/math/float2_significand.hpp +++ b/sprout/math/float2_significand.hpp @@ -19,9 +19,9 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType float2_significand(FloatType x) { - return x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() + return sprout::math::isnan(x) ? x + : x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() : x == -std::numeric_limits::infinity() ? -std::numeric_limits::infinity() - : sprout::math::isnan(x) ? std::numeric_limits::quiet_NaN() : x == 0 ? x : x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x)) ; diff --git a/sprout/math/float_exponent.hpp b/sprout/math/float_exponent.hpp index 0ce6ea1c..ee90bf35 100644 --- a/sprout/math/float_exponent.hpp +++ b/sprout/math/float_exponent.hpp @@ -1,7 +1,6 @@ #ifndef SPROUT_MATH_FLOAT_EXPONENT_HPP #define SPROUT_MATH_FLOAT_EXPONENT_HPP -#include #include #include #include @@ -19,9 +18,9 @@ namespace sprout { > inline SPROUT_CONSTEXPR int float_exponent(FloatType x) { - return x == 0 ? 0 + return sprout::math::isnan(x) ? 0 + : x == 0 ? 0 : x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() ? 0 - : sprout::math::isnan(x) ? FP_ILOGBNAN : sprout::math::ilogb(x) + 1 ; } diff --git a/sprout/math/float_sig_exp.hpp b/sprout/math/float_sig_exp.hpp index 66d0509e..a4238613 100644 --- a/sprout/math/float_sig_exp.hpp +++ b/sprout/math/float_sig_exp.hpp @@ -1,7 +1,6 @@ #ifndef SPROUT_MATH_FLOAT_SIG_EXP_HPP #define SPROUT_MATH_FLOAT_SIG_EXP_HPP -#include #include #include #include @@ -29,9 +28,9 @@ namespace sprout { inline SPROUT_CONSTEXPR sprout::pair float_sig_exp(FloatType x) { typedef sprout::pair type; - return x == std::numeric_limits::infinity() ? type(std::numeric_limits::infinity(), 0) + return sprout::math::isnan(x) ? type(x, 0) + : x == std::numeric_limits::infinity() ? type(std::numeric_limits::infinity(), 0) : x == -std::numeric_limits::infinity() ? type(-std::numeric_limits::infinity(), 0) - : sprout::math::isnan(x) ? type(std::numeric_limits::quiet_NaN(), FP_ILOGBNAN) : x == 0 ? type(x, 0) : sprout::math::detail::float_sig_exp_impl(x, sprout::math::ilogb(x) + 1) ; diff --git a/sprout/math/float_significand.hpp b/sprout/math/float_significand.hpp index 9428c051..7beaadad 100644 --- a/sprout/math/float_significand.hpp +++ b/sprout/math/float_significand.hpp @@ -19,9 +19,9 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType float_significand(FloatType x) { - return x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() + return sprout::math::isnan(x) ? x + : x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() : x == -std::numeric_limits::infinity() ? -std::numeric_limits::infinity() - : sprout::math::isnan(x) ? std::numeric_limits::quiet_NaN() : x == 0 ? x : x / sprout::detail::pow_n(FloatType(std::numeric_limits::radix), sprout::float_exponent(x)) ; diff --git a/sprout/math/fmod.hpp b/sprout/math/fmod.hpp index 2b8fd467..b5cc0842 100644 --- a/sprout/math/fmod.hpp +++ b/sprout/math/fmod.hpp @@ -5,6 +5,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -12,17 +16,32 @@ namespace sprout { namespace math { namespace detail { + template + inline SPROUT_CONSTEXPR T + fmod_impl(T x, T y) { + return x - sprout::math::trunc(x / y) * y; + } + template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR FloatType fmod(FloatType x, FloatType y) { - return x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() || y == 0 - ? std::numeric_limits::quiet_NaN() - : x == 0 ? FloatType(0) + return sprout::math::isnan(y) + ? sprout::math::isnan(x) + ? sprout::math::signbit(y) || sprout::math::signbit(x) ? -std::numeric_limits::quiet_NaN() + : std::numeric_limits::quiet_NaN() + : y + : sprout::math::isnan(x) ? x + : x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() || y == 0 + ? -std::numeric_limits::quiet_NaN() + : x == 0 ? x : y == std::numeric_limits::infinity() || y == -std::numeric_limits::infinity() ? x - : x - sprout::math::trunc(x / y) * y + : static_cast(sprout::math::detail::fmod_impl( + static_cast::type>(x), + static_cast::type>(y) + )) ; } diff --git a/sprout/math/frac_int.hpp b/sprout/math/frac_int.hpp index 9a7ca9a0..bb1f4f3a 100644 --- a/sprout/math/frac_int.hpp +++ b/sprout/math/frac_int.hpp @@ -18,8 +18,8 @@ namespace sprout { inline SPROUT_CONSTEXPR sprout::pair frac_int_impl(T x, T ipart) { typedef sprout::pair type; - return x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() ? type(sprout::math::copysign(T(0), x), ipart) - : sprout::math::isnan(x) ? type(std::numeric_limits::quiet_NaN(), ipart) + return sprout::math::isnan(x) ? type(x, ipart) + : x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() ? type(sprout::math::copysign(T(0), x), ipart) : x == 0 ? type(x, ipart) : x == ipart ? type(T(0) * x, ipart) : type(sprout::math::copysign(x - ipart, x), ipart) diff --git a/sprout/math/fractional_part.hpp b/sprout/math/fractional_part.hpp index 8c76d04a..6084ea55 100644 --- a/sprout/math/fractional_part.hpp +++ b/sprout/math/fractional_part.hpp @@ -27,8 +27,8 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType fractional_part(FloatType x) { - return x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() ? sprout::math::copysign(FloatType(0), x) - : sprout::math::isnan(x) ? std::numeric_limits::quiet_NaN() + return sprout::math::isnan(x) ? x + : x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() ? sprout::math::copysign(FloatType(0), x) : x == 0 ? x : sprout::math::detail::fractional_part_impl(x, sprout::integer_part(x)) ; diff --git a/sprout/math/functions.hpp b/sprout/math/functions.hpp index 5787ad10..9ab5ded8 100644 --- a/sprout/math/functions.hpp +++ b/sprout/math/functions.hpp @@ -7,5 +7,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_MATH_FUNCTIONS_HPP diff --git a/sprout/math/hypot.hpp b/sprout/math/hypot.hpp index 4334d580..62320e9e 100644 --- a/sprout/math/hypot.hpp +++ b/sprout/math/hypot.hpp @@ -4,28 +4,59 @@ #include #include #include -#include -#include #include +#include +#include +#include #include #include +#include +#include namespace sprout { namespace math { namespace detail { + template + inline SPROUT_CONSTEXPR T + hypot_impl_2(T t, T w) { + return t * sprout::math::sqrt(T(1) + w * w); + } + template + inline SPROUT_CONSTEXPR T + hypot_impl_1(T x, T y) { + return x < y + ? sprout::math::detail::hypot_impl_2(y, x / y) + : sprout::math::detail::hypot_impl_2(x, y / x) + ; + } + template + inline SPROUT_CONSTEXPR T + hypot_impl(T x, T y) { + return sprout::math::detail::hypot_impl_1(sprout::math::fabs(x), sprout::math::fabs(y)); + } + template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR FloatType hypot(FloatType x, FloatType y) { - return y == 0 ? sprout::math::fabs(x) - : x == 0 ? sprout::math::fabs(y) - : y == std::numeric_limits::infinity() || y == -std::numeric_limits::infinity() + return y == std::numeric_limits::infinity() || y == -std::numeric_limits::infinity() ? std::numeric_limits::infinity() : x == std::numeric_limits::infinity() || x == -std::numeric_limits::infinity() ? std::numeric_limits::infinity() - : sprout::math::sqrt(x * x + y * y) + : sprout::math::isnan(y) ? y + : sprout::math::isnan(x) ? x +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::hypot(x, y) +#else + : y == 0 ? sprout::math::fabs(x) + : x == 0 ? sprout::math::fabs(y) + : static_cast(sprout::math::detail::hypot_impl( + static_cast::type>(x), + static_cast::type>(y) + )) +#endif ; } @@ -43,7 +74,7 @@ namespace sprout { } } // namespace detail - using NS_SPROUT_MATH_DETAIL::hypot; + using sprout::math::detail::hypot; } // namespace math using sprout::math::hypot; diff --git a/sprout/math/integer.hpp b/sprout/math/integer.hpp new file mode 100644 index 00000000..5e2761eb --- /dev/null +++ b/sprout/math/integer.hpp @@ -0,0 +1,9 @@ +#ifndef SPROUT_MATH_INTEGER_HPP +#define SPROUT_MATH_INTEGER_HPP + +#include +#include +#include +#include + +#endif // #ifndef SPROUT_MATH_INTEGER_HPP diff --git a/sprout/math/integer_part.hpp b/sprout/math/integer_part.hpp index 56ada502..794bee53 100644 --- a/sprout/math/integer_part.hpp +++ b/sprout/math/integer_part.hpp @@ -18,9 +18,9 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType integer_part(FloatType x) { - return x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() + return sprout::math::isnan(x) ? x + : x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() : x == -std::numeric_limits::infinity() ? -std::numeric_limits::infinity() - : sprout::math::isnan(x) ? std::numeric_limits::quiet_NaN() : x == 0 ? x : sprout::math::trunc(x) ; diff --git a/sprout/math/is_even.hpp b/sprout/math/is_even.hpp new file mode 100644 index 00000000..c4705c75 --- /dev/null +++ b/sprout/math/is_even.hpp @@ -0,0 +1,28 @@ +#ifndef SPROUT_MATH_IS_EVEN_HPP +#define SPROUT_MATH_IS_EVEN_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace math { + namespace detail { + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + is_even(FloatType x) { + return sprout::math::fmod(x, FloatType(2)) == FloatType(0); + } + } // namespace detail + + using sprout::math::detail::is_even; + } // namespace math + + using sprout::math::is_even; +} // namespace sprout + +#endif // #ifndef SPROUT_MATH_IS_EVEN_HPP diff --git a/sprout/math/is_integer.hpp b/sprout/math/is_integer.hpp new file mode 100644 index 00000000..2ce00093 --- /dev/null +++ b/sprout/math/is_integer.hpp @@ -0,0 +1,28 @@ +#ifndef SPROUT_MATH_IS_INTEGER_HPP +#define SPROUT_MATH_IS_INTEGER_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace math { + namespace detail { + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + is_integer(FloatType x) { + return x == sprout::math::trunc(x); + } + } // namespace detail + + using sprout::math::detail::is_integer; + } // namespace math + + using sprout::math::is_integer; +} // namespace sprout + +#endif // #ifndef SPROUT_MATH_IS_INTEGER_HPP diff --git a/sprout/math/is_odd.hpp b/sprout/math/is_odd.hpp new file mode 100644 index 00000000..23596757 --- /dev/null +++ b/sprout/math/is_odd.hpp @@ -0,0 +1,28 @@ +#ifndef SPROUT_MATH_IS_ODD_HPP +#define SPROUT_MATH_IS_ODD_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace math { + namespace detail { + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR bool + is_odd(FloatType x) { + return sprout::math::fmod(x, FloatType(2)) == FloatType(1); + } + } // namespace detail + + using sprout::math::detail::is_odd; + } // namespace math + + using sprout::math::is_odd; +} // namespace sprout + +#endif // #ifndef SPROUT_MATH_IS_ODD_HPP diff --git a/sprout/math/lgamma.hpp b/sprout/math/lgamma.hpp index 1b9ef81b..f2153b72 100644 --- a/sprout/math/lgamma.hpp +++ b/sprout/math/lgamma.hpp @@ -7,11 +7,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include namespace sprout { @@ -181,13 +183,17 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType lgamma(FloatType x) { - typedef typename sprout::math::detail::float_compute::type type; - return x == 1 ? FloatType(0) - : x == 2 ? FloatType(0) - : x <= 0 && x == std::trunc(x) ? std::numeric_limits::infinity() + return sprout::math::isnan(x) ? x + : x <= 0 && sprout::math::is_integer(x) ? std::numeric_limits::infinity() : x == -std::numeric_limits::infinity() ? std::numeric_limits::infinity() : x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() - : static_cast(sprout::math::detail::lgamma_impl(static_cast(x))) +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::lgamma(x) +#else + : x == 1 ? FloatType(0) + : x == 2 ? FloatType(0) + : static_cast(sprout::math::detail::lgamma_impl(static_cast::type>(x))) +#endif ; } @@ -201,7 +207,7 @@ namespace sprout { } } // namespace detail - using NS_SPROUT_MATH_DETAIL::lgamma; + using sprout::math::detail::lgamma; } // namespace math using sprout::math::lgamma; diff --git a/sprout/math/log_a.hpp b/sprout/math/log_a.hpp index 65c90368..ca7988e1 100644 --- a/sprout/math/log_a.hpp +++ b/sprout/math/log_a.hpp @@ -4,24 +4,34 @@ #include #include #include -#include +#include #include +#include #include #include namespace sprout { namespace math { namespace detail { + template + inline SPROUT_CONSTEXPR T + log_a_impl(T x, T y) { + return x == 2 ? sprout::math::log(y) / sprout::math::ln_two() + : x == 10 ? sprout::math::log(y) / sprout::math::ln_ten() + : sprout::math::log(y) / sprout::math::log(x) + ; + } + template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR FloatType log_a(FloatType x, FloatType y) { - return x == 2 ? sprout::math::log(y) / sprout::math::ln_two() - : x == 10 ? sprout::math::log(y) / sprout::math::ln_ten() - : sprout::math::log(y) / sprout::math::log(x) - ; + return static_cast(sprout::math::detail::log_a_impl( + static_cast::type>(x), + static_cast::type>(y) + )); } template< diff --git a/sprout/math/pow.hpp b/sprout/math/pow.hpp index 415595ce..26b1feca 100644 --- a/sprout/math/pow.hpp +++ b/sprout/math/pow.hpp @@ -5,45 +5,67 @@ #include #include #include +#include +#include +#include +#include #include #include -#include +#include +#include #include #include namespace sprout { namespace math { namespace detail { + template + inline SPROUT_CONSTEXPR T + pow_impl(T x, T y) { + return sprout::math::exp(y * sprout::math::log(x)); + } + template< typename FloatType, typename sprout::enabler_if::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR FloatType pow(FloatType x, FloatType y) { - return x == 0 - ? y < 0 ? std::numeric_limits::infinity() - : y > 0 ? FloatType(0) - : sprout::math::exp(y * sprout::math::log(x)) - : x == -1 && (y == std::numeric_limits::infinity() || y == -std::numeric_limits::infinity()) ? FloatType(1) - : x == 1 ? FloatType(1) + return x == 1 ? FloatType(1) : y == 0 ? FloatType(1) + : sprout::math::isnan(y) ? y + : sprout::math::isnan(x) ? x + : x == 0 + ? y < 0 + ? sprout::math::is_odd(y) ? sprout::math::copysign(std::numeric_limits::infinity(), x) + : std::numeric_limits::infinity() + : sprout::math::is_odd(y) ? x + : FloatType(0) + : x == -1 && (y == std::numeric_limits::infinity() || y == -std::numeric_limits::infinity()) ? FloatType(1) : y == -std::numeric_limits::infinity() - ? x < 1 && x > -1 ? std::numeric_limits::infinity() - : x > 1 || x < -1 ? FloatType(0) - : sprout::math::exp(y * sprout::math::log(x)) + ? sprout::math::fabs(x) < 1 ? std::numeric_limits::infinity() + : FloatType(0) : y == std::numeric_limits::infinity() - ? x < 1 && x > -1 ? FloatType(0) - : x > 1 || x < -1 ? std::numeric_limits::infinity() - : sprout::math::exp(y * sprout::math::log(x)) + ? sprout::math::fabs(x) < 1 ? FloatType(0) + : std::numeric_limits::infinity() : x == -std::numeric_limits::infinity() - ? y < 0 ? FloatType(0) - : y > 0 ? std::numeric_limits::infinity() - : sprout::math::exp(y * sprout::math::log(x)) + ? y < 0 + ? sprout::math::is_odd(y) ? -FloatType(0) + : FloatType(0) + : sprout::math::is_odd(y) ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity() : x == std::numeric_limits::infinity() ? y < 0 ? FloatType(0) - : y > 0 ? std::numeric_limits::infinity() - : sprout::math::exp(y * sprout::math::log(x)) - : sprout::math::exp(y * sprout::math::log(x)) + : std::numeric_limits::infinity() + : x < 0 && !sprout::math::is_integer(y) ? std::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::pow(x, y) +#else + : static_cast(sprout::math::detail::pow_impl( + static_cast::type>(x), + static_cast::type>(y) + )) +#endif ; } @@ -60,8 +82,13 @@ namespace sprout { return sprout::math::detail::pow(static_cast(x), static_cast(y)); } } // namespace detail - - using NS_SPROUT_MATH_DETAIL::pow; + // + // issue: + // [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ] + // pow(-0, y) returns - for y an odd integer < 0. + // # returns + . ( same as pow(+0, y) ) + // + using sprout::math::detail::pow; } // namespace math using sprout::math::pow; diff --git a/sprout/math/sqrt.hpp b/sprout/math/sqrt.hpp index 7cd77fec..09031931 100644 --- a/sprout/math/sqrt.hpp +++ b/sprout/math/sqrt.hpp @@ -14,15 +14,20 @@ namespace sprout { namespace detail { template inline SPROUT_CONSTEXPR T - sqrt_impl_1(T x, T s, T s2) { + sqrt_impl_2(T x, T s, T s2) { return !(s < s2) ? s2 - : sprout::math::detail::sqrt_impl_1(x, (x / s + s) / 2, s) + : sprout::math::detail::sqrt_impl_2(x, (x / s + s) / 2, s) ; } template inline SPROUT_CONSTEXPR T - sqrt_impl(T x, T s) { - return sprout::math::detail::sqrt_impl_1(x, (x / s + s) / 2, s); + sqrt_impl_1(T x, T s) { + return sprout::math::detail::sqrt_impl_2(x, (x / s + s) / 2, s); + } + template + inline SPROUT_CONSTEXPR T + sqrt_impl(T x) { + return sprout::math::detail::sqrt_impl_1(x, x > 1 ? x : T(1)); } template< @@ -31,12 +36,16 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType sqrt(FloatType x) { - typedef typename sprout::math::detail::float_compute::type type; - return x == 0 ? FloatType(0) + return sprout::math::isnan(x) ? x : x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() - : sprout::math::isnan(x) ? std::numeric_limits::quiet_NaN() - : x < 0 ? std::numeric_limits::quiet_NaN() - : static_cast(sprout::math::detail::sqrt_impl(static_cast(x), x > 1 ? static_cast(x) : type(1))); + : x < 0 ? -std::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::sqrt(x) +#else + : x == 0 ? x + : static_cast(sprout::math::detail::sqrt_impl(static_cast::type>(x))) +#endif + ; } template< typename IntType, @@ -48,7 +57,7 @@ namespace sprout { } } // namespace detail - using NS_SPROUT_MATH_DETAIL::sqrt; + using sprout::math::detail::sqrt; } // namespace math using sprout::math::sqrt; diff --git a/sprout/math/tgamma.hpp b/sprout/math/tgamma.hpp index 7da7d0f9..c54c7693 100644 --- a/sprout/math/tgamma.hpp +++ b/sprout/math/tgamma.hpp @@ -7,9 +7,11 @@ #include #include #include +#include +#include #include #include -#include +#include #include #include #include HDR_ALGORITHM_MIN_MAX_SSCRISK_CEL_OR_SPROUT @@ -105,12 +107,16 @@ namespace sprout { > inline SPROUT_CONSTEXPR FloatType tgamma(FloatType x) { - typedef typename sprout::math::detail::float_compute::type type; - return x == 0 ? std::numeric_limits::infinity() - : x == -std::numeric_limits::infinity() ? std::numeric_limits::quiet_NaN() + return sprout::math::isnan(x) ? x + : x == 0 ? sprout::math::copysign(std::numeric_limits::infinity(), x) + : x == -std::numeric_limits::infinity() ? -std::numeric_limits::quiet_NaN() : x == std::numeric_limits::infinity() ? std::numeric_limits::infinity() - : x < 0 && x == std::trunc(x) ? std::numeric_limits::quiet_NaN() - : static_cast(sprout::math::detail::tgamma_impl(static_cast(x))) + : x < 0 && sprout::math::is_integer(x) ? std::numeric_limits::quiet_NaN() +#if SPROUT_USE_BUILTIN_CMATH_FUNCTION + : std::tgamma(x) +#else + : static_cast(sprout::math::detail::tgamma_impl(static_cast::type>(x))) +#endif ; } @@ -123,8 +129,13 @@ namespace sprout { return sprout::math::detail::tgamma(static_cast(x)); } } // namespace detail - - using NS_SPROUT_MATH_DETAIL::tgamma; + // + // issue: + // [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ] + // tgamma(-0) returns - . + // # returns + . ( same as tgamma(+0) ) + // + using sprout::math::detail::tgamma; } // namespace math using sprout::math::tgamma;