stdcxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin Sebor <se...@roguewave.com>
Subject Re: svn commit: r646396 - /stdcxx/trunk/src/num_put.cpp
Date Thu, 10 Apr 2008 03:30:14 GMT
Unfortunately, my "fix" wasn't good enough. It declared the function
so that num_put.cpp compiled but it missed that signbit() is defined
in libsunmath. Since we don't link with it we would get unsats when
linking programs with stdcxx.

While trying to figure out how to get around this I found that the
C compiler has a __builtin_signbit() function. Unfortunately, the
built-in functions don't seem to be recognized by the C++ compiler.
I think the best thing to do here (and what I think we should do
for all the other functions, too) is to implement it ourselves:

   int __rw_signbit (double x) { return *(long long*)&x >> 63; }

This should work on all IEEE 754 platforms. The other functions
will be a little more tricky but should be able to use a similar
approach.

I've corrected my fix to __rw_signbit() and checked it in here:
   http://svn.apache.org/viewvc?rev=646628&view=rev

It's probably too late to [re]implement the other functions for
4.2.1 but we should open an issue to remind us to do it for 4.2.2
or 4.3, whichever comes first.

Martin

The error:

CC accumulate.o -o accumulate -library=%none  -mt 
-L/build/sebor/stdcxx-suncc-5.9_j1-15d/lib 
-R/build/sebor/stdcxx-suncc-5.9_j1-15d/lib -lstd15d  -lm
Undefined                       first referenced
  symbol                             in file
signbit 
/build/sebor/stdcxx-suncc-5.9_j1-15d/lib/libstd15d.so
ld: fatal: Symbol referencing errors. No output written to accumulate


Martin Sebor wrote:
> faridz@apache.org wrote:
>> Author: faridz
>> Date: Wed Apr  9 08:10:18 2008
>> New Revision: 646396
>>
>> URL: http://svn.apache.org/viewvc?rev=646396&view=rev
>> Log:
>> 2008-04-09  Farid Zaripov  <farid_zaripov@epam.com>
>>
>>     STDCXX-51
>>     * src/num_put.cpp (__rw_isfinite): New function to detect inf and 
>> nan values.
>>     (__rw_signbit): New function to detect the sign of floating point 
>> value.
>>     (__rw_isinf): New function to detect inf values.
>>     (__rw_isnan): New function to detect nan values.
>>     (__rw_isqnan): New function to detect quiet nan values.
>>     (__rw_issnan): New function to detect signaling nan values.
>>     (__rw_fmat_infinite): New function to format inf and nan values.
>>     (__rw_put_num): Use __rw_isfinite() and __rw_fmat_infinite() to 
>> format inf and nan values.
> 
> I'm afraid this patch causes a compilation error on Solaris:
> 
> CC -c -D_RWSTDDEBUG   -mt -D_RWSTD_SOLARIS_THREADS 
> -I/amd/devco/sebor/stdcxx/include 
> -I/build/sebor/stdcxx-suncc-5.9_j1-15d-solaris/include  -library=%none 
> -g  +w -errtags -erroff=hidef  -KPIC 
> /amd/devco/sebor/stdcxx/src/strstream.cpp
> "/amd/devco/sebor/stdcxx/src/num_put.cpp", line 122: Error, badfunccp: 
> The function "signbit" must have a prototype.
> 1 Error(s) detected.
> 
> Depending on where one looks, the signbit() macro is declared either
> in <math.h> or <sunmath.h>
> 
> http://docs.sun.com/app/docs/doc/816-5172/signbit-3m?a=view
> http://docs.sun.com/source/820-4180/man3m/signbit.3m.html
> 
> I suspect Sun C++ is being strict by not declaring it in <math.h>
> because the macro is a C99 feature and the C++ standard incorporates
> C89 but not C99 (yet).
> 
> In any even, I fixed it by conditionally including <sunmath.h>
> on Solaris so we don't lose too many build results overnight:
>   http://svn.apache.org/viewvc?rev=646597&view=rev
> 
> Martin
> 
>>
>> Modified:
>>     stdcxx/trunk/src/num_put.cpp
>>
>> Modified: stdcxx/trunk/src/num_put.cpp
>> URL: 
>> http://svn.apache.org/viewvc/stdcxx/trunk/src/num_put.cpp?rev=646396&r1=646395&r2=646396&view=diff

