Addressed review comments. Keep in mind that only `pow` is implemented
completely, once we get that one right I'll update the others to follow.
http://reviews.llvm.org/D5942
Files:
include/cmath
include/type_traits
test/std/numerics/c.math/cmath.pass.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/cmath
===================================================================
--- include/cmath
+++ include/cmath
@@ -325,7 +325,7 @@
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
signbit(_A1 __lcpp_x) _NOEXCEPT
{
return __libcpp_signbit((typename std::__promote<_A1>::type)__lcpp_x);
@@ -349,7 +349,7 @@
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, int>::type
+typename std::enable_if<std::__promote<_A1>::value, int>::type
fpclassify(_A1 __lcpp_x) _NOEXCEPT
{
return __libcpp_fpclassify((typename std::__promote<_A1>::type)__lcpp_x);
@@ -373,7 +373,7 @@
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
isfinite(_A1 __lcpp_x) _NOEXCEPT
{
return __libcpp_isfinite((typename std::__promote<_A1>::type)__lcpp_x);
@@ -397,7 +397,7 @@
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
isinf(_A1 __lcpp_x) _NOEXCEPT
{
return __libcpp_isinf((typename std::__promote<_A1>::type)__lcpp_x);
@@ -421,7 +421,7 @@
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
isnan(_A1 __lcpp_x) _NOEXCEPT
{
return __libcpp_isnan((typename std::__promote<_A1>::type)__lcpp_x);
@@ -445,7 +445,7 @@
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
+typename std::enable_if<std::__promote<_A1>::value, bool>::type
isnormal(_A1 __lcpp_x) _NOEXCEPT
{
return __libcpp_isnormal((typename std::__promote<_A1>::type)__lcpp_x);
@@ -471,8 +471,7 @@
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_arithmetic<_A1>::value &&
- std::is_arithmetic<_A2>::value,
+ std::__promote<_A1, _A2>::value,
bool
>::type
isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
@@ -501,8 +500,7 @@
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_arithmetic<_A1>::value &&
- std::is_arithmetic<_A2>::value,
+ std::__promote<_A1, _A2>::value,
bool
>::type
isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
@@ -531,8 +529,7 @@
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_arithmetic<_A1>::value &&
- std::is_arithmetic<_A2>::value,
+ std::__promote<_A1, _A2>::value,
bool
>::type
isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
@@ -561,8 +558,7 @@
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_arithmetic<_A1>::value &&
- std::is_arithmetic<_A2>::value,
+ std::__promote<_A1, _A2>::value,
bool
>::type
islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
@@ -591,8 +587,7 @@
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_arithmetic<_A1>::value &&
- std::is_arithmetic<_A2>::value,
+ std::__promote<_A1, _A2>::value,
bool
>::type
islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
@@ -621,8 +616,7 @@
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if
<
- std::is_arithmetic<_A1>::value &&
- std::is_arithmetic<_A2>::value,
+ std::__promote<_A1, _A2>::value,
bool
>::type
isunordered(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
@@ -727,12 +721,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
atan2(_A1 __lcpp_y, _A2 __lcpp_x) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -849,12 +838,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
fmod(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -952,18 +936,25 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
-pow(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
+typename __promote<_A1, _A2>::type
+#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+pow(_A1 __lcpp_x, _A2 __lcpp_y)
+#else
+pow(_A1&& __lcpp_x, _A2&& __lcpp_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)__lcpp_x, (__result_type)__lcpp_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>(__promote<_A1>::__apply(_VSTD::forward<_A1>(__lcpp_x))),
+ static_cast<type>(__promote<_A2>::__apply(_VSTD::forward<_A2>(__lcpp_y))));
}
// sin
@@ -1114,12 +1105,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
copysign(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -1192,12 +1178,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
fdim(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -1216,13 +1197,7 @@
template <class _A1, class _A2, class _A3>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value &&
- is_arithmetic<_A3>::value,
- __promote<_A1, _A2, _A3>
->::type
+typename __promote<_A1, _A2, _A3>::type
fma(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT
{
typedef typename __promote<_A1, _A2, _A3>::type __result_type;
@@ -1242,12 +1217,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
fmax(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -1266,12 +1236,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
fmin(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -1290,12 +1255,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
hypot(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -1459,12 +1419,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
nextafter(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -1496,12 +1451,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
remainder(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
@@ -1520,12 +1470,7 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename __lazy_enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- __promote<_A1, _A2>
->::type
+typename __promote<_A1, _A2>::type
remquo(_A1 __lcpp_x, _A2 __lcpp_y, int* __lcpp_z) _NOEXCEPT
{
typedef typename __promote<_A1, _A2>::type __result_type;
Index: include/type_traits
===================================================================
--- include/type_traits
+++ include/type_traits
@@ -1187,34 +1187,40 @@
#endif // _LIBCPP_HAS_NO_VARIADICS
-template <class _Tp>
+float __numeric_test(float);
+double __numeric_test(char);
+double __numeric_test(int);
+double __numeric_test(unsigned);
+double __numeric_test(long);
+double __numeric_test(unsigned long);
+double __numeric_test(long long);
+double __numeric_test(unsigned long long);
+double __numeric_test(double);
+long double __numeric_test(long double);
+
+template <class _Tp, class = void>
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);
+ static const bool value = false;
+};
- typedef decltype(__test(declval<_Tp>())) type;
- static const bool value = !is_same<type, void>::value;
+template <class _Tp>
+struct __numeric_type<_Tp,
+ typename __void_t<decltype(__numeric_test(declval<_Tp>()))>::type>
+{
+ typedef decltype(__numeric_test(declval<_Tp>())) type;
+ static const bool value = true;
};
template <>
-struct __numeric_type<void>
+struct __numeric_type<__nat>
{
- static const bool value = true;
+ static const bool value = true;
};
// __promote
-template <class _A1, class _A2 = void, class _A3 = void,
+template <class _A1, class _A2 = __nat, class _A3 = __nat,
bool = __numeric_type<_A1>::value &&
__numeric_type<_A2>::value &&
__numeric_type<_A3>::value>
@@ -1237,7 +1243,7 @@
};
template <class _A1, class _A2>
-class __promote_imp<_A1, _A2, void, true>
+class __promote_imp<_A1, _A2, __nat, true>
{
private:
typedef typename __promote_imp<_A1>::type __type1;
@@ -1248,14 +1254,26 @@
};
template <class _A1>
-class __promote_imp<_A1, void, void, true>
+class __promote_imp<_A1, __nat, __nat, true>
{
public:
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>()));
+
+ static type __apply(float __lcpp_x){ return __lcpp_x; }
+ static type __apply(char __lcpp_x){ return __lcpp_x; }
+ static type __apply(int __lcpp_x){ return __lcpp_x; }
+ static type __apply(unsigned __lcpp_x){ return __lcpp_x; }
+ static type __apply(long __lcpp_x){ return __lcpp_x; }
+ static type __apply(unsigned long __lcpp_x){ return __lcpp_x; }
+ static type __apply(long long __lcpp_x){ return __lcpp_x; }
+ static type __apply(unsigned long long __lcpp_x){ return __lcpp_x; }
+ static type __apply(double __lcpp_x){ return __lcpp_x; }
+ static type __apply(long double __lcpp_x){ return __lcpp_x; }
};
-template <class _A1, class _A2 = void, class _A3 = void>
+template <class _A1, class _A2 = __nat, class _A3 = __nat>
class __promote : public __promote_imp<_A1, _A2, _A3> {};
#ifdef _LIBCPP_STORE_AS_OPTIMIZATION
Index: test/std/numerics/c.math/cmath.pass.cpp
===================================================================
--- test/std/numerics/c.math/cmath.pass.cpp
+++ test/std/numerics/c.math/cmath.pass.cpp
@@ -435,15 +435,15 @@
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), "");
+ 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), "");
static_assert((std::is_same<decltype(pow(Ambiguous(), Ambiguous())), Ambiguous>::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);
+ 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()
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits