Patch by Howard. First part of fix for PR18218; add type traits needed to do the right thing. Fix the problems in PR18218 for isnan and pow - they also need to be applied to the other functions in <cmath>. Also, a drive-by fix for the test - now actually calls test_abs()
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@198431 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3f44c407b6
commit
854a7a02b4
@ -326,9 +326,11 @@ typedef __char32_t char32_t;
|
|||||||
#if (__has_feature(cxx_noexcept))
|
#if (__has_feature(cxx_noexcept))
|
||||||
# define _NOEXCEPT noexcept
|
# define _NOEXCEPT noexcept
|
||||||
# define _NOEXCEPT_(x) noexcept(x)
|
# define _NOEXCEPT_(x) noexcept(x)
|
||||||
|
# define _NOEXCEPT_OR_FALSE(x) noexcept(x)
|
||||||
#else
|
#else
|
||||||
# define _NOEXCEPT throw()
|
# define _NOEXCEPT throw()
|
||||||
# define _NOEXCEPT_(x)
|
# define _NOEXCEPT_(x)
|
||||||
|
# define _NOEXCEPT_OR_FALSE(x) false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __has_feature(underlying_type)
|
#if __has_feature(underlying_type)
|
||||||
@ -361,6 +363,7 @@ namespace std {
|
|||||||
|
|
||||||
#define _NOEXCEPT throw()
|
#define _NOEXCEPT throw()
|
||||||
#define _NOEXCEPT_(x)
|
#define _NOEXCEPT_(x)
|
||||||
|
#define _NOEXCEPT_OR_FALSE(x) false
|
||||||
|
|
||||||
#ifndef __GXX_EXPERIMENTAL_CXX0X__
|
#ifndef __GXX_EXPERIMENTAL_CXX0X__
|
||||||
|
|
||||||
@ -433,6 +436,7 @@ using namespace _LIBCPP_NAMESPACE __attribute__((__strong__));
|
|||||||
|
|
||||||
#define _NOEXCEPT throw()
|
#define _NOEXCEPT throw()
|
||||||
#define _NOEXCEPT_(x)
|
#define _NOEXCEPT_(x)
|
||||||
|
#define _NOEXCEPT_OR_FALSE(x) false
|
||||||
|
|
||||||
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
|
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
|
||||||
#define _LIBCPP_END_NAMESPACE_STD }
|
#define _LIBCPP_END_NAMESPACE_STD }
|
||||||
@ -451,6 +455,7 @@ namespace std {
|
|||||||
|
|
||||||
#define _NOEXCEPT throw()
|
#define _NOEXCEPT throw()
|
||||||
#define _NOEXCEPT_(x)
|
#define _NOEXCEPT_(x)
|
||||||
|
#define _NOEXCEPT_OR_FALSE(x) false
|
||||||
|
|
||||||
#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
||||||
#define _LIBCPP_HAS_NO_ADVANCED_SFINAE
|
#define _LIBCPP_HAS_NO_ADVANCED_SFINAE
|
||||||
|
@ -419,12 +419,25 @@ __libcpp_isnan(_A1 __x) _NOEXCEPT
|
|||||||
|
|
||||||
#undef isnan
|
#undef isnan
|
||||||
|
|
||||||
template <class _A1>
|
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
|
bool
|
||||||
isnan(_A1 __x) _NOEXCEPT
|
isnan(float __x) _NOEXCEPT
|
||||||
{
|
{
|
||||||
return __libcpp_isnan((typename std::__promote<_A1>::type)__x);
|
return __libcpp_isnan(__x);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
bool
|
||||||
|
isnan(double __x) _NOEXCEPT
|
||||||
|
{
|
||||||
|
return __libcpp_isnan(__x);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
|
bool
|
||||||
|
isnan(long double __x) _NOEXCEPT
|
||||||
|
{
|
||||||
|
return __libcpp_isnan(__x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // isnan
|
#endif // isnan
|
||||||
@ -652,6 +665,26 @@ using ::isunordered;
|
|||||||
using ::float_t;
|
using ::float_t;
|
||||||
using ::double_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
|
// abs
|
||||||
|
|
||||||
#if !defined(_AIX)
|
#if !defined(_AIX)
|
||||||
@ -952,21 +985,27 @@ inline _LIBCPP_INLINE_VISIBILITY long double pow(long double __x, long double __
|
|||||||
|
|
||||||
template <class _A1, class _A2>
|
template <class _A1, class _A2>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if
|
typename __promote<_A1, _A2>::type
|
||||||
<
|
#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||||
is_arithmetic<_A1>::value &&
|
pow(_A1 __x, _A2 __y)
|
||||||
is_arithmetic<_A2>::value,
|
#else
|
||||||
typename __promote<_A1, _A2>::type
|
pow(_A1&& __x, _A2&& __y)
|
||||||
>::type
|
_NOEXCEPT_
|
||||||
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;
|
typedef typename __promote<_A1>::type _D1;
|
||||||
static_assert((!(is_same<_A1, __result_type>::value &&
|
typedef typename __promote<_A2>::type _D2;
|
||||||
is_same<_A2, __result_type>::value)), "");
|
typedef typename __promote<_D1, _D2>::type type;
|
||||||
return pow((__result_type)__x, (__result_type)__y);
|
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
|
// sin
|
||||||
|
|
||||||
using ::sin;
|
using ::sin;
|
||||||
|
@ -1151,13 +1151,41 @@ template <size_t _Len, class ..._Types> using aligned_union_t = typename aligned
|
|||||||
|
|
||||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
#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
|
// __promote
|
||||||
|
|
||||||
template <class _A1, class _A2 = void, class _A3 = void,
|
template <class _A1, class _A2 = void, class _A3 = void,
|
||||||
bool = (is_arithmetic<_A1>::value || is_void<_A1>::value) &&
|
bool = __numeric_type<_A1>::value &&
|
||||||
(is_arithmetic<_A2>::value || is_void<_A2>::value) &&
|
__numeric_type<_A2>::value &&
|
||||||
(is_arithmetic<_A3>::value || is_void<_A3>::value)>
|
__numeric_type<_A3>::value>
|
||||||
class __promote {};
|
class __promote
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
template <class _A1, class _A2, class _A3>
|
template <class _A1, class _A2, class _A3>
|
||||||
class __promote<_A1, _A2, _A3, true>
|
class __promote<_A1, _A2, _A3, true>
|
||||||
@ -1168,6 +1196,7 @@ private:
|
|||||||
typedef typename __promote<_A3>::type __type3;
|
typedef typename __promote<_A3>::type __type3;
|
||||||
public:
|
public:
|
||||||
typedef decltype(__type1() + __type2() + __type3()) type;
|
typedef decltype(__type1() + __type2() + __type3()) type;
|
||||||
|
static const bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _A1, class _A2>
|
template <class _A1, class _A2>
|
||||||
@ -1178,16 +1207,16 @@ private:
|
|||||||
typedef typename __promote<_A2>::type __type2;
|
typedef typename __promote<_A2>::type __type2;
|
||||||
public:
|
public:
|
||||||
typedef decltype(__type1() + __type2()) type;
|
typedef decltype(__type1() + __type2()) type;
|
||||||
|
static const bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _A1>
|
template <class _A1>
|
||||||
class __promote<_A1, void, void, true>
|
class __promote<_A1, void, void, true>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename conditional<is_arithmetic<_A1>::value,
|
typedef typename __numeric_type<_A1>::type type;
|
||||||
typename conditional<is_integral<_A1>::value, double, _A1>::type,
|
static const bool value = true;
|
||||||
void
|
static const bool __does_not_throw = _NOEXCEPT_OR_FALSE(static_cast<type>(declval<_A1>()));
|
||||||
>::type type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _LIBCPP_STORE_AS_OPTIMIZATION
|
#ifdef _LIBCPP_STORE_AS_OPTIMIZATION
|
||||||
|
@ -15,6 +15,12 @@
|
|||||||
|
|
||||||
#include "hexfloat.h"
|
#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()
|
void test_abs()
|
||||||
{
|
{
|
||||||
static_assert((std::is_same<decltype(std::abs((float)0)), float>::value), "");
|
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::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::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((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(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()
|
void test_sin()
|
||||||
@ -1279,6 +1292,7 @@ void test_trunc()
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
test_abs();
|
||||||
test_acos();
|
test_acos();
|
||||||
test_asin();
|
test_asin();
|
||||||
test_atan();
|
test_atan();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user