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/detail/config.hpp>
|
||||||
#include <sprout/math/atan.hpp>
|
#include <sprout/math/atan.hpp>
|
||||||
#include <sprout/math/constants.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
|
@ -31,9 +31,9 @@ namespace sprout {
|
||||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||||
>::type = sprout::enabler
|
>::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) {
|
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));
|
return sprout::math::detail::atan2(static_cast<type>(y), static_cast<type>(x));
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
|
@ -4,33 +4,24 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/equal_to.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
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
|
// compare
|
||||||
//
|
//
|
||||||
template<
|
template<
|
||||||
typename T1,
|
typename T, typename U,
|
||||||
typename T2,
|
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR int
|
inline SPROUT_CONSTEXPR int
|
||||||
compare(T1 x, T2 y) {
|
compare(T x, U y) {
|
||||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
return sprout::math::equal_to(x, y) ? 0
|
||||||
return sprout::math::detail::compare_impl<promoted>(x, y);
|
: sprout::math::less(x, y) ? -1
|
||||||
|
: 1
|
||||||
|
;
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/algorithm/max.hpp>
|
#include <sprout/algorithm/max.hpp>
|
||||||
#include <sprout/math/abs.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
|
@ -18,12 +18,9 @@ namespace sprout {
|
||||||
return sprout::max(sprout::max(x, y), z);
|
return sprout::max(sprout::max(x, y), z);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<typename FloatType>
|
||||||
typename FloatType,
|
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
|
||||||
>
|
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
equal_to(FloatType x, FloatType y) {
|
equal_to_impl(FloatType x, FloatType y) {
|
||||||
return x == y
|
return x == y
|
||||||
|| sprout::abs(x - y)
|
|| sprout::abs(x - y)
|
||||||
<= std::numeric_limits<FloatType>::epsilon() * sprout::math::detail::max3(std::abs(x), std::abs(y), FloatType(1.0))
|
<= 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<
|
template<
|
||||||
typename IntType,
|
typename FloatType1, typename FloatType2,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<
|
||||||
|
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||||
|
>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
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;
|
return x == y;
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
@ -43,14 +54,12 @@ namespace sprout {
|
||||||
// equal_to
|
// equal_to
|
||||||
//
|
//
|
||||||
template<
|
template<
|
||||||
typename T1,
|
typename T, typename U,
|
||||||
typename T2,
|
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
equal_to(T1 x, T2 y) {
|
equal_to(T x, U y) {
|
||||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
return sprout::math::detail::equal_to(x, y);
|
||||||
return sprout::math::detail::equal_to<promoted>(x, y);
|
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/detail/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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
|
@ -26,9 +26,9 @@ namespace sprout {
|
||||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||||
>::type = sprout::enabler
|
>::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) {
|
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));
|
return sprout::math::detail::fdim(static_cast<type>(x), static_cast<type>(y));
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // 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 <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/detail/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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
|
@ -29,11 +29,11 @@ namespace sprout {
|
||||||
&& std::is_arithmetic<ArithmeticType3>::value
|
&& std::is_arithmetic<ArithmeticType3>::value
|
||||||
>::type = sprout::enabler
|
>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR typename sprout::math::float_promote<
|
inline SPROUT_CONSTEXPR typename sprout::float_promote<
|
||||||
ArithmeticType1, ArithmeticType2, ArithmeticType3
|
ArithmeticType1, ArithmeticType2, ArithmeticType3
|
||||||
>::type
|
>::type
|
||||||
fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) {
|
fma(ArithmeticType1 x, ArithmeticType2 y, ArithmeticType3 z) {
|
||||||
typedef typename sprout::math::float_promote<
|
typedef typename sprout::float_promote<
|
||||||
ArithmeticType1, ArithmeticType2, ArithmeticType3
|
ArithmeticType1, ArithmeticType2, ArithmeticType3
|
||||||
>::type type;
|
>::type type;
|
||||||
return sprout::math::detail::fma(static_cast<type>(x), static_cast<type>(y), static_cast<type>(z));
|
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 <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/detail/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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
|
@ -26,9 +26,9 @@ namespace sprout {
|
||||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||||
>::type = sprout::enabler
|
>::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) {
|
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));
|
return sprout::math::detail::fmax(static_cast<type>(x), static_cast<type>(y));
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/detail/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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
|
@ -26,9 +26,9 @@ namespace sprout {
|
||||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||||
>::type = sprout::enabler
|
>::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) {
|
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));
|
return sprout::math::detail::fmin(static_cast<type>(x), static_cast<type>(y));
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
|
@ -4,42 +4,73 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/not_equal_to.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType1, typename FloatType2,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<
|
||||||
|
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||||
|
>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
greater(FloatType x, FloatType y) {
|
greater(FloatType1 x, FloatType2 y) {
|
||||||
return sprout::math::not_equal_to(x, y) && x > y;
|
return sprout::math::not_equal_to(x, y) && x > y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
typename IntType,
|
typename IntType1, typename IntType2,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
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
|
inline SPROUT_CONSTEXPR bool
|
||||||
greater(IntType x, IntType y) {
|
greater(IntType1 x, IntType2 y) {
|
||||||
return x > 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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
// greater
|
// greater
|
||||||
//
|
//
|
||||||
template<
|
template<
|
||||||
typename T1,
|
typename T, typename U,
|
||||||
typename T2,
|
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
greater(T1 x, T2 y) {
|
greater(T x, U y) {
|
||||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
return sprout::math::detail::greater(x, y);
|
||||||
return sprout::math::detail::greater<promoted>(x, y);
|
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
|
@ -4,42 +4,73 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/equal_to.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType1, typename FloatType2,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<
|
||||||
|
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||||
|
>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
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;
|
return sprout::math::equal_to(x, y) || x > y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
typename IntType,
|
typename IntType1, typename IntType2,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
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
|
inline SPROUT_CONSTEXPR bool
|
||||||
greater_equal(IntType x, IntType y) {
|
greater_equal(IntType1 x, IntType2 y) {
|
||||||
return x >= 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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
// greater_equal
|
// greater_equal_equal
|
||||||
//
|
//
|
||||||
template<
|
template<
|
||||||
typename T1,
|
typename T, typename U,
|
||||||
typename T2,
|
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
greater_equal(T1 x, T2 y) {
|
greater_equal(T x, U y) {
|
||||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
return sprout::math::detail::greater_equal(x, y);
|
||||||
return sprout::math::detail::greater_equal<promoted>(x, y);
|
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/detail/config.hpp>
|
#include <sprout/type_traits/float_promote.hpp>
|
||||||
#include <sprout/math/float_promote.hpp>
|
|
||||||
#include <sprout/math/sqrt.hpp>
|
|
||||||
#include <sprout/type_traits/enabler_if.hpp>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
#include <sprout/math/detail/config.hpp>
|
||||||
|
#include <sprout/math/sqrt.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
|
@ -27,9 +27,9 @@ namespace sprout {
|
||||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||||
>::type = sprout::enabler
|
>::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) {
|
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));
|
return sprout::math::detail::hypot(static_cast<type>(x), static_cast<type>(y));
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
|
@ -4,42 +4,73 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/not_equal_to.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType1, typename FloatType2,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<
|
||||||
|
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||||
|
>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
less(FloatType x, FloatType y) {
|
less(FloatType1 x, FloatType2 y) {
|
||||||
return sprout::math::not_equal_to(x, y) && x < y;
|
return sprout::math::not_equal_to(x, y) && x < y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
typename IntType,
|
typename IntType1, typename IntType2,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
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
|
inline SPROUT_CONSTEXPR bool
|
||||||
less(IntType x, IntType y) {
|
less(IntType1 x, IntType2 y) {
|
||||||
return x < 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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
// less
|
// less
|
||||||
//
|
//
|
||||||
template<
|
template<
|
||||||
typename T1,
|
typename T, typename U,
|
||||||
typename T2,
|
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
less(T1 x, T2 y) {
|
less(T x, U y) {
|
||||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
return sprout::math::detail::less(x, y);
|
||||||
return sprout::math::detail::less<promoted>(x, y);
|
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
|
@ -4,42 +4,73 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
#include <sprout/math/equal_to.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
namespace math {
|
namespace math {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<
|
template<
|
||||||
typename FloatType,
|
typename FloatType1, typename FloatType2,
|
||||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
typename sprout::enabler_if<
|
||||||
|
std::is_floating_point<typename sprout::arithmetic_promote<FloatType1, FloatType2>::type>::value
|
||||||
|
>::type = sprout::enabler
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
less_equal(FloatType x, FloatType y) {
|
less_equal(FloatType1 x, FloatType2 y) {
|
||||||
return sprout::math::equal_to(x, y) || x < y;
|
return sprout::math::not_equal_to(x, y) || x < y;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
typename IntType,
|
typename IntType1, typename IntType2,
|
||||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
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
|
inline SPROUT_CONSTEXPR bool
|
||||||
less_equal(IntType x, IntType y) {
|
less_equal(IntType1 x, IntType2 y) {
|
||||||
return x <= 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
|
} // namespace detail
|
||||||
//
|
//
|
||||||
// less_equal
|
// less_equal
|
||||||
//
|
//
|
||||||
template<
|
template<
|
||||||
typename T1,
|
typename T, typename U,
|
||||||
typename T2,
|
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
inline SPROUT_CONSTEXPR bool
|
||||||
less_equal(T1 x, T2 y) {
|
less_equal(T x, U y) {
|
||||||
typedef typename sprout::math::float_promote<T1, T2>::type promoted;
|
return sprout::math::detail::less_equal(x, y);
|
||||||
return sprout::math::detail::less_equal<promoted>(x, y);
|
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
|
@ -12,12 +12,11 @@ namespace sprout {
|
||||||
// not_equal_to
|
// not_equal_to
|
||||||
//
|
//
|
||||||
template<
|
template<
|
||||||
typename T1,
|
typename T, typename U,
|
||||||
typename T2,
|
typename sprout::enabler_if<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>::type = sprout::enabler
|
||||||
typename sprout::enabler_if<std::is_arithmetic<T1>::value && std::is_arithmetic<T2>::value>::type = sprout::enabler
|
|
||||||
>
|
>
|
||||||
inline SPROUT_CONSTEXPR bool
|
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);
|
return !sprout::math::equal_to(x, y);
|
||||||
}
|
}
|
||||||
} // namespace math
|
} // namespace math
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <sprout/math/exp.hpp>
|
#include <sprout/math/exp.hpp>
|
||||||
#include <sprout/math/log.hpp>
|
#include <sprout/math/log.hpp>
|
||||||
#include <sprout/math/constants.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>
|
#include <sprout/type_traits/enabler_if.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
|
@ -31,9 +31,9 @@ namespace sprout {
|
||||||
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
std::is_arithmetic<ArithmeticType1>::value && std::is_arithmetic<ArithmeticType2>::value
|
||||||
>::type = sprout::enabler
|
>::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) {
|
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));
|
return sprout::math::detail::pow(static_cast<type>(x), static_cast<type>(y));
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <sprout/type_traits/is_c_str.hpp>
|
#include <sprout/type_traits/is_c_str.hpp>
|
||||||
#include <sprout/type_traits/lvalue_reference.hpp>
|
#include <sprout/type_traits/lvalue_reference.hpp>
|
||||||
#include <sprout/type_traits/const_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/enabler_if.hpp>
|
||||||
#include <sprout/type_traits/has_xxx.hpp>
|
#include <sprout/type_traits/has_xxx.hpp>
|
||||||
#include <sprout/type_traits/inherit_if_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
|
#ifndef SPROUT_UTILITY_AS_CONST_HPP
|
||||||
#define SPROUT_UTILITY_AS_CONST_HPP
|
#define SPROUT_UTILITY_AS_CONST_HPP
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
#include <sprout/config.hpp>
|
#include <sprout/config.hpp>
|
||||||
|
#include <sprout/utility/forward.hpp>
|
||||||
|
|
||||||
namespace sprout {
|
namespace sprout {
|
||||||
//
|
//
|
||||||
// as_const
|
// as_const
|
||||||
//
|
//
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T const& as_const(T& t) {
|
inline SPROUT_CONSTEXPR typename std::conditional<
|
||||||
return t;
|
std::is_lvalue_reference<T>::value,
|
||||||
}
|
typename std::remove_reference<T>::type const&,
|
||||||
template<typename T>
|
typename std::remove_reference<T>::type const&&
|
||||||
inline SPROUT_CONSTEXPR T const& as_const(T const& t) {
|
>::type
|
||||||
return t;
|
as_const(T&& t) {
|
||||||
|
return sprout::forward<T>(t);
|
||||||
}
|
}
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,13 @@ namespace sprout {
|
||||||
// as_lvalue
|
// as_lvalue
|
||||||
//
|
//
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T& as_lvalue(T& t) {
|
inline SPROUT_CONSTEXPR T&
|
||||||
|
as_lvalue(T& t) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
template<typename 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;
|
return t;
|
||||||
}
|
}
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
|
@ -9,11 +9,13 @@ namespace sprout {
|
||||||
// forward
|
// forward
|
||||||
//
|
//
|
||||||
template<typename T>
|
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);
|
return static_cast<T&&>(t);
|
||||||
}
|
}
|
||||||
template<typename 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
|
} // namespace sprout
|
||||||
|
|
||||||
#endif // #ifndef SPROUT_UTILITY_FORWARD_HPP
|
#endif // #ifndef SPROUT_UTILITY_FORWARD_HPP
|
||||||
|
|
|
@ -9,7 +9,8 @@ namespace sprout {
|
||||||
// move
|
// move
|
||||||
//
|
//
|
||||||
template<typename T>
|
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);
|
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,
|
!std::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value,
|
||||||
T const&,
|
T const&,
|
||||||
T&&
|
T&&
|
||||||
>::type move_if_noexcept(T& x) SPROUT_NOEXCEPT {
|
>::type
|
||||||
|
move_if_noexcept(T& x) SPROUT_NOEXCEPT {
|
||||||
return sprout::move(x);
|
return sprout::move(x);
|
||||||
}
|
}
|
||||||
} // namespace sprout
|
} // namespace sprout
|
||||||
|
|
Loading…
Reference in a new issue