>>
>> ============================================================================== 
>>
>> --- stdcxx/trunk/src/num_put.cpp (original)
>> +++ stdcxx/trunk/src/num_put.cpp Wed Apr  9 08:10:18 2008
>> @@ -34,6 +34,13 @@
>>  #include <stdio.h>    // for snprintf()
>>  #include <string.h>   // for memmove(), memset()
>>  
>> +#include <float.h>   // for _finite(), _fpclass(), _isnan(), _copysign()
>> +#include <math.h>    // for isfinite(), isnan(), isinf(), signbit()
>> +
>> +#ifndef _RWSTD_NO_IEEEFP_H
>> +#  include <ieeefp.h>   // for fpclass(), isnan()
>> +#endif   // _RWSTD_NO_IEEEFP_H
>> +
>>  #include <loc/_num_put.h>
>>  
>>  #include "strtol.h"   // for __rw_digit_map
>> @@ -65,6 +72,7 @@
>>  #  endif   // _RWSTD_NO_SNPRINTF_IN_LIBC
>>  #endif   // _RWSTD_NO_SNPRINTF
>>  
>> +
>>  _RWSTD_NAMESPACE (__rw) {  
>>  static const char __rw_digits[] =
>> @@ -72,6 +80,155 @@
>>      "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
>>  
>>  
>> +#if defined (_MSC_VER)
>> +
>> +inline bool __rw_isfinite (double val) { return !!_finite (val); }
>> +
>> +inline bool __rw_signbit (double val) { return 0 > _copysign (1., 
>> val); }
>> +
>> +inline bool __rw_isinf (double val) {
>> +    const int fpc = _fpclass (val);
>> +
>> +    if (_FPCLASS_NINF == fpc) {
>> +        // verify that __rw_signbit() correctly determines
>> +        // the sign of negative infinity
>> +        _RWSTD_ASSERT (__rw_signbit (val));
>> +        return true;
>> +    }
>> +    else if (_FPCLASS_PINF == fpc) {
>> +        // verify that __rw_signbit() correctly determines
>> +        // the sign of positive infinity
>> +        _RWSTD_ASSERT (!__rw_signbit (val));
>> +        return true;
>> +    }
>> +
>> +    return false;
>> +}
>> +
>> +inline bool __rw_isnan (double val) { return !!_isnan (val); }
>> +
>> +inline bool __rw_isqnan (double val) {
>> +    return _FPCLASS_QNAN == _fpclass (val);
>> +}
>> +
>> +inline bool __rw_issnan (double val) {
>> +    return _FPCLASS_SNAN == _fpclass (val);
>> +}
>> +
>> +#elif defined (_RWSTD_OS_SUNOS)
>> +
>> +inline bool __rw_isfinite (double val) { return !!finite (val); }
>> +
>> +inline bool __rw_signbit (double val) { return !!signbit (val); }
>> +
>> +inline bool __rw_isinf (double val) {
>> +    const int fpc = fpclass (val);
>> +
>> +    if (FP_NINF == fpc) {
>> +        // verify that __rw_signbit() correctly determines
>> +        // the sign of negative infinity
>> +        _RWSTD_ASSERT (__rw_signbit (val));
>> +        return true;
>> +    }
>> +    else if (FP_PINF == fpc) {
>> +        // verify that __rw_signbit() correctly determines
>> +        // the sign of positive infinity
>> +        _RWSTD_ASSERT (!__rw_signbit (val));
>> +        return true;
>> +    }
>> +
>> +    return false;
>> +}
>> +
>> +inline bool __rw_isnan (double val) { return 0 != isnan (val); }
>> +
>> +inline bool __rw_isqnan (double val) { return FP_QNAN == fpclass 
>> (val); }
>> +
>> +inline bool __rw_issnan (double val) { return FP_SNAN == fpclass 
>> (val); }
>> +
>> +#elif defined (fpclassify)
>> +
>> +inline bool __rw_isfinite (double val) { return !!isfinite (val); }
>> +
>> +inline bool __rw_signbit (double val) { return !!signbit (val); }
>> +
>> +inline bool __rw_isinf (double val) { return !!isinf (val); }
>> +
>> +inline bool __rw_isnan (double val) { return !!isnan (val); }
>> +
>> +inline bool __rw_isqnan (double val) { return false; }
>> +
>> +inline bool __rw_issnan (double val) { return false; }
>> +
>> +#else
>> +
>> +inline bool __rw_isfinite (double) { return true; }
>> +
>> +inline bool __rw_signbit (double) { return false; }
>> +
>> +inline bool __rw_isinf (double) { return false; }
>> +
>> +inline bool __rw_isnan (double) { return false; }
>> +
>> +inline bool __rw_isqnan (double) { return false; }
>> +
>> +inline bool __rw_issnan (double) { return false; }
>> +
>> +#endif
>> +
>> +
>> +static int
>> +__rw_fmat_infinite (char *buf, size_t bufsize, double val, unsigned 
>> flags)
>> +{
>> +    _RWSTD_ASSERT (!__rw_isfinite (val));
>> +    _RWSTD_ASSERT (5 <= bufsize);
>> +
>> +    char* end = buf;
>> +    const bool cap = !!(flags & _RWSTD_IOS_UPPERCASE);
>> +
>> +    if (__rw_isinf (val)) {
>> +        if (__rw_signbit (val)) {
>> +            *end++ = '-';
>> +        }
>> +        else if (flags & _RWSTD_IOS_SHOWPOS) {
>> +            *end++ = '+';
>> +        }
>> +
>> +        const char str [] = "iInNfF";
>> +        *end++ = str [cap + 0];
>> +        *end++ = str [cap + 2];
>> +        *end++ = str [cap + 4];
>> +    }
>> +    else {
>> +        _RWSTD_ASSERT (__rw_isnan (val));
>> +#if 0
>> +        // disabled since not all platforms correctly handling sign 
>> of NaN's
>> +        if (__rw_signbit (val)) {
>> +            *end++ = '-';
>> +        }
>> +        else if (flags & _RWSTD_IOS_SHOWPOS) {
>> +            *end++ = '+';
>> +        }
>> +#endif
>> +
>> +        const char str [] = "nNaAqQsS";
>> +        *end++ = str [cap + 0];
>> +        *end++ = str [cap + 2];
>> +        *end++ = str [cap + 0];
>> +#if 0
>> +        // disabled since not all platforms supporting +        // 
>> the quiet and signaling NaN's
>> +        if (__rw_isqnan (val))
>> +            *end++ = str [cap + 4];
>> +        else if (__rw_issnan (val))
>> +            *end++ = str [cap + 6];
>> +#endif
>> +    }
>> +
>> +    return int (end - buf);
>> +}
>> +
>> +
>>  #ifdef _RWSTD_LONG_LONG
>>  
>>  
>> @@ -778,88 +935,112 @@
>>  
>>  #endif   // _RWSTD_LONG_LONG
>>  
>> -    case __rw_facet::_C_float | __rw_facet::_C_ptr:
>> -        fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 : prec;
>> -        fmt = __rw_get_stdio_fmat (fmtbuf, type & ~__rw_facet::_C_ptr,
>> -                                   flags, fpr);
>> -        for (; ;) {
>> -            len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt,
>> -                                    *(const float*)pval));
>> -
>> -            if (len >= bufsize) {
>> -                if (*pbuf != buf)
>> -                    delete[] *pbuf;
>> -
>> -                *pbuf = new char [bufsize = len + 1 ? len + 1 : 
>> bufsize * 2];
>> +    case __rw_facet::_C_float | __rw_facet::_C_ptr: {
>> +            const float fval = *(const float*)pval;
>> +            if (!__rw_isfinite (fval)) {
>> +                len = __rw_fmat_infinite (*pbuf, bufsize, fval, flags);
>> +                end = *pbuf + len;
>>              }
>>              else {
>> -                _RWSTD_ASSERT (len > 0);
>> -
>> -                break;
>> -            }
>> -        }
>> +                fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 :
prec;
>> +                fmt = __rw_get_stdio_fmat (fmtbuf, type & 
>> ~__rw_facet::_C_ptr,
>> +                                           flags, fpr);
>> +                for (; ;) {
>> +                    len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt, fval));
>>  
>> -        end = *pbuf + len;
>> +                    if (len >= bufsize) {
>> +                        if (*pbuf != buf)
>> +                            delete[] *pbuf;
>>  
>> -        // fix up output to conform to C99
>> -        __rw_fix_flt (end, len, flags, fpr);
>> -        break;
>> +                        bufsize = len + 1 ? len + 1 : bufsize * 2;
>> +                        *pbuf = new char [bufsize];
>> +                    }
>> +                    else {
>> +                        _RWSTD_ASSERT (len > 0);
>>  
>> -    case __rw_facet::_C_double | __rw_facet::_C_ptr:
>> -        fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 : prec;
>> -        fmt = __rw_get_stdio_fmat (fmtbuf, type & ~__rw_facet::_C_ptr,
>> -                                   flags, fpr);
>> +                        break;
>> +                    }
>> +                }
>>  
>> -        for ( ; ; ) {
>> -            len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt,
>> -                                    *(const double*)pval));
>> +                end = *pbuf + len;
>>  
>> -            if (len >= bufsize) {
>> -                if (*pbuf != buf)
>> -                    delete[] *pbuf;
>> +                // fix up output to conform to C99
>> +                __rw_fix_flt (end, len, flags, fpr);
>> +            }
>> +        }
>> +        break;
>>  
>> -                *pbuf = new char [bufsize = len + 1 ? len + 1 : 
>> bufsize * 2];
>> +    case __rw_facet::_C_double | __rw_facet::_C_ptr: {
>> +            const double dval = *(const double*)pval;
>> +            if (!__rw_isfinite (dval)) {
>> +                len = __rw_fmat_infinite (*pbuf, bufsize, dval, flags);
>> +                end = *pbuf + len;
>>              }
>>              else {
>> -                _RWSTD_ASSERT (len > 0);
>> +                fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 :
prec;
>> +                fmt = __rw_get_stdio_fmat (fmtbuf, type & 
>> ~__rw_facet::_C_ptr,
>> +                                           flags, fpr);
>> +
>> +                for ( ; ; ) {
>> +                    len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt, dval));
>> +
>> +                    if (len >= bufsize) {
>> +                        if (*pbuf != buf)
>> +                            delete[] *pbuf;
>> +
>> +                        bufsize = len + 1 ? len + 1 : bufsize * 2;
>> +                        *pbuf = new char [bufsize];
>> +                    }
>> +                    else {
>> +                        _RWSTD_ASSERT (len > 0);
>> +
>> +                        break;
>> +                    }
>> +                }
>>  
>> -                break;
>> +                end = *pbuf + len;
>> +
>> +                // fix up output to conform to C99
>> +                __rw_fix_flt (end, len, flags, fpr);
>>              }
>>          }
>> -
>> -        end = *pbuf + len;
>> -
>> -        // fix up output to conform to C99
>> -        __rw_fix_flt (end, len, flags, fpr);
>>          break;
>>  
>>  #ifndef _RWSTD_NO_LONG_DOUBLE
>>  
>> -    case __rw_facet::_C_ldouble | __rw_facet::_C_ptr:
>> -        fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 : prec;
>> -        fmt = __rw_get_stdio_fmat (fmtbuf, type & ~__rw_facet::_C_ptr,
>> -                                   flags, fpr);
>> -
>> -        for ( ; ; ) {
>> -            len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt,
>> -                                    *(const long double*)pval));
>> -            if (len >= bufsize) {
>> -                if (*pbuf != buf)
>> -                    delete[] *pbuf;
>> -
>> -                *pbuf = new char [bufsize = len + 1 ? len + 1 : 
>> bufsize * 2];
>> +    case __rw_facet::_C_ldouble | __rw_facet::_C_ptr: {
>> +            const long double ldval = *(const long double*)pval;
>> +            if (!__rw_isfinite (ldval)) {
>> +                len = __rw_fmat_infinite (*pbuf, bufsize, ldval, flags);
>> +                end = *pbuf + len;
>>              }
>>              else {
>> -                _RWSTD_ASSERT (len > 0);
>> +                fpr = prec < 0 && flags & _RWSTD_IOS_FIXED ? 0 :
prec;
>> +                fmt = __rw_get_stdio_fmat (fmtbuf, type & 
>> ~__rw_facet::_C_ptr,
>> +                                           flags, fpr);
>> +
>> +                for ( ; ; ) {
>> +                    len = SizeT (_SNPRINTF (*pbuf, bufsize, fmt, 
>> ldval));
>> +                    if (len >= bufsize) {
>> +                        if (*pbuf != buf)
>> +                            delete[] *pbuf;
>> +
>> +                        bufsize = len + 1 ? len + 1 : bufsize * 2;
>> +                        *pbuf = new char [bufsize];
>> +                    }
>> +                    else {
>> +                        _RWSTD_ASSERT (len > 0);
>> +
>> +                        break;
>> +                    }
>> +                }
>>  
>> -                break;
>> +                end = *pbuf + len;
>> +
>> +                // fix up output to conform to C99
>> +                __rw_fix_flt (end, len, flags, fpr);
>>              }
>>          }
>> -
>> -        end = *pbuf + len;
>> -
>> -        // fix up output to conform to C99
>> -        __rw_fix_flt (end, len, flags, fpr);
>>          break;
>>  
>>  #endif   // _RWSTD_NO_LONG_DOUBLE
>>
>>
> 


Mime
View raw message