mirror of
https://github.com/bolero-MURAKAMI/Sprout.git
synced 2024-12-23 21:25:49 +00:00
fix math/comparison.hpp
This commit is contained in:
parent
1c65d59971
commit
3b6ba46f17
23 changed files with 389 additions and 175 deletions
7
sprout/math.hpp
Normal file
7
sprout/math.hpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef SPROUT_MATH_HPP
|
||||
#define SPROUT_MATH_HPP
|
||||
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/functions.hpp>
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_HPP
|
|
@ -6,7 +6,7 @@
|
|||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/atan.hpp>
|
||||
#include <sprout/math/constants.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -31,9 +31,9 @@ namespace sprout {
|
|||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
atan2(ArithmeticType1 y, ArithmeticType2 x) {
|
||||
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::atan2(static_cast<type>(y), static_cast<type>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
|
|
@ -4,33 +4,24 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/equal_to.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/math/less.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
compare_impl(T x, T y) {
|
||||
return sprout::math::equal_to(x, y) ? 0
|
||||
: x < y ? -1
|
||||
: 1
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// compare
|
||||
//
|
||||
template<
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
||||
typename T, typename U,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
compare(T1 x, T2 y) {
|
||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
||||
return sprout::math::detail::compare_impl<promoted>(x, y);
|
||||
compare(T x, U y) {
|
||||
return sprout::math::equal_to(x, y) ? 0
|
||||
: sprout::math::less(x, y) ? -1
|
||||
: 1
|
||||
;
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace sprout
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <sprout/config.hpp>
|
||||
#include <sprout/algorithm/max.hpp>
|
||||
#include <sprout/math/abs.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/arithmetic_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -18,12 +18,9 @@ namespace sprout {
|
|||
return sprout::max(sprout::max(x, y), z);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
template<typename FloatType>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
equal_to(FloatType x, FloatType y) {
|
||||
equal_to_impl(FloatType x, FloatType y) {
|
||||
return x == y
|
||||
|| sprout::abs(x - y)
|
||||
<= std::numeric_limits<FloatType>::epsilon() * sprout::math::detail::max3(std::abs(x), std::abs(y), FloatType(1.0))
|
||||
|
@ -31,11 +28,25 @@ namespace sprout {
|
|||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
typename FloatType1, typename FloatType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
equal_to(IntType x, IntType y) {
|
||||
equal_to(FloatType1 x, FloatType2 y) {
|
||||
typedef typename sprout::arithmetic_promote<FloatType1, FloatType2>::type type;
|
||||
return sprout::math::detail::equal_to_impl<type>(x, y);
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
equal_to(IntType1 x, IntType2 y) {
|
||||
return x == y;
|
||||
}
|
||||
} // namespace detail
|
||||
|
@ -43,14 +54,12 @@ namespace sprout {
|
|||
// equal_to
|
||||
//
|
||||
template<
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
||||
typename T, typename U,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
equal_to(T1 x, T2 y) {
|
||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
||||
return sprout::math::detail::equal_to<promoted>(x, y);
|
||||
equal_to(T x, U y) {
|
||||
return sprout::math::detail::equal_to(x, y);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace sprout
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -26,9 +26,9 @@ namespace sprout {
|
|||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fdim(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::fdim(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
#ifndef SPROUT_MATH_FLOAT_PROMOTE_HPP
|
||||
#define SPROUT_MATH_FLOAT_PROMOTE_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename T, typename U>
|
||||
struct float_promote2
|
||||
: public std::conditional<
|
||||
(std::is_same<T, long double>::value || std::is_same<U, long double>::value),
|
||||
std::common_type<long double>,
|
||||
typename std::conditional<
|
||||
(std::is_same<T, float>::value && std::is_same<U, float>::value),
|
||||
float,
|
||||
double
|
||||
>
|
||||
>::type
|
||||
{
|
||||
static_assert(std::is_arithmetic<U>::value, "float_promote requires arithmetic type.");
|
||||
};
|
||||
|
||||
template<typename Current, typename Head, typename... Tail>
|
||||
struct float_promote_impl
|
||||
: public sprout::math::detail::float_promote_impl<
|
||||
typename sprout::math::detail::float_promote2<Current, Head>::type,
|
||||
Tail...
|
||||
>
|
||||
{};
|
||||
template<typename Current, typename Head>
|
||||
struct float_promote_impl<Current, Head>
|
||||
: public sprout::math::detail::float_promote2<Current, Head>
|
||||
{};
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// float_promote
|
||||
//
|
||||
template<typename... Types>
|
||||
struct float_promote
|
||||
: public sprout::math::detail::float_promote_impl<
|
||||
float, typename std::remove_cv<Types>::type...
|
||||
>
|
||||
{};
|
||||
} // namespace math
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_PROMOTE_HPP
|
|
@ -4,7 +4,7 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -29,11 +29,11 @@ namespace sprout {
|
|||
&& std::is_arithmetic<ArithmeticType3>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<
|
||||
ArithmeticType1, ArithmeticType2, ArithmeticType3
|
||||
>::type
|
||||
fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) {
|
||||
typedef typename sprout::math::float_promote<
|
||||
typedef typename sprout::float_promote<
|
||||
ArithmeticType1, ArithmeticType2, ArithmeticType3
|
||||
>::type type;
|
||||
return sprout::math::detail::fma(static_cast<type>(x), static_cast<type>(y), static_cast<type>(z));
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -26,9 +26,9 @@ namespace sprout {
|
|||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmax(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::fmax(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -26,9 +26,9 @@ namespace sprout {
|
|||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
fmin(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::fmin(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
|
|
@ -4,42 +4,73 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/not_equal_to.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/arithmetic_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
typename FloatType1, typename FloatType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater(FloatType x, FloatType y) {
|
||||
greater(FloatType1 x, FloatType2 y) {
|
||||
return sprout::math::not_equal_to(x, y) && x > y;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& (std::is_unsigned<IntType1>::value == std::is_unsigned<IntType2>::value)
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater(IntType x, IntType y) {
|
||||
greater(IntType1 x, IntType2 y) {
|
||||
return x > y;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_signed<IntType1>::value && std::is_unsigned<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return x < 0 ? false
|
||||
: static_cast<type>(x) > static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_unsigned<IntType1>::value && std::is_signed<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return y < 0 ? true
|
||||
: static_cast<type>(x) > static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// greater
|
||||
//
|
||||
template<
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
||||
typename T, typename U,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater(T1 x, T2 y) {
|
||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
||||
return sprout::math::detail::greater<promoted>(x, y);
|
||||
greater(T x, U y) {
|
||||
return sprout::math::detail::greater(x, y);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace sprout
|
||||
|
|
|
@ -4,42 +4,73 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/equal_to.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/arithmetic_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
typename FloatType1, typename FloatType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater_equal(FloatType x, FloatType y) {
|
||||
greater_equal_equal(FloatType1 x, FloatType2 y) {
|
||||
return sprout::math::equal_to(x, y) || x > y;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& (std::is_unsigned<IntType1>::value == std::is_unsigned<IntType2>::value)
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater_equal(IntType x, IntType y) {
|
||||
greater_equal(IntType1 x, IntType2 y) {
|
||||
return x >= y;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_signed<IntType1>::value && std::is_unsigned<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater_equal(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return x < 0 ? false
|
||||
: static_cast<type>(x) >= static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_unsigned<IntType1>::value && std::is_signed<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater_equal(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return y < 0 ? true
|
||||
: static_cast<type>(x) >= static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// greater_equal
|
||||
// greater_equal_equal
|
||||
//
|
||||
template<
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
||||
typename T, typename U,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
greater_equal(T1 x, T2 y) {
|
||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
||||
return sprout::math::detail::greater_equal<promoted>(x, y);
|
||||
greater_equal(T x, U y) {
|
||||
return sprout::math::detail::greater_equal(x, y);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace sprout
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/math/sqrt.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/sqrt.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
|
@ -27,9 +27,9 @@ namespace sprout {
|
|||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
hypot(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::hypot(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
|
|
@ -4,42 +4,73 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/not_equal_to.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/arithmetic_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
typename FloatType1, typename FloatType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less(FloatType x, FloatType y) {
|
||||
less(FloatType1 x, FloatType2 y) {
|
||||
return sprout::math::not_equal_to(x, y) && x < y;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& (std::is_unsigned<IntType1>::value == std::is_unsigned<IntType2>::value)
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less(IntType x, IntType y) {
|
||||
less(IntType1 x, IntType2 y) {
|
||||
return x < y;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_signed<IntType1>::value && std::is_unsigned<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return x < 0 ? true
|
||||
: static_cast<type>(x) < static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_unsigned<IntType1>::value && std::is_signed<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return y < 0 ? false
|
||||
: static_cast<type>(x) < static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// less
|
||||
//
|
||||
template<
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
||||
typename T, typename U,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less(T1 x, T2 y) {
|
||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
||||
return sprout::math::detail::less<promoted>(x, y);
|
||||
less(T x, U y) {
|
||||
return sprout::math::detail::less(x, y);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace sprout
|
||||
|
|
|
@ -4,42 +4,73 @@
|
|||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/equal_to.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/arithmetic_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
typename FloatType1, typename FloatType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less_equal(FloatType x, FloatType y) {
|
||||
return sprout::math::equal_to(x, y) || x < y;
|
||||
less_equal(FloatType1 x, FloatType2 y) {
|
||||
return sprout::math::not_equal_to(x, y) || x < y;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& (std::is_unsigned<IntType1>::value == std::is_unsigned<IntType2>::value)
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less_equal(IntType x, IntType y) {
|
||||
less_equal(IntType1 x, IntType2 y) {
|
||||
return x <= y;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_signed<IntType1>::value && std::is_unsigned<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less_equal(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return x < 0 ? true
|
||||
: static_cast<type>(x) <= static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename IntType1, typename IntType2,
|
||||
typename sprout::enabler_if<
|
||||
std::is_integral<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::value
|
||||
&& std::is_unsigned<IntType1>::value && std::is_signed<IntType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less_equal(IntType1 x, IntType2 y) {
|
||||
typedef typename std::make_unsigned<typename sprout::arithmetic_promote<IntType1, IntType2>::type>::type type;
|
||||
return y < 0 ? false
|
||||
: static_cast<type>(x) <= static_cast<type>(y)
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
//
|
||||
// less_equal
|
||||
//
|
||||
template<
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
||||
typename T, typename U,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
less_equal(T1 x, T2 y) {
|
||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
||||
return sprout::math::detail::less_equal<promoted>(x, y);
|
||||
less_equal(T x, U y) {
|
||||
return sprout::math::detail::less_equal(x, y);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace sprout
|
||||
|
|
|
@ -12,12 +12,11 @@ namespace sprout {
|
|||
// not_equal_to
|
||||
//
|
||||
template<
|
||||
typename T1,
|
||||
typename T2,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
||||
typename T, typename U,
|
||||
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR bool
|
||||
not_equal_to(T1 x, T2 y) {
|
||||
not_equal_to(T x, U y) {
|
||||
return !sprout::math::equal_to(x, y);
|
||||
}
|
||||
} // namespace math
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <sprout/math/exp.hpp>
|
||||
#include <sprout/math/log.hpp>
|
||||
#include <sprout/math/constants.hpp>
|
||||
#include <sprout/math/float_promote.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -31,9 +31,9 @@ namespace sprout {
|
|||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||
>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
inline SPROUT_CONSTEXPR typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type
|
||||
pow(ArithmeticType1 x, ArithmeticType2 y) {
|
||||
typedef typename sprout::math::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
typedef typename sprout::float_promote<ArithmeticType1, ArithmeticType2>::type type;
|
||||
return sprout::math::detail::pow(static_cast<type>(x), static_cast<type>(y));
|
||||
}
|
||||
} // namespace detail
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <sprout/type_traits/is_c_str.hpp>
|
||||
#include <sprout/type_traits/lvalue_reference.hpp>
|
||||
#include <sprout/type_traits/const_reference.hpp>
|
||||
#include <sprout/type_traits/arithmetic_promote.hpp>
|
||||
#include <sprout/type_traits/float_promote.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/type_traits/has_xxx.hpp>
|
||||
#include <sprout/type_traits/inherit_if_xxx.hpp>
|
||||
|
|
56
sprout/type_traits/arithmetic_promote.hpp
Normal file
56
sprout/type_traits/arithmetic_promote.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef SPROUT_TYPE_TRAITS_ARITHMETIC_PROMOTE_HPP
|
||||
#define SPROUT_TYPE_TRAITS_ARITHMETIC_PROMOTE_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <sprout/config.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct arithmetic_promote1
|
||||
: public std::common_type<T>
|
||||
{
|
||||
static_assert(
|
||||
std::is_arithmetic<T>::value,
|
||||
"arithmetic_promote requires arithmetic types."
|
||||
);
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct arithmetic_promote2
|
||||
: public std::decay<decltype(std::declval<T>() + std::declval<U>())>
|
||||
{
|
||||
static_assert(
|
||||
std::is_arithmetic<T>::value && std::is_arithmetic<U>::value,
|
||||
"arithmetic_promote requires arithmetic types."
|
||||
);
|
||||
};
|
||||
|
||||
template<typename... Types>
|
||||
struct arithmetic_promote_impl;
|
||||
template<typename T, typename U, typename... Tail>
|
||||
struct arithmetic_promote_impl<T, U, Tail...>
|
||||
: public sprout::detail::arithmetic_promote_impl<
|
||||
typename sprout::detail::arithmetic_promote2<T, U>::type,
|
||||
Tail...
|
||||
>
|
||||
{};
|
||||
template<typename T>
|
||||
struct arithmetic_promote_impl<T>
|
||||
: public sprout::detail::arithmetic_promote1<T>
|
||||
{};
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// arithmetic_promote
|
||||
//
|
||||
template<typename... Types>
|
||||
struct arithmetic_promote
|
||||
: public sprout::detail::arithmetic_promote_impl<
|
||||
typename std::remove_cv<Types>::type...
|
||||
>
|
||||
{};
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_TYPE_TRAITS_ARITHMETIC_PROMOTE_HPP
|
67
sprout/type_traits/float_promote.hpp
Normal file
67
sprout/type_traits/float_promote.hpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#ifndef SPROUT_TYPE_TRAITS_FLOAT_PROMOTE_HPP
|
||||
#define SPROUT_TYPE_TRAITS_FLOAT_PROMOTE_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
struct float_promote1
|
||||
: public std::conditional<
|
||||
std::is_floating_point<T>::value,
|
||||
std::common_type<T>,
|
||||
std::common_type<double>
|
||||
>::type
|
||||
{
|
||||
static_assert(
|
||||
std::is_arithmetic<T>::value,
|
||||
"float_promote requires arithmetic type."
|
||||
);
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct float_promote2
|
||||
: public std::conditional<
|
||||
(std::is_same<T, long double>::value || std::is_same<U, long double>::value),
|
||||
std::common_type<long double>,
|
||||
typename std::conditional<
|
||||
(std::is_same<T, float>::value && std::is_same<U, float>::value),
|
||||
float,
|
||||
double
|
||||
>
|
||||
>::type
|
||||
{
|
||||
static_assert(
|
||||
std::is_arithmetic<T>::value && std::is_arithmetic<U>::value,
|
||||
"float_promote requires arithmetic type."
|
||||
);
|
||||
};
|
||||
|
||||
template<typename... Types>
|
||||
struct float_promote_impl;
|
||||
template<typename T, typename U, typename... Tail>
|
||||
struct float_promote_impl<T, U, Tail...>
|
||||
: public sprout::detail::float_promote_impl<
|
||||
typename sprout::detail::float_promote2<T, U>::type,
|
||||
Tail...
|
||||
>
|
||||
{};
|
||||
template<typename T>
|
||||
struct float_promote_impl<T>
|
||||
: public sprout::detail::float_promote1<T>
|
||||
{};
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// float_promote
|
||||
//
|
||||
template<typename... Types>
|
||||
struct float_promote
|
||||
: public sprout::detail::float_promote_impl<
|
||||
typename std::remove_cv<Types>::type...
|
||||
>
|
||||
{};
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_TYPE_TRAITS_FLOAT_PROMOTE_HPP
|
|
@ -1,19 +1,22 @@
|
|||
#ifndef SPROUT_UTILITY_AS_CONST_HPP
|
||||
#define SPROUT_UTILITY_AS_CONST_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/utility/forward.hpp>
|
||||
|
||||
namespace sprout {
|
||||
//
|
||||
// as_const
|
||||
//
|
||||
template<typename T>
|
||||
inline T const& as_const(T& t) {
|
||||
return t;
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T const& as_const(T const& t) {
|
||||
return t;
|
||||
inline SPROUT_CONSTEXPR typename std::conditional<
|
||||
std::is_lvalue_reference<T>::value,
|
||||
typename std::remove_reference<T>::type const&,
|
||||
typename std::remove_reference<T>::type const&&
|
||||
>::type
|
||||
as_const(T&& t) {
|
||||
return sprout::forward<T>(t);
|
||||
}
|
||||
} // namespace sprout
|
||||
|
||||
|
|
|
@ -8,11 +8,13 @@ namespace sprout {
|
|||
// as_lvalue
|
||||
//
|
||||
template<typename T>
|
||||
inline T& as_lvalue(T& t) {
|
||||
inline SPROUT_CONSTEXPR T&
|
||||
as_lvalue(T& t) {
|
||||
return t;
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T const& as_lvalue(T const& t) {
|
||||
inline SPROUT_CONSTEXPR T const&
|
||||
as_lvalue(T const& t) {
|
||||
return t;
|
||||
}
|
||||
} // namespace sprout
|
||||
|
|
|
@ -9,11 +9,13 @@ namespace sprout {
|
|||
// forward
|
||||
//
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T&& forward(typename std::remove_reference<T>::type& t) SPROUT_NOEXCEPT {
|
||||
inline SPROUT_CONSTEXPR T&&
|
||||
forward(typename std::remove_reference<T>::type& t) SPROUT_NOEXCEPT {
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T&& forward(typename std::remove_reference<T>::type&& t) SPROUT_NOEXCEPT = delete;
|
||||
inline SPROUT_CONSTEXPR T&&
|
||||
forward(typename std::remove_reference<T>::type&& t) SPROUT_NOEXCEPT = delete;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_UTILITY_FORWARD_HPP
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace sprout {
|
|||
// move
|
||||
//
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR typename std::remove_reference<T>::type&& move(T&& x) SPROUT_NOEXCEPT {
|
||||
inline SPROUT_CONSTEXPR typename std::remove_reference<T>::type&&
|
||||
move(T&& x) SPROUT_NOEXCEPT {
|
||||
return static_cast<typename std::remove_reference<T>::type&&>(x);
|
||||
}
|
||||
|
||||
|
@ -21,7 +22,8 @@ namespace sprout {
|
|||
!std::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value,
|
||||
T const&,
|
||||
T&&
|
||||
>::type move_if_noexcept(T& x) SPROUT_NOEXCEPT {
|
||||
>::type
|
||||
move_if_noexcept(T& x) SPROUT_NOEXCEPT {
|
||||
return sprout::move(x);
|
||||
}
|
||||
} // namespace sprout
|
||||
|
|
Loading…
Reference in a new issue