1
0
Fork 0
mirror of https://github.com/bolero-MURAKAMI/Sprout synced 2025-02-04 21:33:56 +00:00

fix math functions

This commit is contained in:
bolero-MURAKAMI 2013-05-06 00:22:08 +09:00
parent fccb16687b
commit 7794e56192
27 changed files with 342 additions and 102 deletions

View file

@ -5,6 +5,7 @@
#include <sprout/config.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/fabs.hpp>
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

View file

@ -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<double>::quiet_NaN()
: std::numeric_limits<double>::quiet_NaN()
? sprout::math::signbit(y) && sprout::math::signbit(x) ? -std::numeric_limits<FloatType>::quiet_NaN()
: std::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == -std::numeric_limits<FloatType>::infinity()

View file

@ -5,24 +5,38 @@
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/pow.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/pow.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
namespace math {
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR T
cbrt_impl(T x) {
return x < 0 ? -sprout::pow(-x, sprout::math::third<T>())
: sprout::pow(x, sprout::math::third<T>())
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: x == -std::numeric_limits<FloatType>::infinity() ? -std::numeric_limits<FloatType>::infinity()
: x < 0 ? -sprout::pow(-x, sprout::math::third<FloatType>())
: sprout::pow(x, sprout::math::third<FloatType>())
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::cbrt(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::cbrt_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::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;

View file

@ -4,11 +4,12 @@
#include <limits>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/detail/pow.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/itrunc.hpp>
#include <sprout/math/fractional_part.hpp>
#include <sprout/detail/pow.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
@ -102,13 +103,13 @@ namespace sprout {
template<typename T>
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<typename T>
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<FloatType>::type type;
return x == 0 ? FloatType(0)
return sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() ? FloatType(1)
: x == -std::numeric_limits<FloatType>::infinity() ? FloatType(-1)
: static_cast<FloatType>(sprout::math::detail::erf_impl(static_cast<type>(x)))
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::erf(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::erf_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::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;

View file

@ -4,24 +4,36 @@
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/erf.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
namespace math {
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR T
erfc_impl(T x) {
return T(1) - sprout::math::erf(x);
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
erfc(FloatType x) {
return x == std::numeric_limits<FloatType>::infinity() ? FloatType(0)
return sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() ? FloatType(0)
: x == -std::numeric_limits<FloatType>::infinity() ? FloatType(2)
: FloatType(1) - sprout::erf(x)
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::erfc(x)
#else
: static_cast<FloatType>(sprout::math::detail::erfc_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
template<
typename IntType,
typename sprout::enabler_if<std::is_integral<IntType>::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;

View file

@ -4,6 +4,7 @@
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/copysign.hpp>
#include <sprout/type_traits/enabler_if.hpp>
@ -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<FloatType>::quiet_NaN()
: x == 0 ? FloatType(0)
: sprout::math::copysign(x, FloatType(0))
;
}
template<
typename IntType,

View file

@ -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<FloatType>::infinity() || x == -std::numeric_limits<FloatType>::infinity() ? 0
: sprout::math::isnan(x) ? FP_ILOGBNAN
: sprout::math::ilogb2(x) + 1
;
}

View file

@ -29,9 +29,9 @@ namespace sprout {
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
float2_sig_exp(FloatType x) {
typedef sprout::pair<FloatType, int> type;
return x == std::numeric_limits<FloatType>::infinity() ? type(std::numeric_limits<FloatType>::infinity(), 0)
return sprout::math::isnan(x) ? type(x, 0)
: x == std::numeric_limits<FloatType>::infinity() ? type(std::numeric_limits<FloatType>::infinity(), 0)
: x == -std::numeric_limits<FloatType>::infinity() ? type(-std::numeric_limits<FloatType>::infinity(), 0)
: sprout::math::isnan(x) ? type(std::numeric_limits<FloatType>::quiet_NaN(), FP_ILOGBNAN)
: x == 0 ? type(x, 0)
: sprout::math::detail::float2_sig_exp_impl(x, sprout::math::ilogb2(x) + 1)
;

View file

@ -19,9 +19,9 @@ namespace sprout {
>
inline SPROUT_CONSTEXPR FloatType
float2_significand(FloatType x) {
return x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
return sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: x == -std::numeric_limits<FloatType>::infinity() ? -std::numeric_limits<FloatType>::infinity()
: sprout::math::isnan(x) ? std::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: x / sprout::detail::pow_n(FloatType(2), sprout::float2_exponent(x))
;

View file

@ -1,7 +1,6 @@
#ifndef SPROUT_MATH_FLOAT_EXPONENT_HPP
#define SPROUT_MATH_FLOAT_EXPONENT_HPP
#include <climits>
#include <limits>
#include <type_traits>
#include <sprout/config.hpp>
@ -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<FloatType>::infinity() || x == -std::numeric_limits<FloatType>::infinity() ? 0
: sprout::math::isnan(x) ? FP_ILOGBNAN
: sprout::math::ilogb(x) + 1
;
}

View file

@ -1,7 +1,6 @@
#ifndef SPROUT_MATH_FLOAT_SIG_EXP_HPP
#define SPROUT_MATH_FLOAT_SIG_EXP_HPP
#include <climits>
#include <limits>
#include <type_traits>
#include <sprout/config.hpp>
@ -29,9 +28,9 @@ namespace sprout {
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
float_sig_exp(FloatType x) {
typedef sprout::pair<FloatType, int> type;
return x == std::numeric_limits<FloatType>::infinity() ? type(std::numeric_limits<FloatType>::infinity(), 0)
return sprout::math::isnan(x) ? type(x, 0)
: x == std::numeric_limits<FloatType>::infinity() ? type(std::numeric_limits<FloatType>::infinity(), 0)
: x == -std::numeric_limits<FloatType>::infinity() ? type(-std::numeric_limits<FloatType>::infinity(), 0)
: sprout::math::isnan(x) ? type(std::numeric_limits<FloatType>::quiet_NaN(), FP_ILOGBNAN)
: x == 0 ? type(x, 0)
: sprout::math::detail::float_sig_exp_impl(x, sprout::math::ilogb(x) + 1)
;

View file

@ -19,9 +19,9 @@ namespace sprout {
>
inline SPROUT_CONSTEXPR FloatType
float_significand(FloatType x) {
return x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
return sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: x == -std::numeric_limits<FloatType>::infinity() ? -std::numeric_limits<FloatType>::infinity()
: sprout::math::isnan(x) ? std::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: x / sprout::detail::pow_n(FloatType(std::numeric_limits<FloatType>::radix), sprout::float_exponent(x))
;

View file

@ -5,6 +5,10 @@
#include <type_traits>
#include <stdexcept>
#include <sprout/config.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/signbit.hpp>
#include <sprout/math/trunc.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/type_traits/float_promote.hpp>
@ -12,17 +16,32 @@
namespace sprout {
namespace math {
namespace detail {
template<typename T>
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
fmod(FloatType x, FloatType y) {
return x == std::numeric_limits<FloatType>::infinity() || x == -std::numeric_limits<FloatType>::infinity() || y == 0
? std::numeric_limits<FloatType>::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<FloatType>::quiet_NaN()
: std::numeric_limits<FloatType>::quiet_NaN()
: y
: sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() || x == -std::numeric_limits<FloatType>::infinity() || y == 0
? -std::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: y == std::numeric_limits<FloatType>::infinity() || y == -std::numeric_limits<FloatType>::infinity() ? x
: x - sprout::math::trunc(x / y) * y
: static_cast<FloatType>(sprout::math::detail::fmod_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
;
}

View file

@ -18,8 +18,8 @@ namespace sprout {
inline SPROUT_CONSTEXPR sprout::pair<T, T>
frac_int_impl(T x, T ipart) {
typedef sprout::pair<T, T> type;
return x == std::numeric_limits<T>::infinity() || x == -std::numeric_limits<T>::infinity() ? type(sprout::math::copysign(T(0), x), ipart)
: sprout::math::isnan(x) ? type(std::numeric_limits<T>::quiet_NaN(), ipart)
return sprout::math::isnan(x) ? type(x, ipart)
: x == std::numeric_limits<T>::infinity() || x == -std::numeric_limits<T>::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)

View file

@ -27,8 +27,8 @@ namespace sprout {
>
inline SPROUT_CONSTEXPR FloatType
fractional_part(FloatType x) {
return x == std::numeric_limits<FloatType>::infinity() || x == -std::numeric_limits<FloatType>::infinity() ? sprout::math::copysign(FloatType(0), x)
: sprout::math::isnan(x) ? std::numeric_limits<FloatType>::quiet_NaN()
return sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() || x == -std::numeric_limits<FloatType>::infinity() ? sprout::math::copysign(FloatType(0), x)
: x == 0 ? x
: sprout::math::detail::fractional_part_impl(x, sprout::integer_part(x))
;

View file

@ -7,5 +7,6 @@
#include <sprout/math/factorial.hpp>
#include <sprout/math/bernoulli.hpp>
#include <sprout/math/comparison.hpp>
#include <sprout/math/integer.hpp>
#endif // #ifndef SPROUT_MATH_FUNCTIONS_HPP

View file

@ -4,28 +4,59 @@
#include <limits>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/float_promote.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/signbit.hpp>
#include <sprout/math/fabs.hpp>
#include <sprout/math/sqrt.hpp>
#include <sprout/type_traits/float_promote.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
namespace math {
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR T
hypot_impl_2(T t, T w) {
return t * sprout::math::sqrt(T(1) + w * w);
}
template<typename T>
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<typename T>
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<std::is_floating_point<FloatType>::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<FloatType>::infinity() || y == -std::numeric_limits<FloatType>::infinity()
return y == std::numeric_limits<FloatType>::infinity() || y == -std::numeric_limits<FloatType>::infinity()
? std::numeric_limits<FloatType>::infinity()
: x == std::numeric_limits<FloatType>::infinity() || x == -std::numeric_limits<FloatType>::infinity()
? std::numeric_limits<FloatType>::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<FloatType>(sprout::math::detail::hypot_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::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;

9
sprout/math/integer.hpp Normal file
View file

@ -0,0 +1,9 @@
#ifndef SPROUT_MATH_INTEGER_HPP
#define SPROUT_MATH_INTEGER_HPP
#include <sprout/config.hpp>
#include <sprout/math/is_integer.hpp>
#include <sprout/math/is_odd.hpp>
#include <sprout/math/is_even.hpp>
#endif // #ifndef SPROUT_MATH_INTEGER_HPP

View file

@ -18,9 +18,9 @@ namespace sprout {
>
inline SPROUT_CONSTEXPR FloatType
integer_part(FloatType x) {
return x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
return sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: x == -std::numeric_limits<FloatType>::infinity() ? -std::numeric_limits<FloatType>::infinity()
: sprout::math::isnan(x) ? std::numeric_limits<FloatType>::quiet_NaN()
: x == 0 ? x
: sprout::math::trunc(x)
;

28
sprout/math/is_even.hpp Normal file
View file

@ -0,0 +1,28 @@
#ifndef SPROUT_MATH_IS_EVEN_HPP
#define SPROUT_MATH_IS_EVEN_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/math/fmod.hpp>
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::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

View file

@ -0,0 +1,28 @@
#ifndef SPROUT_MATH_IS_INTEGER_HPP
#define SPROUT_MATH_IS_INTEGER_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/math/trunc.hpp>
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::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

28
sprout/math/is_odd.hpp Normal file
View file

@ -0,0 +1,28 @@
#ifndef SPROUT_MATH_IS_ODD_HPP
#define SPROUT_MATH_IS_ODD_HPP
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/math/fmod.hpp>
namespace sprout {
namespace math {
namespace detail {
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::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

View file

@ -7,11 +7,13 @@
#include <sprout/math/detail/config.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/factorial.hpp>
#include <sprout/math/log.hpp>
#include <sprout/math/sin.hpp>
#include <sprout/math/fabs.hpp>
#include <sprout/math/itrunc.hpp>
#include <sprout/math/is_integer.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
@ -181,13 +183,17 @@ namespace sprout {
>
inline SPROUT_CONSTEXPR FloatType
lgamma(FloatType x) {
typedef typename sprout::math::detail::float_compute<FloatType>::type type;
return x == 1 ? FloatType(0)
: x == 2 ? FloatType(0)
: x <= 0 && x == std::trunc(x) ? std::numeric_limits<FloatType>::infinity()
return sprout::math::isnan(x) ? x
: x <= 0 && sprout::math::is_integer(x) ? std::numeric_limits<FloatType>::infinity()
: x == -std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: static_cast<FloatType>(sprout::math::detail::lgamma_impl(static_cast<type>(x)))
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::lgamma(x)
#else
: x == 1 ? FloatType(0)
: x == 2 ? FloatType(0)
: static_cast<FloatType>(sprout::math::detail::lgamma_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::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;

View file

@ -4,24 +4,34 @@
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/log.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/math/log.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#include <sprout/type_traits/float_promote.hpp>
namespace sprout {
namespace math {
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR T
log_a_impl(T x, T y) {
return x == 2 ? sprout::math::log(y) / sprout::math::ln_two<T>()
: x == 10 ? sprout::math::log(y) / sprout::math::ln_ten<T>()
: sprout::math::log(y) / sprout::math::log(x)
;
}
template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::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<FloatType>()
: x == 10 ? sprout::math::log(y) / sprout::math::ln_ten<FloatType>()
: sprout::math::log(y) / sprout::math::log(x)
;
return static_cast<FloatType>(sprout::math::detail::log_a_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
));
}
template<

View file

@ -5,45 +5,67 @@
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/copysign.hpp>
#include <sprout/math/fabs.hpp>
#include <sprout/math/exp.hpp>
#include <sprout/math/log.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/math/is_integer.hpp>
#include <sprout/math/is_odd.hpp>
#include <sprout/type_traits/float_promote.hpp>
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
namespace math {
namespace detail {
template<typename T>
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<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType
pow(FloatType x, FloatType y) {
return x == 0
? y < 0 ? std::numeric_limits<FloatType>::infinity()
: y > 0 ? FloatType(0)
: sprout::math::exp(y * sprout::math::log(x))
: x == -1 && (y == std::numeric_limits<FloatType>::infinity() || y == -std::numeric_limits<FloatType>::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<FloatType>::infinity(), x)
: std::numeric_limits<FloatType>::infinity()
: sprout::math::is_odd(y) ? x
: FloatType(0)
: x == -1 && (y == std::numeric_limits<FloatType>::infinity() || y == -std::numeric_limits<FloatType>::infinity()) ? FloatType(1)
: y == -std::numeric_limits<FloatType>::infinity()
? x < 1 && x > -1 ? std::numeric_limits<FloatType>::infinity()
: x > 1 || x < -1 ? FloatType(0)
: sprout::math::exp(y * sprout::math::log(x))
? sprout::math::fabs(x) < 1 ? std::numeric_limits<FloatType>::infinity()
: FloatType(0)
: y == std::numeric_limits<FloatType>::infinity()
? x < 1 && x > -1 ? FloatType(0)
: x > 1 || x < -1 ? std::numeric_limits<FloatType>::infinity()
: sprout::math::exp(y * sprout::math::log(x))
? sprout::math::fabs(x) < 1 ? FloatType(0)
: std::numeric_limits<FloatType>::infinity()
: x == -std::numeric_limits<FloatType>::infinity()
? y < 0 ? FloatType(0)
: y > 0 ? std::numeric_limits<FloatType>::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<FloatType>::infinity()
: std::numeric_limits<FloatType>::infinity()
: x == std::numeric_limits<FloatType>::infinity()
? y < 0 ? FloatType(0)
: y > 0 ? std::numeric_limits<FloatType>::infinity()
: sprout::math::exp(y * sprout::math::log(x))
: sprout::math::exp(y * sprout::math::log(x))
: std::numeric_limits<FloatType>::infinity()
: x < 0 && !sprout::math::is_integer(y) ? std::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::pow(x, y)
#else
: static_cast<FloatType>(sprout::math::detail::pow_impl(
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x),
static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(y)
))
#endif
;
}
@ -60,8 +82,13 @@ namespace sprout {
return sprout::math::detail::pow(static_cast<type>(x), static_cast<type>(y));
}
} // namespace detail
using NS_SPROUT_MATH_DETAIL::pow;
//
// issue:
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
// pow(-0, y) returns -<2D>‡ for y an odd integer < 0.
// # returns +<2B>‡ . ( same as pow(+0, y) )
//
using sprout::math::detail::pow;
} // namespace math
using sprout::math::pow;

View file

@ -14,15 +14,20 @@ namespace sprout {
namespace detail {
template<typename T>
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<typename T>
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<typename T>
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<FloatType>::type type;
return x == 0 ? FloatType(0)
return sprout::math::isnan(x) ? x
: x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: sprout::math::isnan(x) ? std::numeric_limits<FloatType>::quiet_NaN()
: x < 0 ? std::numeric_limits<FloatType>::quiet_NaN()
: static_cast<FloatType>(sprout::math::detail::sqrt_impl(static_cast<type>(x), x > 1 ? static_cast<type>(x) : type(1)));
: x < 0 ? -std::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::sqrt(x)
#else
: x == 0 ? x
: static_cast<FloatType>(sprout::math::detail::sqrt_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::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;

View file

@ -7,9 +7,11 @@
#include <sprout/config.hpp>
#include <sprout/math/detail/config.hpp>
#include <sprout/math/detail/float_compute.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/copysign.hpp>
#include <sprout/math/factorial.hpp>
#include <sprout/math/iround.hpp>
#include <sprout/math/trunc.hpp>
#include <sprout/math/is_integer.hpp>
#include <sprout/algorithm/clamp.hpp>
#include <sprout/type_traits/enabler_if.hpp>
#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<FloatType>::type type;
return x == 0 ? std::numeric_limits<FloatType>::infinity()
: x == -std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::quiet_NaN()
return sprout::math::isnan(x) ? x
: x == 0 ? sprout::math::copysign(std::numeric_limits<FloatType>::infinity(), x)
: x == -std::numeric_limits<FloatType>::infinity() ? -std::numeric_limits<FloatType>::quiet_NaN()
: x == std::numeric_limits<FloatType>::infinity() ? std::numeric_limits<FloatType>::infinity()
: x < 0 && x == std::trunc(x) ? std::numeric_limits<FloatType>::quiet_NaN()
: static_cast<FloatType>(sprout::math::detail::tgamma_impl(static_cast<type>(x)))
: x < 0 && sprout::math::is_integer(x) ? std::numeric_limits<FloatType>::quiet_NaN()
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
: std::tgamma(x)
#else
: static_cast<FloatType>(sprout::math::detail::tgamma_impl(static_cast<typename sprout::math::detail::float_compute<FloatType>::type>(x)))
#endif
;
}
@ -123,8 +129,13 @@ namespace sprout {
return sprout::math::detail::tgamma(static_cast<double>(x));
}
} // namespace detail
using NS_SPROUT_MATH_DETAIL::tgamma;
//
// issue:
// [ !SPROUT_USE_BUILTIN_CMATH_FUNCTION ]
// tgamma(-0) returns -<2D>‡ .
// # returns +<2B>‡ . ( same as tgamma(+0) )
//
using sprout::math::detail::tgamma;
} // namespace math
using sprout::math::tgamma;