Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (c) 1999
      3  * Silicon Graphics Computer Systems, Inc.
      4  *
      5  * Copyright (c) 1999
      6  * Boris Fomitchev
      7  *
      8  * This material is provided "as is", with absolutely no warranty expressed
      9  * or implied. Any use is at your own risk.
     10  *
     11  * Permission to use or copy this software for any purpose is hereby granted
     12  * without fee, provided the above notices are retained on all copies.
     13  * Permission to modify the code and to distribute modified code is granted,
     14  * provided the above notices are retained, and a notice that the code was
     15  * modified is included with the above copyright notice.
     16  *
     17  */
     18 
     19 #include "stlport_prefix.h"
     20 
     21 #include <cmath>
     22 #include <ios>
     23 #include <locale>
     24 
     25 #if defined (__DECCXX)
     26 #  define NDIG 400
     27 #else
     28 #  define NDIG 82
     29 #endif
     30 
     31 #define todigit(x) ((x)+'0')
     32 
     33 #if defined (_STLP_UNIX)
     34 
     35 #  if defined (__sun)
     36 #    include <floatingpoint.h>
     37 #  endif
     38 
     39 #  if defined (__sun) || defined (__digital__) || defined (__sgi) || defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
     40 // DEC, SGI & Solaris need this
     41 #    include <values.h>
     42 #    include <nan.h>
     43 #  endif
     44 
     45 #  if defined (__QNXNTO__) || ( defined(__GNUC__) && defined(__APPLE__) ) || defined(_STLP_USE_UCLIBC) /* 0.9.26 */ || \
     46       defined(__FreeBSD__)
     47 #    define USE_SPRINTF_INSTEAD
     48 #  endif
     49 
     50 #  if defined (_AIX) // JFA 3-Aug-2000
     51 #    include <math.h>
     52 #    include <float.h>
     53 #  endif
     54 
     55 #  include <math.h>
     56 #endif
     57 
     58 #include <cstdio>
     59 #include <cstdlib>
     60 
     61 #if defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__) || defined (__DJGPP) || \
     62     defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
     63 #  include <float.h>
     64 #endif
     65 
     66 #if defined (__MRC__) || defined (__SC__)  || defined (_CRAY)  //*TY 02/24/2000 - added support for MPW
     67 #  include <fp.h>
     68 #endif
     69 
     70 #if defined (__CYGWIN__)
     71 #  include <ieeefp.h>
     72 #endif
     73 
     74 #if defined (__MSL__)
     75 #  include <cstdlib>  // for atoi
     76 #  include <cstdio>  // for snprintf
     77 #  include <algorithm>
     78 #  include <cassert>
     79 #endif
     80 
     81 #if defined (__ISCPP__)
     82 #  include <cfloat>
     83 #endif
     84 
     85 #include <algorithm>
     86 
     87 #if defined (__DMC__)
     88 #  define snprintf _snprintf
     89 #endif
     90 
     91 _STLP_BEGIN_NAMESPACE
     92 
     93 _STLP_MOVE_TO_PRIV_NAMESPACE
     94 
     95 #if defined (__MWERKS__) || defined(__BEOS__)
     96 #  define USE_SPRINTF_INSTEAD
     97 #endif
     98 
     99 template <int N>
    100 struct _Dig
    101 {
    102     enum { dig = _Dig<N/10>::dig + 1 };
    103 };
    104 
    105 _STLP_TEMPLATE_NULL
    106 struct _Dig<0>
    107 {
    108     enum { dig = 0 };
    109 };
    110 
    111 #ifdef _STLP_NO_LONG_DOUBLE
    112 # define MAXEDIGITS int(_Dig<DBL_MAX_10_EXP>::dig)
    113 # define MAXFSIG DBL_DIG
    114 # define MAXFCVT (DBL_DIG + 1)
    115 #else
    116 # define MAXEDIGITS int(_Dig<LDBL_MAX_10_EXP>::dig)
    117 # define MAXFSIG LDBL_DIG
    118 # define MAXFCVT (LDBL_DIG + 1)
    119 #endif
    120 
    121 // Tests for infinity and NaN differ on different OSs.  We encapsulate
    122 // these differences here.
    123 #if !defined (USE_SPRINTF_INSTEAD)
    124 #  if defined (__hpux) && defined (__GNUC__)
    125 #    define _STLP_USE_SIGN_HELPER
    126 #  elif defined (__DJGPP) || (defined (_STLP_USE_GLIBC) && ! defined (__MSL__)) || \
    127       defined (__CYGWIN__) || \
    128       defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
    129       defined (__HP_aCC)
    130 static inline bool _Stl_is_nan_or_inf(double x)
    131 #    if defined (isfinite)
    132 { return !isfinite(x); }
    133 #    else
    134 { return !finite(x); }
    135 #    endif
    136 static inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && ( copysign(1., x) < 0 ); }
    137 static inline bool _Stl_is_inf(double x)        { return isinf(x); }
    138 // inline bool _Stl_is_neg_inf(double x)    { return isinf(x) < 0; }
    139 static inline bool _Stl_is_neg_inf(double x)    { return isinf(x) && x < 0; }
    140 #  elif (defined (__unix) || defined (__unix__)) && \
    141          !defined (__APPLE__) && !defined (__DJGPP) && !defined(__osf__) && \
    142          !defined (_CRAY) && !defined(__ANDROID__)
    143 static inline bool _Stl_is_nan_or_inf(double x) { return IsNANorINF(x); }
    144 static inline bool _Stl_is_inf(double x)        { return IsNANorINF(x) && IsINF(x); }
    145 static inline bool _Stl_is_neg_inf(double x)    { return (IsINF(x)) && (x < 0.0); }
    146 static inline bool _Stl_is_neg_nan(double x)    { return IsNegNAN(x); }
    147 #  elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__)
    148 static inline bool _Stl_is_nan_or_inf(double x) { return !_finite(x); }
    149 #    if !defined (__BORLANDC__)
    150 static inline bool _Stl_is_inf(double x)        {
    151   int fclass = _fpclass(x);
    152   return fclass == _FPCLASS_NINF || fclass == _FPCLASS_PINF;
    153 }
    154 static inline bool _Stl_is_neg_inf(double x)    { return _fpclass(x) == _FPCLASS_NINF; }
    155 #    else
    156 static inline bool _Stl_is_inf(double x)        {  return _Stl_is_nan_or_inf(x) && !_isnan(x);}
    157 static inline bool _Stl_is_neg_inf(double x)    {  return _Stl_is_inf(x) && x < 0 ; }
    158 #    endif
    159 static inline bool _Stl_is_neg_nan(double x)    { return _isnan(x) && _copysign(1., x) < 0 ; }
    160 #    if defined (__BORLANDC__)
    161 static inline bool _Stl_is_nan_or_inf(long double x) { return !_finitel(x); }
    162 static inline bool _Stl_is_inf(long double x)        {  return _Stl_is_nan_or_inf(x) && !_isnanl(x);}
    163 static inline bool _Stl_is_neg_inf(long double x)    {  return _Stl_is_inf(x) && x < 0 ; }
    164 static inline bool _Stl_is_neg_nan(long double x)    { return _isnanl(x) && _copysignl(1.l, x) < 0 ; }
    165 #    elif !defined (_STLP_NO_LONG_DOUBLE)
    166 // Simply there to avoid warning long double -> double implicit conversion:
    167 static inline bool _Stl_is_nan_or_inf(long double x) { return _Stl_is_nan_or_inf(__STATIC_CAST(double, x)); }
    168 static inline bool _Stl_is_inf(long double x)        {  return _Stl_is_inf(__STATIC_CAST(double, x));}
    169 static inline bool _Stl_is_neg_inf(long double x)    {  return _Stl_is_neg_inf(__STATIC_CAST(double, x)); }
    170 static inline bool _Stl_is_neg_nan(long double x)    { return _Stl_is_neg_nan(__STATIC_CAST(double, x)); }
    171 #    endif
    172 #  elif defined (__MRC__) || defined (__SC__) || defined (__DMC__)
    173 static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !isfinite(x); }
    174 static bool _Stl_is_inf(double x)        { return !isfinite(x); }
    175 static bool _Stl_is_neg_inf(double x)    { return !isfinite(x) && signbit(x); }
    176 static bool _Stl_is_neg_nan(double x)    { return isnan(x) && signbit(x); }
    177 #  elif /* defined(__FreeBSD__) || defined(__OpenBSD__) || */ (defined(__GNUC__) && defined(__APPLE__))
    178 static inline bool _Stl_is_nan_or_inf(double x) { return !finite(x); }
    179 static inline bool _Stl_is_inf(double x)        {   return _Stl_is_nan_or_inf(x) && ! isnan(x); }
    180 static inline bool _Stl_is_neg_inf(double x)    {   return _Stl_is_inf(x) && x < 0 ; }
    181 static inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && copysign(1., x) < 0 ; }
    182 #  elif defined( _AIX ) // JFA 11-Aug-2000
    183 static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !finite(x); }
    184 static bool _Stl_is_inf(double x)        { return !finite(x); }
    185 // bool _Stl_is_neg_inf(double x)    { return _class(x) == FP_MINUS_INF; }
    186 static bool _Stl_is_neg_inf(double x)    { return _Stl_is_inf(x) && ( copysign(1., x) < 0 );  }
    187 static bool _Stl_is_neg_nan(double x)    { return isnan(x) && ( copysign(1., x) < 0 );  }
    188 #  elif defined (__ISCPP__)
    189 static inline bool _Stl_is_nan_or_inf  (double x) { return _fp_isINF(x) || _fp_isNAN(x); }
    190 static inline bool _Stl_is_inf         (double x) { return _fp_isINF(x); }
    191 static inline bool _Stl_is_neg_inf     (double x) { return _fp_isINF(x) && x < 0; }
    192 static inline bool _Stl_is_neg_nan     (double x) { return _fp_isNAN(x) && x < 0; }
    193 #  elif defined (_CRAY)
    194 #    if defined (_CRAYIEEE)
    195 static inline bool _Stl_is_nan_or_inf(double x) { return isnan(x) || isinf(x); }
    196 static inline bool _Stl_is_inf(double x)        { return isinf(x); }
    197 static inline bool _Stl_is_neg_inf(double x)    { return isinf(x) && signbit(x); }
    198 static inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && signbit(x); }
    199 #    else
    200 static inline bool _Stl_is_nan_or_inf(double x) { return false; }
    201 static inline bool _Stl_is_inf(double x)        { return false; }
    202 static inline bool _Stl_is_neg_inf(double x)    { return false; }
    203 static inline bool _Stl_is_neg_nan(double x)    { return false; }
    204 #    endif
    205 #  else // nothing from above
    206 #    define USE_SPRINTF_INSTEAD
    207 #  endif
    208 #endif // !USE_SPRINTF_INSTEAD
    209 
    210 #if !defined (USE_SPRINTF_INSTEAD)
    211 // Reentrant versions of floating-point conversion functions.  The argument
    212 // lists look slightly different on different operating systems, so we're
    213 // encapsulating the differences here.
    214 
    215 #  if defined (__CYGWIN__) || defined(__DJGPP)
    216 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
    217 { return ecvtbuf(x, n, pt, sign, buf); }
    218 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
    219 { return fcvtbuf(x, n, pt, sign, buf); }
    220 #    if !defined (_STLP_NO_LONG_DOUBLE)
    221 #      if defined (__CYGWIN__)
    222 #        define _STLP_EMULATE_LONG_DOUBLE_CVT
    223 #      else
    224 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
    225 { return ecvtbuf(x, n, pt, sign, buf); }
    226 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
    227 { return fcvtbuf(x, n, pt, sign, buf); }
    228 #      endif
    229 #    endif
    230 #  elif defined (_STLP_USE_GLIBC)
    231 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    232 { return ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
    233 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    234 { return fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
    235 #    ifndef _STLP_NO_LONG_DOUBLE
    236 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    237 { return qecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
    238 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    239 { return qfcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
    240 #    endif
    241 #    define _STLP_NEED_CVT_BUFFER_SIZE
    242 #  elif defined (__sun)
    243 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
    244 { return econvert(x, n, pt, sign, buf); }
    245 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
    246 { return fconvert(x, n, pt, sign, buf); }
    247 #    ifndef _STLP_NO_LONG_DOUBLE
    248 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
    249 { return qeconvert(&x, n, pt, sign, buf); }
    250 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
    251 { return qfconvert(&x, n, pt, sign, buf); }
    252 #    endif
    253 #  elif defined (__DECCXX)
    254 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    255 { return (ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
    256 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    257 { return (fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
    258 #    ifndef _STLP_NO_LONG_DOUBLE
    259 // fbp : no "long double" conversions !
    260 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    261 { return (ecvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0) ; }
    262 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
    263 { return (fcvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
    264 #    endif
    265 #    define _STLP_NEED_CVT_BUFFER_SIZE
    266 #  elif defined (__hpux)
    267 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign)
    268 { return ecvt(x, n, pt, sign); }
    269 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign)
    270 { return fcvt(x, n, pt, sign); }
    271 #    if !defined (_STLP_NO_LONG_DOUBLE)
    272 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign)
    273 { return _ldecvt(*(long_double*)&x, n, pt, sign); }
    274 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign)
    275 { return _ldfcvt(*(long_double*)&x, n, pt, sign); }
    276 #    endif
    277 #    define _STLP_CVT_NEED_SYNCHRONIZATION
    278 #  elif defined (__unix) && !defined (__APPLE__) && !defined (_CRAY)
    279 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
    280 { return ecvt_r(x, n, pt, sign, buf); }
    281 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
    282 { return fcvt_r(x, n, pt, sign, buf); }
    283 #    if !defined (_STLP_NO_LONG_DOUBLE)
    284 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
    285 { return qecvt_r(x, n, pt, sign, buf); }
    286 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
    287 { return qfcvt_r(x, n, pt, sign, buf); }
    288 #    endif
    289 #  elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__)
    290 #    if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
    291 #      define _STLP_APPEND(a, b) a##b
    292 #      define _STLP_BUF_PARAMS , char* buf, size_t bsize
    293 #      define _STLP_SECURE_FUN(F, X, N, PT, SIGN) _STLP_APPEND(F, _s)(buf, bsize, X, N, PT, SIGN); return buf
    294 #    else
    295 #      define _STLP_BUF_PARAMS
    296 #      define _STLP_SECURE_FUN(F, X, N, PT, SIGN) return F(X, N, PT, SIGN)
    297 #      define _STLP_CVT_NEED_SYNCHRONIZATION
    298 #    endif
    299 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
    300 { _STLP_SECURE_FUN(_ecvt, x, n, pt, sign); }
    301 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
    302 { _STLP_SECURE_FUN(_fcvt, x, n, pt, sign); }
    303 #    if !defined (_STLP_NO_LONG_DOUBLE)
    304 #      if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
    305 #        define _STLP_PARAMS , buf, bsize
    306 #      else
    307 #        define _STLP_PARAMS
    308 #      endif
    309 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
    310 { return _Stl_ecvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); }
    311 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
    312 { return _Stl_fcvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); }
    313 #      undef _STLP_PARAMS
    314 #    endif
    315 #    undef _STLP_SECURE_FUN
    316 #    undef _STLP_BUF_PARAMS
    317 #    undef _STLP_APPEND
    318 #    if defined (__BORLANDC__) /* || defined (__GNUC__) MinGW do not support 'L' modifier so emulation do not work */
    319 #      define _STLP_EMULATE_LONG_DOUBLE_CVT
    320 #    endif
    321 #  elif defined (__ISCPP__)
    322 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
    323 { return _fp_ecvt( x, n, pt, sign, buf); }
    324 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
    325 { return _fp_fcvt(x, n, pt, sign, buf); }
    326 #    if !defined (_STLP_NO_LONG_DOUBLE)
    327 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
    328 { return _fp_ecvt( x, n, pt, sign, buf); }
    329 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
    330 { return _fp_fcvt(x, n, pt, sign, buf); }
    331 #    endif
    332 #  elif defined (_AIX) || defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
    333         defined (__MRC__) || defined (__SC__) || defined (_CRAY) || \
    334         defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR) || \
    335         defined (__DMC__)
    336 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign)
    337 { return ecvt(x, n, pt, sign ); }
    338 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign)
    339 { return fcvt(x, n, pt, sign); }
    340 #    if !defined (_STLP_NO_LONG_DOUBLE)
    341 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign)
    342 { return ecvt(x, n, pt, sign ); }
    343 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign)
    344 { return fcvt(x, n, pt, sign); }
    345 #    endif
    346 #    define _STLP_CVT_NEED_SYNCHRONIZATION
    347 #  else
    348 #    error Missing _Stl_ecvtR and _Stl_fcvtR implementations.
    349 #  endif
    350 
    351 #if defined (_STLP_CVT_NEED_SYNCHRONIZATION)
    352 /* STLport synchronize access to *cvt functions but those methods might
    353  * be called from outside, in this case we will still have a race condition. */
    354 #  if defined (_STLP_THREADS)
    355 static _STLP_STATIC_MUTEX& put_float_mutex() {
    356   static _STLP_STATIC_MUTEX __put_float_mutex _STLP_MUTEX_INITIALIZER;
    357   return __put_float_mutex;
    358 }
    359 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) {
    360   _STLP_auto_lock lock(put_float_mutex());
    361   strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf;
    362 }
    363 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) {
    364   _STLP_auto_lock lock(put_float_mutex());
    365   strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf;
    366 }
    367 #    if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
    368 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) {
    369   _STLP_auto_lock lock(put_float_mutex());
    370   strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf;
    371 }
    372 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) {
    373   _STLP_auto_lock lock(put_float_mutex());
    374   strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf;
    375 }
    376 #    endif
    377 #  else
    378 static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char*)
    379 { return _Stl_ecvtR(x, n, pt, sign); }
    380 static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char*)
    381 { return _Stl_fcvtR(x, n, pt, sign); }
    382 #    if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
    383 static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char*)
    384 { return _Stl_ecvtR(x, n, pt, sign); }
    385 static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char*)
    386 { return _Stl_fcvtR(x, n, pt, sign); }
    387 #    endif
    388 #  endif
    389 #endif
    390 
    391 #  if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS) && !defined (_STLP_NEED_CVT_BUFFER_SIZE)
    392 #    define _STLP_CVT_BUFFER(B) B
    393 #  else
    394 #    define _STLP_CVT_BUFFER(B) _STLP_ARRAY_AND_SIZE(B)
    395 #  endif
    396 
    397 #  if defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
    398 static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier);
    399 
    400 // Emulation of ecvt/fcvt functions using sprintf:
    401 static char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) {
    402   // If long double value can be safely converted to double without losing precision
    403   // we use the ecvt function for double:
    404   double y = __STATIC_CAST(double, x);
    405   if (x == y)
    406     return _Stl_ecvtR(y, n, pt, sign, buf);
    407 
    408   char fmtbuf[32];
    409   __fill_fmtbuf(fmtbuf, 0, 'L');
    410   sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x);
    411   /* We are waiting for something having the form x.xxxe+yyyy */
    412   *pt = 0;
    413   *sign = 0;
    414   int i = -1;
    415   int offset = 0;
    416   while (buf[++i] != 0 && n != 0) {
    417     if (buf[i] >= '0' && buf[i] <= '9') {
    418       --n;
    419       if (offset != 0)
    420         buf[i - offset] = buf[i];
    421     }
    422     else {
    423       if (offset != 0) break;
    424       ++offset;
    425       *pt = i;
    426     }
    427   }
    428   if (offset != 0)
    429     buf[i - offset] = 0;
    430   // Extract exponent part in point position:
    431   int e = 0;
    432   while (buf[++i] != 0) {
    433     if (buf[i] >= '0' && buf[i] <= '9') {
    434       e = e * 10 + (buf[i] - '0');
    435     }
    436   }
    437   *pt += e;
    438   return buf;
    439 }
    440 
    441 static char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) {
    442   // If long double value can be safely converted to double without losing precision
    443   // we use the fcvt function for double:
    444   double y = __STATIC_CAST(double, x);
    445   if (x == y)
    446     return _Stl_fcvtR(y, n, pt, sign, buf);
    447 
    448   char fmtbuf[32];
    449   __fill_fmtbuf(fmtbuf, ios_base::fixed, 'L');
    450   sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x);
    451   *pt = 0;
    452   *sign = 0;
    453   int i = -1;
    454   int offset = 0;
    455   while (buf[++i] != 0 && (offset == 0 || n != 0)) {
    456     if (buf[i] >= '0' && buf[i] <= '9') {
    457       if (offset != 0) {
    458         --n;
    459         buf[i - offset] = buf[i];
    460       }
    461     }
    462     else {
    463       ++offset;
    464       *pt = i;
    465     }
    466   }
    467   if (offset != 0)
    468     buf[i - offset] = 0;
    469   else
    470     *pt = i;
    471   return buf;
    472 }
    473 #endif
    474 
    475 //----------------------------------------------------------------------
    476 // num_put
    477 
    478 // __format_float formats a mantissa and exponent as returned by
    479 // one of the conversion functions (ecvt_r, fcvt_r, qecvt_r, qfcvt_r)
    480 // according to the specified precision and format flags.  This is
    481 // based on doprnt but is much simpler since it is concerned only
    482 // with floating point input and does not consider all formats.  It
    483 // also does not deal with blank padding, which is handled by
    484 // __copy_float_and_fill.
    485 
    486 static size_t __format_float_scientific( __iostring& buf, const char *bp,
    487                                          int decpt, int sign, bool is_zero,
    488                                          ios_base::fmtflags flags,
    489                                          int precision) {
    490   // sign if required
    491   if (sign)
    492     buf += '-';
    493   else if (flags & ios_base::showpos)
    494     buf += '+';
    495 
    496   // first digit of mantissa
    497   buf += *bp++;
    498 
    499   // start of grouping position, grouping won't occur in scientific notation
    500   // as it is impossible to have something like 1234.0e04 but we return a correct
    501   // group position for coherency with __format_float_fixed.
    502   size_t __group_pos = buf.size();
    503 
    504   // decimal point if required
    505   if (precision != 0 || flags & ios_base::showpoint) {
    506     buf += '.';
    507   }
    508 
    509   // rest of mantissa
    510   while (*bp != 0 && precision--)
    511     buf += *bp++;
    512 
    513   // trailing 0 if needed
    514   if (precision > 0)
    515     buf.append(precision, '0');
    516 
    517   // exponent size = number of digits + exponent sign + exponent symbol + trailing zero
    518   char expbuf[MAXEDIGITS + 3];
    519   //We start filling at the buffer end
    520   char *suffix = expbuf + MAXEDIGITS + 2;
    521   *suffix = 0;
    522   if (!is_zero) {
    523     int nn = decpt - 1;
    524     if (nn < 0)
    525       nn = -nn;
    526     for (; nn > 9; nn /= 10)
    527       *--suffix = (char) todigit(nn % 10);
    528     *--suffix = (char) todigit(nn);
    529   }
    530 
    531   // prepend leading zeros to exponent
    532   // C89 Standard says that it should be at least 2 digits, C99 Standard says that
    533   // we stop prepend zeros if more than 3 digits. To repect both STLport prepend zeros
    534   // until it is 2 digits.
    535   while (suffix > &expbuf[MAXEDIGITS])
    536     *--suffix = '0';
    537 
    538   // put in the exponent sign
    539   *--suffix = (char) ((decpt > 0 || is_zero ) ? '+' : '-');
    540 
    541   // put in the e
    542   *--suffix = flags & ios_base::uppercase ? 'E' : 'e';
    543 
    544   // copy the suffix
    545   buf += suffix;
    546   return __group_pos;
    547 }
    548 
    549 static size_t __format_float_fixed( __iostring &buf, const char *bp,
    550                                     int decpt, int sign,
    551                                     ios_base::fmtflags flags,
    552                                     int precision) {
    553   if ( sign && (decpt > -precision) && (*bp != 0) )
    554     buf += '-';
    555   else if ( flags & ios_base::showpos )
    556     buf += '+';
    557 
    558   // digits before decimal point
    559   int nnn = decpt;
    560   do {
    561     buf += (nnn <= 0 || *bp == 0) ? '0' : *bp++;
    562   } while ( --nnn > 0 );
    563 
    564   // start of grouping position
    565   size_t __group_pos = buf.size();
    566 
    567   // decimal point if needed
    568   if ( flags & ios_base::showpoint || precision > 0 ) {
    569     buf += '.';
    570   }
    571 
    572   // digits after decimal point if any
    573   while ( *bp != 0 && --precision >= 0 ) {
    574     buf += (++decpt <= 0) ? '0' : *bp++;
    575   }
    576 
    577   // trailing zeros if needed
    578   if (precision > 0)
    579     buf.append(precision, '0');
    580 
    581   return __group_pos;
    582 }
    583 
    584 #if defined (_STLP_USE_SIGN_HELPER)
    585 template<class _FloatT>
    586 struct float_sign_helper {
    587   float_sign_helper(_FloatT __x)
    588   { _M_number._num = __x; }
    589 
    590   bool is_negative() const {
    591     const unsigned short sign_mask(1 << (sizeof(unsigned short) * CHAR_BIT - 1));
    592     return (get_sign_word() & sign_mask) != 0;
    593   }
    594 private:
    595   union {
    596     unsigned short _Words[8];
    597     _FloatT _num;
    598   } _M_number;
    599 
    600   unsigned short get_word_higher() const _STLP_NOTHROW
    601   { return _M_number._Words[0]; }
    602   unsigned short get_word_lower() const _STLP_NOTHROW
    603   { return _M_number._Words[(sizeof(_FloatT) >= 12 ? 10 : sizeof(_FloatT)) / sizeof(unsigned short) - 1]; }
    604   unsigned short get_sign_word() const _STLP_NOTHROW
    605 #  if defined (_STLP_BIG_ENDIAN)
    606   { return get_word_higher(); }
    607 #  else /* _STLP_LITTLE_ENDIAN */
    608   { return get_word_lower(); }
    609 #  endif
    610 };
    611 #endif
    612 
    613 template <class _FloatT>
    614 static size_t __format_nan_or_inf(__iostring& buf, _FloatT x, ios_base::fmtflags flags) {
    615   static const char* inf[2] = { "inf", "Inf" };
    616   static const char* nan[2] = { "nan", "NaN" };
    617   const char** inf_or_nan;
    618 #if !defined (_STLP_USE_SIGN_HELPER)
    619   if (_Stl_is_inf(x)) {            // Infinity
    620     inf_or_nan = inf;
    621     if (_Stl_is_neg_inf(x))
    622       buf += '-';
    623     else if (flags & ios_base::showpos)
    624       buf += '+';
    625   } else {                      // NaN
    626     inf_or_nan = nan;
    627     if (_Stl_is_neg_nan(x))
    628       buf += '-';
    629     else if (flags & ios_base::showpos)
    630       buf += '+';
    631   }
    632 #else
    633   typedef numeric_limits<_FloatT> limits;
    634   if (x == limits::infinity() || x == -limits::infinity()) {
    635     inf_or_nan = inf;
    636   } else {                    // NaN
    637     inf_or_nan = nan;
    638   }
    639   float_sign_helper<_FloatT> helper(x);
    640   if (helper.is_negative())
    641     buf += '-';
    642   else if (flags & ios_base::showpos)
    643     buf += '+';
    644 #endif
    645   size_t ret = buf.size();
    646   buf += inf_or_nan[flags & ios_base::uppercase ? 1 : 0];
    647   return ret;
    648 }
    649 
    650 static inline size_t __format_float(__iostring &buf, const char * bp,
    651                                     int decpt, int sign, bool is_zero,
    652                                     ios_base::fmtflags flags,
    653                                     int precision) {
    654   size_t __group_pos = 0;
    655   switch (flags & ios_base::floatfield) {
    656     case ios_base::scientific:
    657       __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero,
    658                                                flags, precision);
    659       break;
    660     case ios_base::fixed:
    661       __group_pos = __format_float_fixed( buf, bp, decpt, sign,
    662                                           flags, precision);
    663       break;
    664     default: // g format
    665       // establish default precision
    666       if (flags & ios_base::showpoint || precision > 0) {
    667         if (precision == 0) precision = 1;
    668       } else
    669         precision = 6;
    670 
    671       // reset exponent if value is zero
    672       if (is_zero)
    673         decpt = 1;
    674 
    675       int kk = precision;
    676       if (!(flags & ios_base::showpoint)) {
    677         size_t n = strlen(bp);
    678         if (n < (size_t)kk)
    679           kk = (int)n;
    680         while (kk >= 1 && bp[kk-1] == '0')
    681           --kk;
    682       }
    683 
    684       if (decpt < -3 || decpt > precision) {
    685         precision = kk - 1;
    686         __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero,
    687                                                  flags, precision);
    688       } else {
    689         precision = kk - decpt;
    690         __group_pos = __format_float_fixed( buf, bp, decpt, sign,
    691                                             flags, precision);
    692       }
    693       break;
    694   } /* switch */
    695   return __group_pos;
    696 }
    697 
    698 #endif
    699 
    700 #if defined (USE_SPRINTF_INSTEAD) || defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
    701 struct GroupPos {
    702   bool operator () (char __c) const {
    703     return __c == '.' ||
    704            __c == 'e' || __c == 'E';
    705   }
    706 };
    707 
    708 // Creates a format string for sprintf()
    709 static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier) {
    710   fmtbuf[0] = '%';
    711   int i = 1;
    712 
    713   if (flags & ios_base::showpos)
    714     fmtbuf[i++] = '+';
    715 
    716   if (flags & ios_base::showpoint)
    717     fmtbuf[i++] = '#';
    718 
    719   fmtbuf[i++] = '.';
    720   fmtbuf[i++] = '*';
    721 
    722   if (long_modifier)
    723     fmtbuf[i++] = long_modifier;
    724 
    725   switch (flags & ios_base::floatfield)
    726     {
    727     case ios_base::scientific:
    728       fmtbuf[i++] = (flags & ios_base::uppercase) ?  'E' : 'e';
    729       break;
    730     case ios_base::fixed:
    731 #  if defined (__FreeBSD__)
    732       fmtbuf[i++] = 'f';
    733 #  else
    734       fmtbuf[i++] = (flags & ios_base::uppercase) ? 'F' : 'f';
    735 #  endif
    736       break;
    737     default:
    738       fmtbuf[i++] = (flags & ios_base::uppercase) ?  'G' : 'g';
    739       break;
    740     }
    741 
    742   fmtbuf[i] = 0;
    743 }
    744 
    745 #endif  /* USE_SPRINTF_INSTEAD */
    746 
    747 template <class _FloatT>
    748 static size_t  __write_floatT(__iostring &buf, ios_base::fmtflags flags, int precision,
    749                               _FloatT x
    750 #if defined (USE_SPRINTF_INSTEAD)
    751                               , char modifier) {
    752   /* In theory, if we want 'arbitrary' precision, we should use 'arbitrary'
    753    * buffer size below, but really we limited by exponent part in double.
    754    *    - ptr
    755    */
    756   typedef numeric_limits<_FloatT> limits;
    757   char static_buf[limits::max_exponent10 + 6]; // 6: -xxx.yyyE-zzz (sign, dot, E, exp sign, \0)
    758   char fmtbuf[32];
    759   __fill_fmtbuf(fmtbuf, flags, modifier);
    760   snprintf(_STLP_ARRAY_AND_SIZE(static_buf), fmtbuf, precision, x);
    761   buf = static_buf;
    762   return find_if(buf.begin(), buf.end(), GroupPos()) - buf.begin();
    763 #else
    764                               ) {
    765   typedef numeric_limits<_FloatT> limits;
    766   //If numeric_limits support is correct we use the exposed values to detect NaN and infinity:
    767   if (limits::has_infinity && limits::has_quiet_NaN) {
    768     if (!(x == x) || // NaN check
    769         (x == limits::infinity() || x == -limits::infinity())) {
    770       return __format_nan_or_inf(buf, x, flags);
    771     }
    772   }
    773   // numeric_limits support is not good enough, we rely on platform dependent function
    774   // _Stl_is_nan_or_inf that do not support long double.
    775   else if (_Stl_is_nan_or_inf(x)) {
    776     return __format_nan_or_inf(buf, x, flags);
    777   }
    778 #  if defined (__MINGW32__)
    779   //For the moment MinGW is limited to display at most numeric_limits<double>::max()
    780   if (x > numeric_limits<double>::max() ||
    781       x < -numeric_limits<double>::max()) {
    782     return __format_nan_or_inf(buf, x, flags);
    783   }
    784 #  endif
    785 
    786   /* Buffer size is max number of digits which is the addition of:
    787    * - max_exponent10: max number of digits in fixed mode
    788    * - digits10 + 2: max number of significant digits
    789    * - trailing '\0'
    790    */
    791   char cvtbuf[limits::max_exponent10 + limits::digits10 + 2 + 1];
    792   char *bp;
    793   int decpt, sign;
    794 
    795   switch (flags & ios_base::floatfield) {
    796   case ios_base::fixed:
    797     {
    798       /* Here, number of digits represents digits _after_ decimal point.
    799        * In order to limit static buffer size we have to give 2 different values depending on x value.
    800        * For small values (abs(x) < 1) we need as many digits as requested by precision limited by the maximum number of digits
    801        * which is min_exponent10 + digits10 + 2
    802        * For bigger values we won't have more than limits::digits10 + 2 digits after decimal point. */
    803       int digits10 = (x > -1.0 && x < 1.0 ? -limits::min_exponent10 + limits::digits10 + 2
    804                                           : limits::digits10 + 2);
    805       bp = _Stl_fcvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) );
    806     }
    807     break;
    808   case ios_base::scientific:
    809   default:
    810     /* Here, number of digits is total number of digits which is limited to digits10 + 2. */
    811     {
    812       int digits10 = limits::digits10 + 2;
    813       bp = _Stl_ecvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) );
    814     }
    815     break;
    816   }
    817   return __format_float(buf, bp, decpt, sign, x == 0.0, flags, precision);
    818 #endif
    819 }
    820 
    821 size_t  _STLP_CALL
    822 __write_float(__iostring &buf, ios_base::fmtflags flags, int precision,
    823               double x) {
    824   return __write_floatT(buf, flags, precision, x
    825 #if defined (USE_SPRINTF_INSTEAD)
    826                                                , 0
    827 #endif
    828                                                   );
    829 }
    830 
    831 #if !defined (_STLP_NO_LONG_DOUBLE)
    832 size_t _STLP_CALL
    833 __write_float(__iostring &buf, ios_base::fmtflags flags, int precision,
    834               long double x) {
    835   return __write_floatT(buf, flags, precision, x
    836 #if defined (USE_SPRINTF_INSTEAD)
    837                                                , 'L'
    838 #endif
    839                                                     );
    840 }
    841 #endif
    842 
    843 void _STLP_CALL __get_floor_digits(__iostring &out, _STLP_LONGEST_FLOAT_TYPE __x) {
    844   typedef numeric_limits<_STLP_LONGEST_FLOAT_TYPE> limits;
    845 #if defined (USE_SPRINTF_INSTEAD)
    846   char cvtbuf[limits::max_exponent10 + 6];
    847 #  if !defined (_STLP_NO_LONG_DOUBLE)
    848   snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%Lf", __x); // check for 1234.56!
    849 #  else
    850   snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%f", __x);  // check for 1234.56!
    851 #  endif
    852   char *p = strchr( cvtbuf, '.' );
    853   if ( p == 0 ) {
    854     out.append( cvtbuf );
    855   } else {
    856     out.append( cvtbuf, p );
    857   }
    858 #else
    859   char cvtbuf[limits::max_exponent10 + 1];
    860   char * bp;
    861   int decpt, sign;
    862   bp = _Stl_fcvtR(__x, 0, &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf));
    863 
    864   if (sign) {
    865     out += '-';
    866   }
    867   out.append(bp, bp + decpt);
    868 #endif
    869 }
    870 
    871 
    872 #if !defined (_STLP_NO_WCHAR_T)
    873 void _STLP_CALL __convert_float_buffer( __iostring const& str, __iowstring &out,
    874                                         const ctype<wchar_t>& ct, wchar_t dot, bool __check_dot) {
    875   string::const_iterator str_ite(str.begin()), str_end(str.end());
    876 
    877   //First loop, check the dot char
    878   if (__check_dot) {
    879     while (str_ite != str_end) {
    880       if (*str_ite != '.') {
    881         out += ct.widen(*str_ite++);
    882       } else {
    883         out += dot;
    884         break;
    885       }
    886     }
    887   } else {
    888     if (str_ite != str_end) {
    889       out += ct.widen(*str_ite);
    890     }
    891   }
    892 
    893   if (str_ite != str_end) {
    894     //Second loop, dot has been found, no check anymore
    895     while (++str_ite != str_end) {
    896       out += ct.widen(*str_ite);
    897     }
    898   }
    899 }
    900 
    901 #endif
    902 
    903 void _STLP_CALL
    904 __adjust_float_buffer(__iostring &str, char dot) {
    905   if ('.' != dot) {
    906     size_t __dot_pos = str.find('.');
    907     if (__dot_pos != string::npos) {
    908       str[__dot_pos] = dot;
    909     }
    910   }
    911 }
    912 
    913 _STLP_MOVE_TO_STD_NAMESPACE
    914 _STLP_END_NAMESPACE
    915 
    916 // Local Variables:
    917 // mode:C++
    918 // End:
    919