stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r614980 - /stdcxx/trunk/tests/support/18.numeric.special.float.cpp
Date Thu, 24 Jan 2008 20:27:33 GMT
Author: sebor
Date: Thu Jan 24 12:27:33 2008
New Revision: 614980

URL: http://svn.apache.org/viewvc?rev=614980&view=rev
Log:
2008-01-24  Martin Sebor  <sebor@roguewave.com>

	STDCXX-4
	* tests/support/18.numeric.special.float.cpp: Migrated the test to
	exercise floating point specializations of the numeric_limits class
	template from the Rogue Wave test suite.

Added:
    stdcxx/trunk/tests/support/18.numeric.special.float.cpp   (with props)

Added: stdcxx/trunk/tests/support/18.numeric.special.float.cpp
URL: http://svn.apache.org/viewvc/stdcxx/trunk/tests/support/18.numeric.special.float.cpp?rev=614980&view=auto
==============================================================================
--- stdcxx/trunk/tests/support/18.numeric.special.float.cpp (added)
+++ stdcxx/trunk/tests/support/18.numeric.special.float.cpp Thu Jan 24 12:27:33 2008
@@ -0,0 +1,1433 @@
+/***********************************************************************
+ *
+ * 18.numeric.special.float.cpp
+ *
+ *   test to exercise floating point specializations of the numeric_limits
+ *   class template
+ *
+ * $Id$
+ *
+ ***********************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ *
+ * Copyright 2000-2008 Rogue Wave Software, Inc.
+ * 
+ ***********************************************************************/
+
+#include <rw/_defs.h>
+
+#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
+   // disable implicit inclusion to work around 
+   // a limitation in IBM's VisualAge 5.0.2.0 (see PR#26959) 
+#  define _RWSTD_NO_IMPLICIT_INCLUSION 
+#endif 
+ 
+
+#include <limits>
+
+#include <climits>
+#include <cstdlib>   // for atof
+#include <cstdio>    // for sprintf
+
+#include <float.h>   // for constants, MSVC _fpclass, _isinf, _isnan
+#include <math.h>    // for fpclassify, isinf, isnan
+
+#ifndef _RWSTD_NO_IEEEFP_H
+#  include <ieeefp.h>   // for fpclass, isnan
+#endif   // _RWSTD_NO_IEEEFP_H
+
+#include <driver.h>
+
+// use FLT_ROUNDS if available, otherwise (e.g., when <ieeefp.h> must
+// be #included to bring the macro in), fall back on our own macro
+#ifndef FLT_ROUNDS
+#  define FLT_ROUNDS   _RWSTD_FLT_ROUNDS
+#endif   // FLT_ROUNDS
+
+/***********************************************************************/
+
+// determine whether the architecture is little-endian or big-endian
+static const int endian_test = 1;
+
+// extern works around a SunPro 5.4 bug (PR #28124)
+extern const bool big_endian = !*(const char*)&endian_test;
+
+/***********************************************************************/
+
+volatile float  flt_zero  = 0;
+volatile double dbl_zero  = 0;
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
+volatile long double ldbl_zero = 0;
+
+#endif   // _RWSTD_NO_LONG_DOUBLE
+
+/***********************************************************************/
+
+#if defined (_MSC_VER)
+
+const char* fpclass_name (int fpc)
+{
+    switch (fpc) {
+    case _FPCLASS_SNAN: return "_FPCLASS_SNAN";
+    case _FPCLASS_QNAN: return "_FPCLASS_QNAN";
+    case _FPCLASS_NINF: return "_FPCLASS_NINF";
+    case _FPCLASS_NN:   return "_FPCLASS_NN";
+    case _FPCLASS_ND:   return "_FPCLASS_ND";
+    case _FPCLASS_NZ:   return "_FPCLASS_NZ";
+    case _FPCLASS_PZ:   return "_FPCLASS_PZ";
+    case _FPCLASS_PD:   return "_FPCLASS_PD";
+    case _FPCLASS_PN:   return "_FPCLASS_PN";
+    case _FPCLASS_PINF: return "_FPCLASS_PINF";
+    }
+
+    static char buf [16];
+    std::sprintf (buf, "%#x", fpc);
+    return buf;
+}
+
+#elif defined (_RWSTD_OS_SUNOS)
+
+const char* fpclass_name (fpclass_t fpc)
+{
+    switch (fpc) {
+    case FP_SNAN:    return "FP_SNAN";
+    case FP_QNAN:    return "FP_QNAN";
+    case FP_NINF:    return "FP_NINF";
+    case FP_PINF:    return "FP_PINF";
+    case FP_NDENORM: return "FP_NDENORM";
+    case FP_PDENORM: return "FP_PDENORM";
+    case FP_NZERO:   return "FP_NZERO";
+    case FP_PZERO:   return "FP_PZERO";
+    case FP_NNORM:   return "FP_NNORM";
+    case FP_PNORM:   return "FP_PNORM";
+
+    }
+
+    static char buf [16];
+    std::sprintf (buf, "%#x", fpc);
+    return buf;
+}
+
+#elif defined (fpclassify)   // C99 classification
+
+const char* fpclass_name (int fpc)
+{
+    switch (fpc) {
+#  ifdef FP_INFINITE
+    case FP_INFINITE:  return "FP_INFINITE";
+#  endif
+#  ifdef FP_NAN
+    case FP_NAN:       return "FP_NAN";
+#  endif
+#  ifdef FP_NORMAL
+    case FP_NORMAL:    return "FP_NORMAL";
+#  endif
+#  ifdef FP_SUBNORMAL
+    case FP_SUBNORMAL: return "FP_SUBNORMAL";
+#  endif
+#  ifdef FP_ZERO
+    case FP_ZERO:      return "FP_ZERO";
+#  endif
+    default: break;
+    }
+
+    static char buf [16];
+    std::sprintf (buf, "%#x", fpc);
+    return buf;
+}
+
+#endif
+
+/***********************************************************************/
+
+template <class FloatT>
+void test_infinity (FloatT inf, FloatT max, const char *tname)
+{
+    if (!std::numeric_limits<FloatT>::traps) {
+
+        // infinity must be even greater than the maximum value
+        rw_assert (inf > max, 0, __LINE__,
+                   "numeric_limits<%s>::infinity() > "
+                   "numeric_limits<%s>::max()", tname, tname);
+
+        // multiplying infinity by anything other than 0.0 yields infinity
+        rw_assert (inf == inf * inf, 0, __LINE__,
+                   "numeric_limits<%s>::infinity()", tname);
+    }
+
+#ifdef _MSC_VER
+
+    const int fpc = _fpclass (inf);
+    rw_assert (_FPCLASS_PINF == fpc, 0, __LINE__,
+               "_fpclass (numeric_limits<%s>::infinity()) == "
+               "%d (_FPCLASS_PINF), got %d (%s)",
+               tname, _FPCLASS_PINF, fpc, fpclass_name (fpc));
+
+#elif defined (_RWSTD_OS_SUNOS)
+
+    rw_assert (!finite (inf), 0, __LINE__,
+               "finite (numeric_limits<%s>::infinity()) == 0, "
+               "got non-zero", tname);
+
+    const fpclass_t fpc = fpclass (inf);
+    rw_assert (FP_PINF == fpclass (inf), 0, __LINE__,
+               "fpclass (numeric_limits<%s>::infinity()) == %d (FP_PINF), "
+               "got %d (%s)", tname, FP_PINF, fpc, fpclass_name (fpc));
+
+#else
+
+#  ifdef isinf
+
+    rw_assert (isinf (inf), 0, __LINE__,
+               "isinf (numeric_limits<%s>::infinity()) != 0, got 0",
+               tname);
+
+#  endif   // isinf
+
+#  ifdef fpclassify
+
+    const int fpc = fpclassify (inf);
+    rw_assert (FP_INFINITE == fpc, 0, __LINE__,
+               "fpclassify(numeric_limits<%s>::infinity()) == "
+               "%d (FP_INFINITE), got %d (%s)", tname,
+               FP_INFINITE, fpc, fpclass_name (fpc));
+
+#  endif   // fpclassify
+
+#endif
+
+}
+
+/***********************************************************************/
+
+template <class FloatT>
+void test_quiet_NaN (FloatT qnan, FloatT qnan2, const char *tname)
+{
+    // NAN never compares equal to self or any other number
+    rw_assert (!(qnan == qnan2), 0, __LINE__,
+               "numeric_limits<%s>::quiet_NaN() != "
+               "numeric_limits<%1$s>::quiet_NaN()",
+               tname);
+
+    const FloatT inf = std::numeric_limits<FloatT>::infinity ();
+
+    rw_assert (!(qnan == inf), 0, __LINE__,
+               "numeric_limits<%s>::quiet_NaN() != "
+               "numeric_limits<%1$s>::infinity()",
+               tname);
+
+    rw_assert (!(qnan == -inf), 0, __LINE__,
+               "numeric_limits<%s>::quiet_NaN() != "
+               "-numeric_limits<%1$s>::infinity()",
+               tname);
+
+#ifdef _MSC_VER
+
+    rw_assert (0 != _isnan (qnan), 0, __LINE__,
+               "_isnan(numeric_limits<%s>::quiet_NaN()) != 0, got 0",
+               tname);
+
+    const int fpc = _fpclass (qnan);
+    rw_assert (_FPCLASS_QNAN == fpc, 0, __LINE__,
+               "_fpclass(numeric_limits<%s>::quiet_NaN()) == "
+               "%d (_FPCLASS_QNAN), got %d (%s)",
+               tname, _FPCLASS_QNAN, fpc, fpclass_name (fpc));
+
+#elif defined (_RWSTD_OS_SUNOS)
+
+    rw_assert (!finite (qnan), 0, __LINE__,
+               "finite(numeric_limits<%s>::quiet_NaN()) == 0, "
+               "got non-zero", tname);
+
+    const fpclass_t fpc = fpclass (qnan);
+    rw_assert (FP_QNAN == fpc, 0, __LINE__,
+               "fpclass(numeric_limits<%s>::infinity()) == %d (FP_QNAN), "
+               "got %d (%s)", tname, FP_QNAN, fpc, fpclass_name (fpc));
+
+#else
+
+#  ifdef isnan
+
+    rw_assert (0 != isnan (qnan), 0, __LINE__,
+               "isnan(numeric_limits<%s>::quiet_NaN()) != 0, got 0",
+               tname);
+
+#  endif   // isnan
+
+#  ifdef fpclassify
+
+    const int fpc = fpclassify (qnan);
+    rw_assert (FP_NAN == fpc, 0, __LINE__,
+               "fpclassify(numeric_limits<%s>::quiet_NaN()) == "
+               "%d (FP_NAN), got %d (%s)", tname,
+               FP_NAN, fpc, fpclass_name (fpc));
+
+#  endif   // fpclassify
+
+#endif
+
+}
+
+/***********************************************************************/
+
+template <class FloatT>
+void test_signaling_NaN (FloatT snan, FloatT snan2, const char *tname)
+{
+    // NAN never compares equal to self or any other number
+    rw_assert (!(snan == snan2), 0, __LINE__,
+               "numeric_limits<%s>::signaling_NaN() != "
+               "numeric_limits<%1$s>::signaling_NaN()",
+               tname);
+
+    const FloatT inf = std::numeric_limits<FloatT>::infinity ();
+
+    rw_assert (!(snan == inf), 0, __LINE__,
+               "numeric_limits<%s>::signaling_NaN() != "
+               "numeric_limits<%1$s>::infinity()",
+                tname);
+
+    rw_assert (!(snan == -inf), 0, __LINE__,
+               "numeric_limits<%s>::signaling_NaN() != "
+               "-numeric_limits<%1$s>::infinity()",
+               tname);
+
+#ifdef _MSC_VER
+
+    rw_assert (0 != _isnan (snan), 0, __LINE__,
+               "_isnan (numeric_limits<%s>::signaling_NaN()) != 0, got 0",
+               tname);
+
+    const int fpc = _fpclass (snan);
+    rw_assert (_FPCLASS_SNAN == fpc, 0, __LINE__,
+               "_fpclass(numeric_limits<%s>::signaling_NaN()) == "
+               "%d (_FPCLASS_SNAN), got %d (%s)",
+               tname, _FPCLASS_SNAN, fpc, fpclass_name (fpc));
+
+#elif defined (_RWSTD_OS_SUNOS)
+
+    rw_assert (!finite (snan), 0, __LINE__,
+               "finite(numeric_limits<%s>::signaling_NaN()) == 0, "
+               "got non-zero", tname);
+
+    const fpclass_t fpc = fpclass (snan);
+    rw_assert (FP_SNAN == fpc, 0, __LINE__,
+               "fpclass(numeric_limits<%s>::signaling_NaN()) == %d "
+               "(FP_SNAN), got %d (%s)", tname,
+               FP_SNAN, fpc, fpclass_name (fpc));
+#else
+
+#  ifdef isnan
+
+    rw_assert (0 != isnan (snan), 0, __LINE__,
+               "isnan(numeric_limits<%s>::signaling_NaN()) != 0, got 0",
+               tname);
+
+#  endif   // isnan
+
+#  ifdef fpclassify
+
+    const int fpc = fpclassify (snan);
+    rw_assert (FP_NAN == fpc, 0, __LINE__,
+               "fpclassify(numeric_limits<%s>::signaling_NaN()) == "
+               "%d (FP_NAN), got %d (%s)", tname,
+               FP_NAN, fpc, fpclass_name (fpc));
+
+#  endif   // fpclassify
+
+#endif
+
+}
+
+/***********************************************************************/
+
+template <class T>
+struct limits_values;
+
+#if    defined (__alpha) && !defined (__linux__) \
+    && !defined (__VMS) && defined (__DECCXX) && defined (__PURE_CNAME)
+
+extern "C" unsigned int read_rnd ();
+#define read_rnd   read_rnd
+
+#endif   // __alpha && !__linux__ && !__VMS && __DECCXX &&
__PURE_CNAME
+
+/***********************************************************************/
+
+_RWSTD_SPECIALIZED_CLASS
+struct limits_values<float>
+{
+    static bool is_specialized () { return true; }
+
+    static float (min) () { return FLT_MIN; }
+    static float (max) () { return FLT_MAX; }
+
+    static int digits () { return FLT_MANT_DIG; }
+    static int digits10 () { return FLT_DIG; }
+    static bool is_signed () { return  0.0f - 1.0f < 0.0f; }
+    static bool is_integer () { return false; }
+    static bool is_exact () { return false; }
+    static int radix () { return FLT_RADIX; }
+
+    static float epsilon () { return FLT_EPSILON; }
+
+    static float round_error () {
+
+#ifdef __osf__
+        int rounding = FLT_ROUNDS;
+#  ifdef read_rnd
+        if (rounding == std::round_indeterminate)
+            rounding = _RWSTD_STATIC_CAST (int, read_rnd ());
+#  endif   //  read_rnd
+
+        switch (rounding) {
+        case std::round_toward_zero:
+        case std::round_toward_infinity:
+        case std::round_toward_neg_infinity:
+            return 1.0f;
+        default:
+            return 0.5f;
+        }
+#else
+        return 0.5f;
+#endif
+
+    }
+
+    static int min_exponent () { return FLT_MIN_EXP; }
+    static int min_exponent10 () { return FLT_MIN_10_EXP; }
+    static int max_exponent () { return FLT_MAX_EXP; }
+    static int max_exponent10 () { return FLT_MAX_10_EXP; }
+
+    static bool has_infinity () {
+        return true;
+    }
+
+    static bool has_quiet_NaN () {
+
+#if defined (NAN)
+        // 7.12, p5 of C99:
+        // The macro NAN is defined if and only if the implementation
+        // supports quiet NaNs for the float type. It expands to a
+        // constant expression of type float representing a quiet NaN.
+        return true;
+#else
+        return true;
+#endif
+
+    }
+
+
+    static bool has_signaling_NaN () {
+
+#if defined (FLT_SNAN)
+        return true;
+#else
+#  ifndef _RWSTD_NO_SIGNALING_NAN
+        return true;
+#  else
+        return false;
+#  endif   // _RWSTD_NO_SIGNALING_NAN
+#endif
+
+    }
+
+
+    static std::float_denorm_style has_denorm () {
+
+#if defined (_AIX)
+        return std::denorm_present;
+#elif defined (__hpux)
+        return std::denorm_indeterminate;
+#elif defined (__osf__)
+        return std::denorm_present;
+#else
+        return std::denorm_indeterminate;
+#endif
+    }
+
+
+    static bool has_denorm_loss () { return false; }
+
+
+    static float infinity () {
+
+#if defined (FLT_INFINITY)
+        return FLT_INFINITY;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        float inf = float (std::atof ("inf"));
+        if (inf > FLT_MAX)
+            return inf;
+
+        inf = 1.0f / flt_zero;
+
+        return inf;
+
+#else
+        const union {
+            char bits [sizeof (float)];
+            float val;
+        } val = {
+            _RWSTD_FLT_INF_BITS
+        };
+            
+        return val.val;
+#endif
+
+    }
+
+
+    static float quiet_NaN () {
+
+#if defined (NAN)
+        return NAN;
+#elif defined (FLT_QNAN)
+        return FLT_QNAN;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        float nan = float (std::atof ("nan"));
+
+        if (nan != float (std::atof ("nan")))
+            return nan;
+
+        nan = float (dbl_zero / flt_zero);
+
+        return nan;
+
+#else
+        const union {
+            char bits [sizeof (float)];
+            float val;
+        } val = {
+            _RWSTD_FLT_QNAN_BITS
+        };
+            
+        return val.val;
+
+#endif
+
+    }
+
+
+    static float signaling_NaN () {
+
+#if defined (FLT_SNAN)
+        return FLT_SNAN;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        union {
+            float val;
+            char bits [sizeof (float)];
+        } snan;
+
+        snan.val = infinity ();
+
+#  ifdef __hpux
+
+        if (big_endian) {
+            snan.bits [sizeof snan.val - 2] = '\xc0';
+        }
+        else {
+            snan.bits [1] = '\xc0';
+        }
+
+#  else   // if !defined (__hpux)
+
+        // convert infinity into a signaling NAN
+        // (toggle any bit in signifcand)
+        if (big_endian) {
+            snan.bits [sizeof snan.val - 1] |= 1;
+        }
+        else {
+            snan.bits [0] |= 1;
+        }
+
+#  endif   // __hpux
+
+        return snan.val;
+
+#else
+
+        const union {
+            char bits [sizeof (float)];
+            float val;
+        } val = {
+            _RWSTD_FLT_SNAN_BITS
+        };
+            
+        return val.val;
+
+#endif
+
+    }
+
+
+    static float denorm_min () {
+
+#if defined (__FLT_DENORM_MIN__)
+        // gcc 3.x predefined macro
+        return __FLT_DENORM_MIN__;
+#elif defined (__osf__)
+        const unsigned short pos_denorm [] = { 0x0001, 0x0000 };
+        return *_RWSTD_REINTERPRET_CAST (const float*, pos_denorm);
+#else
+        // assume IEEE 754
+
+        static union {
+            float denorm_min;
+            char denorm_min_bits [sizeof (float)];
+        } u;
+
+        if (big_endian)
+            u.denorm_min_bits [sizeof (float) - 1] = '\001';
+        else
+            u.denorm_min_bits [0] = '\001';
+
+        return u.denorm_min;
+
+#endif
+
+    }
+
+
+    static bool is_iec559 () {
+
+#if defined (__osf__)
+
+        // Tru64 UNIX with Compaq C++: IEC 559 support is enabled
+        // by specifying the -ieee flag on the compiler command line
+
+#  ifdef _IEEE_FP
+        return true;
+#  else
+        return false;
+#  endif   //  _IEEE_FP
+#else
+        return true;
+#endif
+
+    }
+
+
+    static bool is_bounded () { return true; }
+    static bool is_modulo () { return false; }
+
+    static bool traps () { return true; }
+    static bool tinyness_before () { return false; }
+
+
+    static std::float_round_style round_style () {
+
+#if defined (_AIX)
+        return std::round_to_nearest;
+#else
+        return _RWSTD_STATIC_CAST (std::float_round_style, FLT_ROUNDS);
+#endif
+    }
+
+};
+
+/***********************************************************************/
+
+
+_RWSTD_SPECIALIZED_CLASS
+struct limits_values<double>
+{
+    static bool is_specialized () { return true; }
+
+    static double (min)() { return DBL_MIN; }
+    static double (max)() { return DBL_MAX; }
+
+    static int digits () { return DBL_MANT_DIG; }
+    static int digits10 () { return DBL_DIG; }
+    static bool is_signed () { return  0.0 - 1.0 < 0.0; }
+    static bool is_integer () { return false; }
+    static bool is_exact () { return false; }
+    static int radix () { return FLT_RADIX; }
+
+    static double epsilon () { return DBL_EPSILON; }
+
+
+    static double round_error () {
+
+#ifdef __osf__
+        int rounding = FLT_ROUNDS;
+#  ifdef read_rnd
+        if (rounding == std::round_indeterminate)
+            rounding = _RWSTD_STATIC_CAST (int, read_rnd ());
+#  endif   //  read_rnd
+        switch (rounding) {
+        case std::round_toward_zero:
+        case std::round_toward_infinity:
+        case std::round_toward_neg_infinity:
+            return 1.0;
+        default:
+            return 0.5;
+        }
+#else
+        return 0.5;
+#endif
+
+    }
+
+
+    static int min_exponent () { return DBL_MIN_EXP; }
+    static int min_exponent10 () { return DBL_MIN_10_EXP; }
+    static int max_exponent () { return DBL_MAX_EXP; }
+    static int max_exponent10 () { return DBL_MAX_10_EXP; }
+
+
+    static bool has_infinity () {
+        return true;
+    }
+
+
+    static bool has_quiet_NaN () {
+        return true;
+    }
+
+
+    static bool has_signaling_NaN () {
+
+#if defined DBL_SNAN
+        return true;
+#else
+#  ifndef _RWSTD_NO_SIGNALING_NAN
+        return true;
+#  else
+        return false;
+#  endif   // _RWSTD_NO_SIGNALING_NAN
+#endif
+
+    }
+
+
+    static std::float_denorm_style has_denorm () {
+#if defined (_AIX)
+        return std::denorm_present;
+#elif defined (__hpux)
+        return std::denorm_indeterminate;
+#elif defined (__osf__)
+        return std::denorm_present;
+#else
+        return std::denorm_indeterminate;
+#endif
+    }
+
+
+    static bool has_denorm_loss () { return false; }
+
+
+    static double infinity () {
+
+#if defined (DBL_INFINITY)
+        return DBL_INFINITY;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        double inf = std::atof ("inf");
+        if (inf > DBL_MAX)
+            return inf;
+
+        inf = 1.0 / dbl_zero;
+
+        return inf;
+
+#else
+        const union {
+            char bits [sizeof (double)];
+            double val;
+        } val = {
+            _RWSTD_DBL_INF_BITS
+        };
+            
+        return val.val;
+#endif
+
+    }
+
+
+    static double quiet_NaN () {
+
+#if defined (NAN)
+        return NAN;
+#elif defined (DBL_QNAN)
+        return DBL_QNAN;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        double nan = std::atof ("nan");
+
+        if (nan != std::atof ("nan"))
+            return nan;
+
+        nan = flt_zero / dbl_zero;
+
+        return nan;
+
+#else
+        const union {
+            char bits [sizeof (double)];
+            double val;
+        } val = {
+            _RWSTD_DBL_QNAN_BITS
+        };
+            
+        return val.val;
+
+#endif
+
+    }
+
+
+    static double signaling_NaN () {
+
+#if defined (DBL_SNAN)
+        return DBL_SNAN;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        union {
+            double val;
+            char bits [sizeof (double)];
+        } snan;
+
+        snan.val = infinity ();
+
+#  ifdef __hpux
+
+        if (big_endian) {
+            snan.bits [sizeof snan.val - 2] = '\xf8';
+        }
+        else {
+            snan.bits [1] = '\xf8';
+        }
+
+#  else   // if !defined (__hpux)
+
+        // convert infinity into a signaling NAN
+        // (toggle any bit in signifcand)
+        if (big_endian) {
+            snan.bits [sizeof snan.val - 1] |= 1;
+        }
+        else {
+            snan.bits [0] |= 1;
+        }
+
+#  endif   // __hpux
+
+        return snan.val;
+
+#else
+
+        const union {
+            char bits [sizeof (double)];
+            double val;
+        } val = {
+            _RWSTD_DBL_SNAN_BITS
+        };
+            
+        return val.val;
+
+#endif
+
+    }
+
+
+    static double denorm_min () {
+
+#if defined (__DBL_DENORM_MIN__)
+        // gcc 3.x predefined macro
+        return __DBL_DENORM_MIN__;
+#elif defined (__osf__)
+        const unsigned short pos_denorm [] = { 0x0001, 0x0000 };
+        return *_RWSTD_REINTERPRET_CAST (const double*, pos_denorm);
+#else
+        // assume IEEE 754
+
+        static union {
+            double denorm_min;
+            char denorm_min_bits [sizeof (double)];
+        } u;
+
+        if (big_endian)
+            u.denorm_min_bits [sizeof (double) - 1] = '\001';
+        else
+            u.denorm_min_bits [0] = '\001';
+
+        return u.denorm_min;
+
+#endif
+
+    }
+
+
+    static bool is_iec559 () {
+
+#if defined (__osf__)
+#  ifdef _IEEE_FP
+        return true;
+#  else
+        return false;
+#  endif   //  _IEEE_FP
+#else
+        return true;
+#endif
+
+    }
+
+
+    static bool is_bounded () { return true; }
+    static bool is_modulo () { return false; }
+
+    static bool traps () { return true; }
+    static bool tinyness_before () { return false; }
+
+
+    static std::float_round_style round_style () {
+
+#if defined (_AIX)
+        return std::round_to_nearest;
+#else
+        return _RWSTD_STATIC_CAST (std::float_round_style, FLT_ROUNDS);
+#endif
+
+    }
+
+};
+
+/***********************************************************************/
+
+
+_RWSTD_SPECIALIZED_CLASS
+struct limits_values<long double>
+{
+    static bool is_specialized () { return true; }
+
+    static long double (min)() { return LDBL_MIN; }
+    static long double (max)() { return LDBL_MAX; }
+
+    static int digits () { return LDBL_MANT_DIG; }
+    static int digits10 () { return LDBL_DIG; }
+    static bool is_signed () { return  0.0 - 1.0 < 0.0; }
+    static bool is_integer () { return false; }
+    static bool is_exact () { return false; }
+    static int radix () { return FLT_RADIX; }
+
+    static long double epsilon () { return LDBL_EPSILON; }
+
+    static long double round_error () {
+
+#ifdef __osf__
+        int rounding = FLT_ROUNDS;
+#  ifdef read_rnd
+        if (rounding == std::round_indeterminate)
+            rounding = _RWSTD_STATIC_CAST (int, read_rnd ());
+#  endif   //  read_rnd
+        switch (rounding) {
+        case std::round_toward_zero:
+        case std::round_toward_infinity:
+        case std::round_toward_neg_infinity:
+            return 1.0;
+        default:
+            return 0.5;
+        }
+#else
+        return 0.5;
+#endif
+
+    }
+
+    static int min_exponent () { return LDBL_MIN_EXP; }
+    static int min_exponent10 () { return LDBL_MIN_10_EXP; }
+    static int max_exponent () { return LDBL_MAX_EXP; }
+    static int max_exponent10 () { return LDBL_MAX_10_EXP; }
+
+    static bool has_infinity () {
+        return true;
+    }
+
+    static bool has_quiet_NaN () {
+        return true;
+    }
+
+
+    static bool has_signaling_NaN () {
+
+#if defined (LDBL_SNAN)
+        return true;
+#else
+#  ifndef _RWSTD_NO_SIGNALING_NAN
+        return true;
+#  else
+        return false;
+#  endif   // _RWSTD_NO_SIGNALING_NAN
+#endif
+
+    }
+
+
+    static std::float_denorm_style has_denorm () {
+#if defined (_AIX)
+        return std::denorm_present;
+#elif defined (__hpux)
+        return std::denorm_indeterminate;
+#elif defined (__osf__)
+        return std::denorm_present;
+#else
+        return std::denorm_indeterminate;
+#endif
+    }
+
+    static bool has_denorm_loss () { return false; }
+
+
+    static long double infinity () {
+
+#if defined (LDBL_INFINITY)
+        return LDBL_INFINITY;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        long double inf = std::atof ("inf");
+        if (inf > LDBL_MAX)
+            return inf;
+
+        inf = (long double)1.0 / ldbl_zero;
+
+        return inf;
+
+#else
+        const union {
+            char bits [sizeof (long double)];
+            long double val;
+        } val = {
+            _RWSTD_LDBL_INF_BITS
+        };
+            
+        return val.val;
+#endif
+
+    }
+
+
+    static long double quiet_NaN () {
+
+#if defined (NAN)
+        return NAN;
+#elif defined (LDBL_QNAN)
+        return LDBL_QNAN;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        long double nan = std::atof ("nan");
+
+        if (nan != (long double)std::atof ("nan"))
+            return nan;
+
+        nan = ldbl_zero / ldbl_zero;
+
+        return nan;
+
+#else
+        const union {
+            char bits [sizeof (long double)];
+            long double val;
+        } val = {
+            _RWSTD_LDBL_QNAN_BITS
+        };
+            
+        return val.val;
+
+#endif
+
+    }
+
+
+    static long double signaling_NaN () {
+
+#if defined (LDBL_SNAN)
+        return LDBL_SNAN;
+#elif defined (_RWSTD_NO_DBL_TRAPS)
+
+        union {
+            long double val;
+            char bits [sizeof (long double)];
+        } snan;
+
+        snan.val = infinity ();
+
+#  ifdef __hpux
+
+        if (big_endian) { on floating types
+            snan.bits [sizeof snan.val - 3] = '\x80';
+        }
+        else {
+            snan.bits [2] = '\x80';
+        }
+
+#  else   // if !defined (__hpux)
+
+        // convert infinity into a signaling NAN
+        // (toggle any bit in signifcand)
+        if (big_endian) {
+            snan.bits [sizeof snan.val - 1] |= 1;
+        }
+        else {
+            snan.bits [0] |= 1;
+        }
+
+#  endif   // __hpux
+
+        return snan.val;
+
+#else
+
+        const union {
+            char bits [sizeof (long double)];
+            long double val;
+        } val = {
+            _RWSTD_LDBL_SNAN_BITS
+        };
+            
+        return val.val;
+
+#endif
+
+    }
+
+
+    static long double denorm_min () {
+
+#if defined (__LDBL_DENORM_MIN__)
+        // gcc 3.x predefined macro
+        return __LDBL_DENORM_MIN__;
+#elif defined (__osf__)
+        const unsigned short pos_denorm [] = { 0x0001, 0x0000 };
+        return *_RWSTD_REINTERPRET_CAST (const long double*, pos_denorm);
+#else
+        // assume IEEE 754
+
+        static union {
+            long double denorm_min;
+            char denorm_min_bits [sizeof (long double)];
+        } u;
+
+        if (big_endian)
+            u.denorm_min_bits [sizeof (long double) - 1] = '\001';
+        else
+            u.denorm_min_bits [0] = '\001';
+
+        return u.denorm_min;
+#endif
+
+    }
+
+
+    static bool is_iec559 () {
+#if defined (__osf__)
+#  ifdef _IEEE_FP
+        return true;
+#  else
+        return false;
+#  endif   //  _IEEE_FP
+#else
+        return true;
+#endif
+    }
+
+    static bool is_bounded () { return true; }
+    static bool is_modulo () { return false; }
+
+    static bool traps () { return true; }
+    static bool tinyness_before () { return false; }
+
+    static std::float_round_style round_style () {
+#if defined (_AIX)
+        return std::round_to_nearest;
+#else
+        return _RWSTD_STATIC_CAST (std::float_round_style, FLT_ROUNDS);
+#endif
+    }
+};
+
+/***********************************************************************/
+
+template <class FloatT>
+void test_limits (FloatT, const char *tname, const char *fmt)
+{
+    typedef std::numeric_limits<FloatT> FLim;
+    typedef limits_values<FloatT>       FVal;
+
+    // self-test: assert that endianness is correctly computed
+#if defined (__alpha)
+    RW_WARNING (t, !big_endian, ("alpha is typically little-endian"));
+#elif defined (_AIX)
+    RW_WARNING (t, big_endian, ("AIX is big-endian"));
+#elif defined (__hppa)
+    RW_WARNING (t, big_endian, ("HPPA is big-endian"));
+#elif defined (__i386__)
+    RW_WARNING (t, !big_endian, ("Intel x86 is little-endian"));
+#elif defined (__sparc)
+    RW_WARNING (t, big_endian, ("SPARC is big-endian"));
+#elif defined (_WIN64)
+    RW_WARNING (t, !big_endian, ("WIN64 is little-endian"));
+#elif defined (_WIN32)
+    RW_WARNING (t, !big_endian, ("WIN32 is little-endian"));
+#endif
+
+#ifndef _RWSTD_NO_STATIC_CONST_MEMBER_INIT
+
+#  if !defined (__EDG__) || __EDG_VERSION__ > 245
+#    define CHECK_CONST(const_int)   \
+         enum { e = const_int };     \
+         (void)&const_int
+#  else   // if EDG eccp < 3.0
+    // working around an EDG eccp 2.4x ICE (not in 3.0)
+#    define CHECK_CONST(const_int)                        \
+         switch (const_int) { case const_int: break; };   \
+         (void)&const_int
+#  endif   // __EDG__
+#else
+   // static const integral members must be usable
+   //  as constant integral expressions
+#  define CHECK_CONST(const_int)      enum { e = const_int }
+#endif   // _RWSTD_NO_STATIC_CONST_MEMBER_INIT
+
+
+// compare against a computed value
+#define VERIFY_DATA(member) do {                                        \
+        /* verify that member is a constant integral expression */      \
+        CHECK_CONST (FLim::member);                                     \
+        /* verify value */                                              \
+        rw_assert (FLim::member == FVal::member (), 0, __LINE__,        \
+                   "numeric_limits<%s>::" #member " == %i, got %i",     \
+                   tname, FVal::member (), FLim::member);               \
+    } while (0)
+
+// compare against a constant
+#define VERIFY_CONST(member, value) do {                                 \
+        /* verify that member if a constant integral expression */       \
+        CHECK_CONST (FLim::member);                                      \
+        /* verify value */                                               \
+        rw_assert (FLim::member == value, 0, __LINE__,                   \
+                   "numeric_limits<%s>::" #member " == %i, got %i",      \
+                   tname, FVal::member, value);                          \
+    } while (0)
+
+// account for NaN != NaN
+#define VERIFY_FUNCTION(member) do {                                       \
+        /* verify function signature */                                    \
+        FloatT (*pf)() _PTR_THROWS(()) = &FLim::member;                    \
+        _RWSTD_UNUSED (pf);                                                \
+        /* verify value */                                                 \
+        rw_assert (   FLim::member () == FVal::member ()                   \
+                   || FLim::member () != FLim::member ()                   \
+                   && FVal::member () != FVal::member (),                  \
+                   0, __LINE__,                                            \
+                   "numeric_limits<%s>::" #member "() == %{@}, got %{@}",  \
+                   tname, fmt, FVal::member (), fmt, FLim::member ());     \
+    } while (0)
+
+#define VERIFY_SIGNATURE(member) do {                   \
+        /* verify function signature */                 \
+        FloatT (*pf)() _PTR_THROWS(()) = &FLim::member; \
+        _RWSTD_UNUSED (pf);                             \
+    } while (0)
+
+#undef min
+#undef max
+
+    VERIFY_FUNCTION (min);           // 18.2.1.2, p1
+    VERIFY_FUNCTION (max);           //           p4
+    VERIFY_DATA (digits);            //           p6
+    VERIFY_DATA (digits10);          //           p9
+    VERIFY_DATA (is_signed);         //           p11
+    VERIFY_DATA (is_integer);        //           p13
+    VERIFY_DATA (is_exact);          //           p15
+    VERIFY_DATA (radix);             //           p17
+    
+    VERIFY_FUNCTION (epsilon);       // 18.2.1.2, p19
+    VERIFY_FUNCTION (round_error);   //           p22
+
+    VERIFY_DATA (min_exponent);      // 18.2.1.2, p23
+    VERIFY_DATA (min_exponent10);    //           p25
+    VERIFY_DATA (max_exponent);      //           p27
+    VERIFY_DATA (max_exponent10);    //           p29
+
+    VERIFY_FUNCTION (infinity);      // 18.2.1.2, p42
+
+    if (FLim::has_infinity)
+        test_infinity (FLim::infinity (), FLim::max (), tname);
+
+    if (std::numeric_limits<FloatT>::traps)   //  p45
+        VERIFY_SIGNATURE (quiet_NaN);
+    else {
+        VERIFY_FUNCTION (quiet_NaN);
+
+        if (FLim::has_quiet_NaN)
+            test_quiet_NaN (FLim::quiet_NaN (),
+                            FLim::quiet_NaN (), tname);
+    }
+    
+    if (std::numeric_limits<FloatT>::traps)   //  p47
+        VERIFY_SIGNATURE (signaling_NaN);
+    else {
+        VERIFY_FUNCTION (signaling_NaN);
+
+        if (FLim::has_signaling_NaN) 
+            test_signaling_NaN (FLim::signaling_NaN (),
+                                FLim::signaling_NaN (), tname);
+    }
+
+    if (std::numeric_limits<FloatT>::traps) { //  p49
+        // denorm min may trap (e.g., Tru64 UNIX on Alpha
+        // with Compaq C++ without the -ieee compiler flag)
+        VERIFY_SIGNATURE (denorm_min);
+    }
+    else {
+        VERIFY_FUNCTION (denorm_min);
+    }
+
+#ifdef _MSC_VER
+
+    if (sizeof (FloatT) > sizeof (float)) {
+        // for doubles and long doubles only, verify that denorm_min
+        // is properly classified
+
+        const FloatT denorm_min = FLim::denorm_min ();
+
+        const int fpc = _fpclass (double (denorm_min));
+
+        rw_assert (_FPCLASS_PD == fpc, 0, __LINE__,
+                   "_fpclass(numeric_limits<%s>::denorm_min()) == "
+                   "%d (_FPCLASS_PD), got %d (%s)",
+                   tname, _FPCLASS_PD, fpc, fpclass_name (fpc));
+    }
+
+#endif   // _MSC_VER
+
+    VERIFY_DATA (is_iec559);         // 18.2.1.2, p52
+    VERIFY_DATA (is_bounded);        //           p54
+    VERIFY_DATA (is_modulo);         //           p56
+
+    VERIFY_DATA (tinyness_before);   // 18.2.1.2, p61
+    VERIFY_DATA (round_style);       //           p63
+
+    if (!FLim::traps) {              // 18.2.1.2, p59
+        // invalid floating point operations must not trap
+
+        // IEEE 754 specifies that the following operations
+        // return NaN unless they trap:
+        //     1.   sqrt (n); n < 0
+        //     2.   rem (x, 0.0), rem (inf, x)
+        //     3.   0 * inf
+        //     4.   0.0 / 0.0, inf / inf
+        //     5.   inf - inf (when both inf have the same sign)
+
+        // use a variable (not a literal) to prevent warnings
+        volatile FloatT zero = 0;
+
+        // compute infinity (division may trap)
+        const FloatT inf = FLim::infinity ();
+
+        FloatT nan = zero * inf;   // #3
+        nan = zero / zero;         // #4a
+        nan = inf / inf;           // #4b
+        nan = inf - inf;           // #5
+
+        _RWSTD_UNUSED (inf);
+        _RWSTD_UNUSED (nan);
+    }
+
+    if (FLim::is_iec559) {
+        // 18.2.1.2, p33
+        VERIFY_CONST (has_infinity, true);
+
+        // 18.2.1.2, p36
+        VERIFY_CONST (has_quiet_NaN, true);
+
+        // 18.2.1.2, p39
+        VERIFY_CONST (has_signaling_NaN, true);
+
+        // 18.2.1.2, p40 - 42
+        VERIFY_DATA (has_denorm);
+        VERIFY_DATA (has_denorm_loss);
+    }
+    else {
+        // 18.2.1.2, p34 - 42
+        VERIFY_DATA (has_quiet_NaN);
+        VERIFY_DATA (has_signaling_NaN);
+        VERIFY_DATA (has_denorm);
+        VERIFY_DATA (has_denorm_loss);
+    }
+}
+
+/***********************************************************************/
+
+static int
+run_test (int, char**)
+{
+#undef VERIFY_CONST
+#define VERIFY_CONST(x, value) do {                     \
+        enum { e = x };                                 \
+        rw_assert (value == x, 0, __LINE__,             \
+                   #x " == %d, got %d", value, x);      \
+    } while (0)
+
+    // verify values of constants in 18.2.1.3
+    VERIFY_CONST (std::round_indeterminate,      -1);
+    VERIFY_CONST (std::round_toward_zero,         0);
+    VERIFY_CONST (std::round_to_nearest,          1);
+    VERIFY_CONST (std::round_toward_infinity,     2);
+    VERIFY_CONST (std::round_toward_neg_infinity, 3);
+
+    // verify values of constants in 18.2.1.4
+    VERIFY_CONST (std::denorm_indeterminate, std::float_denorm_style (-1));
+    VERIFY_CONST (std::denorm_absent,        std::float_denorm_style (0));
+    VERIFY_CONST (std::denorm_present,       std::float_denorm_style (1));
+        
+    test_limits (float (), "float", "%g");
+    test_limits (double (), "double", "%g");
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
+   // working around a SunPro 5.3 ICE (PR #25968)
+#  if !defined (__SUNPRO_CC) || __SUNPRO_CC > 0x530
+
+    const char fmt[] = "%" _RWSTD_LDBL_PRINTF_PREFIX "g";
+    test_limits ((long double)0.0, "long double", fmt);
+
+#  endif   // SunPro > 5.3
+
+#endif   //_RWSTD_NO_LONG_DOUBLE
+
+    return 0;
+}
+
+/***********************************************************************/
+
+int main (int argc, char *argv[])
+{
+    // working around a bogus EDG eccp warning (see PR #25679)
+    _RWSTD_UNUSED (big_endian);
+
+    return rw_test (argc, argv, __FILE__,
+                    "numeric.special",
+                    "floating specializations",
+                    run_test,
+                    "",
+                    (void*)0);
+}

Propchange: stdcxx/trunk/tests/support/18.numeric.special.float.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: stdcxx/trunk/tests/support/18.numeric.special.float.cpp
------------------------------------------------------------------------------
    svn:keywords = Id



Mime
View raw message