diff mbox

[v3] Implement US 136

Message ID 4C5E821B.2060403@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Aug. 8, 2010, 10:08 a.m. UTC
Hi,

tested x86_64-linux, committed to mainline.

Paolo.

///////////////////
2010-08-08  Paolo Carlini  <paolo.carlini@oracle.com>

	* include/c_global/cmath: Implement US 136.
	* include/tr1_impl/cmath: Do not bring fpclassify, etc from namespace
	std, define namespace tr1.
	* testsuite/26_numerics/headers/cmath/
	c99_classification_macros_c++0x.cc: New.
diff mbox

Patch

Index: include/tr1_impl/cmath
===================================================================
--- include/tr1_impl/cmath	(revision 162994)
+++ include/tr1_impl/cmath	(working copy)
@@ -1,6 +1,6 @@ 
 // TR1 cmath -*- C++ -*-
 
-// Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -294,21 +294,115 @@ 
 #if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
 
   /// Function template definitions [8.16.3].
-  using std::signbit;
-  
-  using std::fpclassify;
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    fpclassify(_Tp __f)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				  FP_SUBNORMAL, FP_ZERO, __type(__f));
+    }
 
-  using std::isfinite;
-  using std::isinf;
-  using std::isnan;
-  using std::isnormal;
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isfinite(_Tp __f)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isfinite(__type(__f));
+    }
 
-  using std::isgreater;
-  using std::isgreaterequal;
-  using std::isless;
-  using std::islessequal;
-  using std::islessgreater;
-  using std::isunordered;
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isinf(_Tp __f)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isinf(__type(__f));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isnan(_Tp __f)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isnan(__type(__f));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isnormal(_Tp __f)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isnormal(__type(__f));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    signbit(_Tp __f)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_signbit(__type(__f));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isgreater(_Tp __f1, _Tp __f2)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isgreater(__type(__f1), __type(__f2));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isgreaterequal(_Tp __f1, _Tp __f2)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isgreaterequal(__type(__f1), __type(__f2));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isless(_Tp __f1, _Tp __f2)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isless(__type(__f1), __type(__f2));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    islessequal(_Tp __f1, _Tp __f2)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_islessequal(__type(__f1), __type(__f2));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    islessgreater(_Tp __f1, _Tp __f2)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_islessgreater(__type(__f1), __type(__f2));
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
+					   int>::__type
+    isunordered(_Tp __f1, _Tp __f2)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __builtin_isunordered(__type(__f1), __type(__f2));
+    }
+
 #endif
 #endif
 
