dexonsmith created this revision.

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.


https://reviews.llvm.org/D31561

Files:
  libcxx/include/math.h
  libcxx/test/std/numerics/c.math/cmath.pass.cpp

Index: libcxx/test/std/numerics/c.math/cmath.pass.cpp
===================================================================
--- libcxx/test/std/numerics/c.math/cmath.pass.cpp
+++ libcxx/test/std/numerics/c.math/cmath.pass.cpp
@@ -10,6 +10,7 @@
 // <cmath>
 
 #include <cmath>
+#include <limits>
 #include <type_traits>
 #include <cassert>
 
@@ -551,6 +552,13 @@
     static_assert((std::is_same<decltype(std::signbit((long double)0)), bool>::value), "");
     static_assert((std::is_same<decltype(signbit(Ambiguous())), Ambiguous>::value), "");
     assert(std::signbit(-1.0) == true);
+    assert(std::signbit(0u) == false);
+    assert(std::signbit(std::numeric_limits<unsigned>::max()) == false);
+    assert(std::signbit(0) == false);
+    assert(std::signbit(1) == false);
+    assert(std::signbit(-1) == true);
+    assert(std::signbit(std::numeric_limits<int>::max()) == false);
+    assert(std::signbit(std::numeric_limits<int>::min()) == true);
 }
 
 void test_fpclassify()
@@ -564,6 +572,11 @@
     static_assert((std::is_same<decltype(std::fpclassify((long double)0)), int>::value), "");
     static_assert((std::is_same<decltype(fpclassify(Ambiguous())), Ambiguous>::value), "");
     assert(std::fpclassify(-1.0) == FP_NORMAL);
+    assert(std::fpclassify(0) == FP_ZERO);
+    assert(std::fpclassify(1) == FP_NORMAL);
+    assert(std::fpclassify(-1) == FP_NORMAL);
+    assert(std::fpclassify(std::numeric_limits<int>::max()) == FP_NORMAL);
+    assert(std::fpclassify(std::numeric_limits<int>::min()) == FP_NORMAL);
 }
 
 void test_isfinite()
@@ -577,6 +590,11 @@
     static_assert((std::is_same<decltype(std::isfinite((long double)0)), bool>::value), "");
     static_assert((std::is_same<decltype(isfinite(Ambiguous())), Ambiguous>::value), "");
     assert(std::isfinite(-1.0) == true);
+    assert(std::isfinite(0) == true);
+    assert(std::isfinite(1) == true);
+    assert(std::isfinite(-1) == true);
+    assert(std::isfinite(std::numeric_limits<int>::max()) == true);
+    assert(std::isfinite(std::numeric_limits<int>::min()) == true);
 }
 
 void test_isnormal()
@@ -590,6 +608,11 @@
     static_assert((std::is_same<decltype(std::isnormal((long double)0)), bool>::value), "");
     static_assert((std::is_same<decltype(isnormal(Ambiguous())), Ambiguous>::value), "");
     assert(std::isnormal(-1.0) == true);
+    assert(std::isnormal(0) == false);
+    assert(std::isnormal(1) == true);
+    assert(std::isnormal(-1) == true);
+    assert(std::isnormal(std::numeric_limits<int>::max()) == true);
+    assert(std::isnormal(std::numeric_limits<int>::min()) == true);
 }
 
 void test_isgreater()
@@ -651,6 +674,11 @@
     static_assert((std::is_same<decltype(std::isinf(0)), bool>::value), "");
     static_assert((std::is_same<decltype(std::isinf((long double)0)), bool>::value), "");
     assert(std::isinf(-1.0) == false);
+    assert(std::isinf(0) == false);
+    assert(std::isinf(1) == false);
+    assert(std::isinf(-1) == false);
+    assert(std::isinf(std::numeric_limits<int>::max()) == false);
+    assert(std::isinf(std::numeric_limits<int>::min()) == false);
 }
 
 void test_isless()
@@ -731,6 +759,11 @@
     static_assert((std::is_same<decltype(std::isnan(0)), bool>::value), "");
     static_assert((std::is_same<decltype(std::isnan((long double)0)), bool>::value), "");
     assert(std::isnan(-1.0) == false);
+    assert(std::isnan(0) == false);
+    assert(std::isnan(1) == false);
+    assert(std::isnan(-1) == false);
+    assert(std::isnan(std::numeric_limits<int>::max()) == false);
+    assert(std::isnan(std::numeric_limits<int>::min()) == false);
 }
 
 void test_isunordered()
Index: libcxx/include/math.h
===================================================================
--- libcxx/include/math.h
+++ libcxx/include/math.h
@@ -327,22 +327,50 @@
 
 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) && ((_VC_CRT_MAJOR_VERSION-0) >= 14)
 
 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
@@ -361,22 +389,34 @@
 
 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) && ((_VC_CRT_MAJOR_VERSION-0) >= 14)
 
 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, int>::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
@@ -395,12 +435,18 @@
 
 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
 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_integral<_A1>::value, bool>::type
+isfinite(_A1) _NOEXCEPT
+{ return true; }
+
 #endif  // isfinite
 
 // isinf
@@ -419,12 +465,18 @@
 
 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
 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_integral<_A1>::value, bool>::type
+isinf(_A1) _NOEXCEPT
+{ return false; }
+
 #endif  // isinf
 
 // isnan
@@ -443,12 +495,18 @@
 
 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
@@ -467,12 +525,18 @@
 
 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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to