diff options
-rw-r--r-- | libcxx/include/__config | 5 | ||||
-rw-r--r-- | libcxx/include/cmath | 71 | ||||
-rw-r--r-- | libcxx/include/type_traits | 45 | ||||
-rw-r--r-- | libcxx/test/numerics/c.math/cmath.pass.cpp | 14 |
4 files changed, 111 insertions, 24 deletions
diff --git a/libcxx/include/__config b/libcxx/include/__config index f992bd5eaca..8aa57acfd72 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -326,9 +326,11 @@ typedef __char32_t char32_t; #if (__has_feature(cxx_noexcept)) # define _NOEXCEPT noexcept # define _NOEXCEPT_(x) noexcept(x) +# define _NOEXCEPT_OR_FALSE(x) noexcept(x) #else # define _NOEXCEPT throw() # define _NOEXCEPT_(x) +# define _NOEXCEPT_OR_FALSE(x) false #endif #if __has_feature(underlying_type) @@ -361,6 +363,7 @@ namespace std { #define _NOEXCEPT throw() #define _NOEXCEPT_(x) +#define _NOEXCEPT_OR_FALSE(x) false #ifndef __GXX_EXPERIMENTAL_CXX0X__ @@ -433,6 +436,7 @@ using namespace _LIBCPP_NAMESPACE __attribute__((__strong__)); #define _NOEXCEPT throw() #define _NOEXCEPT_(x) +#define _NOEXCEPT_OR_FALSE(x) false #define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { #define _LIBCPP_END_NAMESPACE_STD } @@ -451,6 +455,7 @@ namespace std { #define _NOEXCEPT throw() #define _NOEXCEPT_(x) +#define _NOEXCEPT_OR_FALSE(x) false #define _LIBCPP_HAS_NO_TEMPLATE_ALIASES #define _LIBCPP_HAS_NO_ADVANCED_SFINAE diff --git a/libcxx/include/cmath b/libcxx/include/cmath index 75087ae78fb..4f279783a90 100644 --- a/libcxx/include/cmath +++ b/libcxx/include/cmath @@ -419,12 +419,25 @@ __libcpp_isnan(_A1 __x) _NOEXCEPT #undef isnan -template <class _A1> inline _LIBCPP_INLINE_VISIBILITY -typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type -isnan(_A1 __x) _NOEXCEPT +bool +isnan(float __x) _NOEXCEPT +{ + return __libcpp_isnan(__x); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +isnan(double __x) _NOEXCEPT { - return __libcpp_isnan((typename std::__promote<_A1>::type)__x); + return __libcpp_isnan(__x); +} + +inline _LIBCPP_INLINE_VISIBILITY +bool +isnan(long double __x) _NOEXCEPT +{ + return __libcpp_isnan(__x); } #endif // isnan @@ -652,6 +665,26 @@ using ::isunordered; using ::float_t; using ::double_t; +// isnan + +template <class _A1> +inline _LIBCPP_INLINE_VISIBILITY +typename std::enable_if<__promote<_A1>::value, bool>::type +#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES +isnan(_A1 __x) +#else +isnan(_A1&& __x) + _NOEXCEPT_ + ( + _NOEXCEPT_(__promote<_A1>::__does_not_throw) + ) +#endif +{ + typedef typename __promote<_A1>::type type; + static_assert(!(is_same<typename remove_reference<_A1>::type, type>::value), ""); + return __libcpp_isnan(static_cast<type>(_VSTD::forward<_A1>(__x))); +} + // abs #if !defined(_AIX) @@ -952,21 +985,27 @@ inline _LIBCPP_INLINE_VISIBILITY long double pow(long double __x, long double __ template <class _A1, class _A2> inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_arithmetic<_A1>::value && - is_arithmetic<_A2>::value, - typename __promote<_A1, _A2>::type ->::type -pow(_A1 __x, _A2 __y) _NOEXCEPT +typename __promote<_A1, _A2>::type +#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES +pow(_A1 __x, _A2 __y) +#else +pow(_A1&& __x, _A2&& __y) + _NOEXCEPT_ + ( + _NOEXCEPT_(__promote<_A1>::__does_not_throw) && + _NOEXCEPT_(__promote<_A2>::__does_not_throw) + ) +#endif { - typedef typename __promote<_A1, _A2>::type __result_type; - static_assert((!(is_same<_A1, __result_type>::value && - is_same<_A2, __result_type>::value)), ""); - return pow((__result_type)__x, (__result_type)__y); + typedef typename __promote<_A1>::type _D1; + typedef typename __promote<_A2>::type _D2; + typedef typename __promote<_D1, _D2>::type type; + static_assert((!(is_same<typename remove_reference<_A1>::type, type>::value && + is_same<typename remove_reference<_A2>::type, type>::value)), ""); + return pow(static_cast<type>(static_cast<_D1>(_VSTD::forward<_A1>(__x))), + static_cast<type>(static_cast<_D2>(_VSTD::forward<_A2>(__y)))); } - // sin using ::sin; diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 0ad7b7f29d1..04e5fd14882 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1151,13 +1151,41 @@ template <size_t _Len, class ..._Types> using aligned_union_t = typename aligned #endif // _LIBCPP_HAS_NO_VARIADICS +template <class _Tp> +struct __numeric_type +{ + static void __test(...); + static float __test(float); + static double __test(char); + static double __test(int); + static double __test(unsigned); + static double __test(long); + static double __test(unsigned long); + static double __test(long long); + static double __test(unsigned long long); + static double __test(double); + static long double __test(long double); + + typedef decltype(__test(declval<_Tp>())) type; + static const bool value = !is_same<type, void>::value; +}; + +template <> +struct __numeric_type<void> +{ + static const bool value = true; +}; + // __promote template <class _A1, class _A2 = void, class _A3 = void, - bool = (is_arithmetic<_A1>::value || is_void<_A1>::value) && - (is_arithmetic<_A2>::value || is_void<_A2>::value) && - (is_arithmetic<_A3>::value || is_void<_A3>::value)> -class __promote {}; + bool = __numeric_type<_A1>::value && + __numeric_type<_A2>::value && + __numeric_type<_A3>::value> +class __promote +{ + static const bool value = false; +}; template <class _A1, class _A2, class _A3> class __promote<_A1, _A2, _A3, true> @@ -1168,6 +1196,7 @@ private: typedef typename __promote<_A3>::type __type3; public: typedef decltype(__type1() + __type2() + __type3()) type; + static const bool value = true; }; template <class _A1, class _A2> @@ -1178,16 +1207,16 @@ private: typedef typename __promote<_A2>::type __type2; public: typedef decltype(__type1() + __type2()) type; + static const bool value = true; }; template <class _A1> class __promote<_A1, void, void, true> { public: - typedef typename conditional<is_arithmetic<_A1>::value, - typename conditional<is_integral<_A1>::value, double, _A1>::type, - void - >::type type; + typedef typename __numeric_type<_A1>::type type; + static const bool value = true; + static const bool __does_not_throw = _NOEXCEPT_OR_FALSE(static_cast<type>(declval<_A1>())); }; #ifdef _LIBCPP_STORE_AS_OPTIMIZATION diff --git a/libcxx/test/numerics/c.math/cmath.pass.cpp b/libcxx/test/numerics/c.math/cmath.pass.cpp index 10b0993ad2e..13d872cdcc7 100644 --- a/libcxx/test/numerics/c.math/cmath.pass.cpp +++ b/libcxx/test/numerics/c.math/cmath.pass.cpp @@ -15,6 +15,12 @@ #include "hexfloat.h" +// convertible to int/float/double/etc +template <class T, int N=0> +struct Value { + operator T () { return T(N); } +}; + void test_abs() { static_assert((std::is_same<decltype(std::abs((float)0)), float>::value), ""); @@ -333,7 +339,14 @@ void test_pow() static_assert((std::is_same<decltype(std::powf(0,0)), float>::value), ""); static_assert((std::is_same<decltype(std::powl(0,0)), long double>::value), ""); static_assert((std::is_same<decltype(std::pow((int)0, (int)0)), double>::value), ""); + static_assert((std::is_same<decltype(std::pow(Value<int>(), (int)0)), double>::value), ""); + static_assert((std::is_same<decltype(std::pow(Value<long double>(), (float)0)), long double>::value), ""); + static_assert((std::is_same<decltype(std::pow((float) 0, Value<float>())), float>::value), ""); assert(std::pow(1,1) == 1); + assert(std::pow(Value<int,1>(), Value<float,1>()) == 1); + assert(std::pow(1.0f, Value<double,1>()) == 1); + assert(std::pow(1.0, Value<int,1>()) == 1); + assert(std::pow(Value<long double,1>(), 1LL) == 1); } void test_sin() @@ -1279,6 +1292,7 @@ void test_trunc() int main() { + test_abs(); test_acos(); test_asin(); test_atan(); |