Index: include/c_global/cmath
===================================================================
--- include/c_global/cmath	(revision 162994)
+++ include/c_global/cmath	(working copy)
@@ -497,7 +497,253 @@ 
 
 _GLIBCXX_BEGIN_NAMESPACE(std)
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+  inline int
+  fpclassify(float __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  inline int
+  fpclassify(double __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
+  inline int
+  fpclassify(long double __x)
+  { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL,
+				FP_SUBNORMAL, FP_ZERO, __x); }
+
   template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
+					   int>::__type
+    fpclassify(_Tp __x)
+    { return __x != 0 ? FP_NORMAL : FP_ZERO; }
+
+  inline bool
+  isfinite(float __x)
+  { return __builtin_isfinite(__x); }
+
+  inline bool
+  isfinite(double __x)
+  { return __builtin_isfinite(__x); }
+
+  inline bool
+  isfinite(long double __x)
+  { return __builtin_isfinite(__x); }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
+					   bool>::__type
+    isfinite(_Tp __x)
+    { return true; }
+
+  inline bool
+  isinf(float __x)
+  { return __builtin_isinf(__x); }
+
+  inline bool
+  isinf(double __x)
+  { return __builtin_isinf(__x); }
+
+  inline bool
+  isinf(long double __x)
+  { return __builtin_isinf(__x); }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
+					   bool>::__type
+    isinf(_Tp __x)
+    { return false; }
+
+  inline bool
+  isnan(float __x)
+  { return __builtin_isnan(__x); }
+
+  inline bool
+  isnan(double __x)
+  { return __builtin_isnan(__x); }
+
+  inline bool
+  isnan(long double __x)
+  { return __builtin_isnan(__x); }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
+					   bool>::__type
+    isnan(_Tp __x)
+    { return false; }
+
+  inline bool
+  isnormal(float __x)
+  { return __builtin_isnormal(__x); }
+
+  inline bool
+  isnormal(double __x)
+  { return __builtin_isnormal(__x); }
+
+  inline bool
+  isnormal(long double __x)
+  { return __builtin_isnormal(__x); }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
+					   bool>::__type
+    isnormal(_Tp __x)
+    { return __x != 0 ? true : false; }
+
+  inline bool
+  signbit(float __x)
+  { return __builtin_signbit(__x); }
+
+  inline bool
+  signbit(double __x)
+  { return __builtin_signbit(__x); }
+
+  inline bool
+  signbit(long double __x)
+  { return __builtin_signbit(__x); }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
+					   bool>::__type
+    signbit(_Tp __x)
+    { return __x < 0 ? true : false; }
+
+  inline bool
+  isgreater(float __x, float __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  inline bool
+  isgreater(double __x, double __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  inline bool
+  isgreater(long double __x, long double __y)
+  { return __builtin_isgreater(__x, __y); }
+
+  template<typename _Tp, typename _Up>
+    inline typename
+    __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value
+			    && __is_arithmetic<_Up>::__value), bool>::__type
+    isgreater(_Tp __x, _Up __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return __builtin_isgreater(__type(__x), __type(__y));
+    }
+
+  inline bool
+  isgreaterequal(float __x, float __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  inline bool
+  isgreaterequal(double __x, double __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  inline bool
+  isgreaterequal(long double __x, long double __y)
+  { return __builtin_isgreaterequal(__x, __y); }
+
+  template<typename _Tp, typename _Up>
+    inline typename
+    __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value
+			    && __is_arithmetic<_Up>::__value), bool>::__type
+    isgreaterequal(_Tp __x, _Up __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return __builtin_isgreaterequal(__type(__x), __type(__y));
+    }
+
+  inline bool
+  isless(float __x, float __y)
+  { return __builtin_isless(__x, __y); }
+
+  inline bool
+  isless(double __x, double __y)
+  { return __builtin_isless(__x, __y); }
+
+  inline bool
+  isless(long double __x, long double __y)
+  { return __builtin_isless(__x, __y); }
+
+  template<typename _Tp, typename _Up>
+    inline typename
+    __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value
+			    && __is_arithmetic<_Up>::__value), bool>::__type
+    isless(_Tp __x, _Up __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return __builtin_isless(__type(__x), __type(__y));
+    }
+
+  inline bool
+  islessequal(float __x, float __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  inline bool
+  islessequal(double __x, double __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  inline bool
+  islessequal(long double __x, long double __y)
+  { return __builtin_islessequal(__x, __y); }
+
+  template<typename _Tp, typename _Up>
+    inline typename
+    __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value
+			    && __is_arithmetic<_Up>::__value), bool>::__type
+    islessequal(_Tp __x, _Up __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return __builtin_islessequal(__type(__x), __type(__y));
+    }
+
+  inline bool
+  islessgreater(float __x, float __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  inline bool
+  islessgreater(double __x, double __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  inline bool
+  islessgreater(long double __x, long double __y)
+  { return __builtin_islessgreater(__x, __y); }
+
+  template<typename _Tp, typename _Up>
+    inline typename
+    __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value
+			    && __is_arithmetic<_Up>::__value), bool>::__type
+    islessgreater(_Tp __x, _Up __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return __builtin_islessgreater(__type(__x), __type(__y));
+    }
+
+  inline bool
+  isunordered(float __x, float __y)
+  { return __builtin_isunordered(__x, __y); }
+
+  inline bool
+  isunordered(double __x, double __y)
+  { return __builtin_isunordered(__x, __y); }
+
+  inline bool
+  isunordered(long double __x, long double __y)
+  { return __builtin_isunordered(__x, __y); }
+
+  template<typename _Tp, typename _Up>
+    inline typename
+    __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value
+			    && __is_arithmetic<_Up>::__value), bool>::__type
+    isunordered(_Tp __x, _Up __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return __builtin_isunordered(__type(__x), __type(__y));
+    }
+
+#else
+
+  template<typename _Tp>
     inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
 					   int>::__type
     fpclassify(_Tp __f)
@@ -606,6 +852,8 @@ 
       return __builtin_isunordered(__type(__f1), __type(__f2));
     }
 
+#endif
+
 _GLIBCXX_END_NAMESPACE
 
 #endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */
Index: testsuite/26_numerics/headers/cmath/c99_classification_macros_c++0x.cc
===================================================================
--- testsuite/26_numerics/headers/cmath/c99_classification_macros_c++0x.cc	(revision 0)
+++ testsuite/26_numerics/headers/cmath/c99_classification_macros_c++0x.cc	(revision 0)
@@ -0,0 +1,92 @@ 
+// Copyright (C) 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile { xfail uclibc } }
+// { dg-excess-errors "" { target uclibc } }
+
+#include <cmath>
+
+void fpclassify() { }
+
+void isfinite() { }
+
+void isinf() { }
+
+void isnan() { }
+
+void isnormal() { }
+
+void signbit() { }
+
+void isgreater() { }
+
+void isgreaterequal() { }
+
+void isless() { }
+
+void islessequal() { }
+
+void islessgreater() { }
+
+void isunordered() { }
+
+#if _GLIBCXX_USE_C99_MATH
+template <typename _Tp, typename _Up = _Tp>
+  void test_c99_classify()
+  {
+    bool test __attribute__((unused)) = true;
+
+    typedef _Tp fp_type_one;
+    typedef _Up fp_type_two;
+    fp_type_one f1 = 1.0;
+    fp_type_two f2 = 3.0;
+    int resi;
+    bool res;
+
+    resi = std::fpclassify(f1);
+    res = std::isfinite(f2);
+    res = std::isinf(f1);
+    res = std::isnan(f2);
+    res = std::isnormal(f1);
+    res = std::signbit(f2);
+    res = std::isgreater(f1, f2);
+    res = std::isgreaterequal(f1, f2);
+    res = std::isless(f1, f2);
+    res = std::islessequal(f1,f2);
+    res = std::islessgreater(f1, f2);
+    res = std::isunordered(f1, f2);
+    resi = resi; // Suppress unused warning.
+    res = res;
+  }
+#endif
+
+int main()
+{
+#if _GLIBCXX_USE_C99_MATH
+  test_c99_classify<float>();
+  test_c99_classify<double>();
+  test_c99_classify<long double>();
+  test_c99_classify<float, double>();
+  test_c99_classify<float, long double>();
+  test_c99_classify<double, float>();
+  test_c99_classify<double, long double>();
+  test_c99_classify<long double, float>();
+  test_c99_classify<long double, double>();
+#endif
+  return 0;
+}