cmath: Skip Libc for integral types in isinf, etc.
For std::isinf, the standard requires effectively calling isinf as double from Libc for integral types. But integral types are never infinite; we don't need to call Libc to return false. Also short-circuit other functions where Libc won't have interesting answers: signbit, fpclassify, isfinite, isnan, and isnormal. I added correctness tests for integral types since we're no longer deferring to Libc. In review it was pointed out that in future revisions of the C++ standard we may add more types to std::is_arithmetic (e.g., std::is_fixed_point). I'll leave it to a future commit to hack this to allow using math functions on those. We'll need to change things like __libcpp_fpclassify anyway, so I'm not sure anything here would really be future-proof. https://reviews.llvm.org/D31561 rdar://problem/31361223 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@301060 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -307,6 +307,7 @@ long double truncl(long double x);
|
||||
extern "C++" {
|
||||
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
|
||||
// signbit
|
||||
|
||||
@@ -324,22 +325,50 @@ __libcpp_signbit(_A1 __lcpp_x) _NOEXCEPT
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
|
||||
typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
|
||||
signbit(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_signbit((typename std::__promote<_A1>::type)__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<
|
||||
std::is_integral<_A1>::value && std::is_signed<_A1>::value, bool>::type
|
||||
signbit(_A1 __lcpp_x) _NOEXCEPT
|
||||
{ return __lcpp_x < 0; }
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<
|
||||
std::is_integral<_A1>::value && !std::is_signed<_A1>::value, bool>::type
|
||||
signbit(_A1) _NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
#elif defined(_LIBCPP_MSVCRT)
|
||||
|
||||
template <typename _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
|
||||
typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
|
||||
signbit(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return ::signbit(static_cast<typename std::__promote<_A1>::type>(__lcpp_x));
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<
|
||||
std::is_integral<_A1>::value && std::is_signed<_A1>::value, bool>::type
|
||||
signbit(_A1 __lcpp_x) _NOEXCEPT
|
||||
{ return __lcpp_x < 0; }
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<
|
||||
std::is_integral<_A1>::value && !std::is_signed<_A1>::value, bool>::type
|
||||
signbit(_A1) _NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
#endif // signbit
|
||||
|
||||
// fpclassify
|
||||
@@ -358,22 +387,34 @@ __libcpp_fpclassify(_A1 __lcpp_x) _NOEXCEPT
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, int>::type
|
||||
typename std::enable_if<std::is_floating_point<_A1>::value, int>::type
|
||||
fpclassify(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_fpclassify((typename std::__promote<_A1>::type)__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_integral<_A1>::value, int>::type
|
||||
fpclassify(_A1 __lcpp_x) _NOEXCEPT
|
||||
{ return __lcpp_x == 0 ? FP_ZERO : FP_NORMAL; }
|
||||
|
||||
#elif defined(_LIBCPP_MSVCRT)
|
||||
|
||||
template <typename _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, int>::type
|
||||
typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
|
||||
fpclassify(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return ::fpclassify(static_cast<typename std::__promote<_A1>::type>(__lcpp_x));
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_integral<_A1>::value, int>::type
|
||||
fpclassify(_A1 __lcpp_x) _NOEXCEPT
|
||||
{ return __lcpp_x == 0 ? FP_ZERO : FP_NORMAL; }
|
||||
|
||||
#endif // fpclassify
|
||||
|
||||
// isfinite
|
||||
@@ -392,12 +433,22 @@ __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
|
||||
typename std::enable_if<
|
||||
std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity,
|
||||
bool>::type
|
||||
isfinite(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_isfinite((typename std::__promote<_A1>::type)__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<
|
||||
std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity,
|
||||
bool>::type
|
||||
isfinite(_A1) _NOEXCEPT
|
||||
{ return true; }
|
||||
|
||||
#endif // isfinite
|
||||
|
||||
// isinf
|
||||
@@ -416,12 +467,22 @@ __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
|
||||
typename std::enable_if<
|
||||
std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity,
|
||||
bool>::type
|
||||
isinf(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_isinf((typename std::__promote<_A1>::type)__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<
|
||||
std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity,
|
||||
bool>::type
|
||||
isinf(_A1) _NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
#endif // isinf
|
||||
|
||||
// isnan
|
||||
@@ -440,12 +501,18 @@ __libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
|
||||
typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
|
||||
isnan(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_isnan((typename std::__promote<_A1>::type)__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_integral<_A1>::value, bool>::type
|
||||
isnan(_A1) _NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
#endif // isnan
|
||||
|
||||
// isnormal
|
||||
@@ -464,12 +531,18 @@ __libcpp_isnormal(_A1 __lcpp_x) _NOEXCEPT
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
|
||||
typename std::enable_if<std::is_floating_point<_A1>::value, bool>::type
|
||||
isnormal(_A1 __lcpp_x) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_isnormal((typename std::__promote<_A1>::type)__lcpp_x);
|
||||
}
|
||||
|
||||
template <class _A1>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename std::enable_if<std::is_integral<_A1>::value, bool>::type
|
||||
isnormal(_A1 __lcpp_x) _NOEXCEPT
|
||||
{ return __lcpp_x != 0; }
|
||||
|
||||
#endif // isnormal
|
||||
|
||||
// isgreater
|
||||
|
||||
Reference in New Issue
Block a user