cmath: Implement US 136.

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.

From-SVN: r162995
This commit is contained in:
Paolo Carlini 2010-08-08 10:07:16 +00:00 committed by Paolo Carlini
parent 1159da448c
commit 77fd1c1d44
4 changed files with 456 additions and 14 deletions

View File

@ -1,3 +1,11 @@
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.
2010-08-06 David Malcolm <dmalcolm@redhat.com>
Jan Kratochvil <jan.kratochvil@redhat.com>

View File

@ -497,6 +497,252 @@ _GLIBCXX_END_NAMESPACE
_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
@ -606,6 +852,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
return __builtin_isunordered(__type(__f1), __type(__f2));
}
#endif
_GLIBCXX_END_NAMESPACE
#endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */

View File

@ -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 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
#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));
}
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));
}
using std::isgreater;
using std::isgreaterequal;
using std::isless;
using std::islessequal;
using std::islessgreater;
using std::isunordered;
#endif
#endif

View File

@ -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;
}