home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / stlpt453.zip / STLport-4.5.3 / src / num_put_float.cpp < prev    next >
C/C++ Source or Header  |  2002-01-18  |  25KB  |  716 lines

  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. # ifdef __DECCXX
  22. #define NDIG 400
  23. # else
  24. #define NDIG 82
  25. # endif
  26.  
  27. # ifdef _STLP_NO_LONG_DOUBLE
  28. #  define MAXECVT 17
  29. #  define MAXFCVT 18
  30. typedef double max_double_type;
  31. # else
  32. #  define MAXECVT 35
  33. #  define MAXFCVT 36
  34. typedef long double max_double_type;
  35. # endif
  36.  
  37. #define MAXFSIG MAXECVT
  38. #define MAXESIZ 5
  39.  
  40. #define todigit(x) ((x)+'0')
  41.  
  42. # include <stl/_config.h>
  43.  
  44. # ifdef _STLP_UNIX
  45.  
  46. # if defined (__sun) 
  47. #  include <floatingpoint.h>
  48. # endif
  49.  
  50. //# if !(defined(_STLP_USE_GLIBC) || defined(__FreeBSD__) || defined(__NetBSD__) || defined (_AIX) || defined(__MVS__) || defined (__OS400__) || defined (__QNXNTO__) || defined (__APPLE__) || defined (__DJGPP))
  51. # if defined (__sun) || defined (__digital__) || defined (__sgi) || defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
  52. // DEC, SGI & Solaris need this
  53. #  include <values.h>
  54. #  include <nan.h>
  55. # endif
  56.  
  57. # if defined (__QNXNTO__) || ( defined(__GNUC__) && defined(__APPLE__) )
  58. #  define USE_SPRINTF_INSTEAD
  59. # endif
  60.  
  61. #  if defined( _AIX ) // JFA 3-Aug-2000
  62. #    include <math.h>
  63. #    include <float.h>
  64. #  endif
  65.  
  66. # endif
  67.  
  68. # include <cstdlib>
  69.  
  70. #if defined (_MSC_VER) || defined (__MINGW32__) || defined (__BORLANDC__) || defined (__DJGPP)  || defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
  71. # include <float.h>
  72. #endif
  73.  
  74. #if defined(__MRC__) || defined(__SC__)        //*TY 02/24/2000 - added support for MPW
  75. # include <fp.h>
  76. #endif
  77.  
  78. #include <cmath>
  79.  
  80. #if defined( __MSL__ )
  81. # include <cstdlib>    // for atoi
  82. # include <cstdio>    // for snprintf
  83. # include <algorithm>
  84. # include <cassert>
  85. #endif
  86.  
  87. #if defined (__ISCPP__)
  88. # include <cfloat>
  89. #endif
  90.  
  91.  
  92. # include "num_put.h"
  93. # include <algorithm>
  94.  
  95.  
  96. #if defined(__hpux) && !defined(_INCLUDE_HPUX_SOURCE)
  97.      extern "C" double erf(double);
  98.      extern "C" double erfc(double);
  99.      extern "C" double gamma(double);                             /* obsolescent */
  100.      extern "C" double hypot(double, double);
  101.      extern "C" int    isnan(double);
  102.      extern "C" double j0(double);
  103.      extern "C" double j1(double);
  104.      extern "C" double jn(int, double);
  105.      extern "C" double lgamma(double);
  106.      extern "C" double y0(double);
  107.      extern "C" double y1(double);
  108.      extern "C" double yn(int, double);
  109.  
  110. #  define HUGE_VALF     _SINFINITY
  111. #  define INFINITY      _SINFINITY
  112. #  define NAN           _SQNAN
  113.  
  114. #  define isnan(x)              _ISNAN(x)
  115. #  define isinf(x)              _ISINF(x)
  116. #  define signbit(x)            _SIGNBIT(x)
  117. #  define isfinite(x)           _ISFINITE(x)
  118. #  define isnormal(x)           _ISNORMAL(x)
  119. #  define fpclassify(x)         _FPCLASSIFY(x)
  120. #  define isunordered(x,y)      _ISUNORDERED(x,y)
  121. #  define isgreater(x,y)        _ISGREATER(x,y)
  122. #  define isgreaterequal(x,y)   _ISGREATEREQUAL(x,y)
  123. #  define isless(x,y)           _ISLESS(x,y)
  124. #  define islessequal(x,y)      _ISLESSEQUAL(x,y)
  125. #  define islessgreater(x,y)    _ISLESSGREATER(x,y)
  126.  
  127. #  define FP_NORMAL     0
  128. #  define FP_ZERO       1
  129. #  define FP_INFINITE   2
  130. #  define FP_SUBNORMAL  3
  131. #  define FP_NAN        4
  132.  
  133. #  define DECIMAL_DIG   17
  134.  
  135. #  define _IS64(x) (sizeof(x)==sizeof(double))
  136. #  define _IS32(x) (sizeof(x)==sizeof(float))
  137.  
  138. extern "C" {
  139.      extern double copysign(double, double);
  140.      extern const float _SINFINITY;
  141.      extern const float _SQNAN;
  142. #    ifdef _PA_RISC
  143. #      define _ISNAN(x)          (_IS32(x)?_Isnanf(x):(isnan)(x))
  144. #      define _ISINF(x)          (_IS32(x)?_Isinff(x):_Isinf(x))
  145. #      define _SIGNBIT(x)        (_IS32(x)?_Signbitf(x):_Signbit(x))
  146. #      define _ISFINITE(x)       (_IS32(x)?_Isfinitef(x):_Isfinite(x))
  147. #      define _ISNORMAL(x)       (_IS32(x)?_Isnormalf(x):_Isnormal(x))
  148. #      define _FPCLASSIFY(x)     (_IS32(x)?_Fpclassifyf(x)>>1:_Fpclassify(x)>>1)
  149. #      define _ISUNORDERED(x,y)  (_IS32(x)&&_IS32(y)?_Isunorderedf(x,y):_Isunordered(x,y))
  150.        extern int _Signbit(double);
  151.        extern int _Signbitf(float);
  152.        extern int _Isnanf(float);
  153.        extern int _Isfinite(double);
  154.        extern int _Isfinitef(float);
  155.        extern int _Isinf(double);
  156.        extern int _Isinff(float);
  157.        extern int _Isnormal(double);
  158.        extern int _Isnormalf(float);
  159.        extern int _Isunordered(double, double);
  160.        extern int _Isunorderedf(float, float);
  161.        extern int _Fpclassify(double);
  162.        extern int _Fpclassifyf(float);
  163. #    else
  164. #      include "math_ia64_internal.h"
  165. #      define _FPCLASSIFY(x)     (_IS32(x)?_Fpclassf(x):_Fpclass(x))
  166.        extern int _Fpclass(double);
  167.        extern int _Fpclassf(float);
  168. #    endif
  169. }
  170.  
  171. #ifndef _INCLUDE_XOPEN_SOURCE_EXTENDED
  172. extern "C" char *fcvt(double, int, int *, int *);
  173. extern "C" char *ecvt(double, int, int *, int *);
  174. #endif
  175. #ifndef _INCLUDE_HPUX_SOURCE
  176. #  ifndef _LONG_DOUBLE
  177. #    define _LONG_DOUBLE
  178.      typedef struct {
  179.        uint32_t word1, word2, word3, word4;
  180.      } long_double;
  181. #  endif /* _LONG_DOUBLE */
  182. extern "C" char *_ldecvt(long_double, int, int *, int *);
  183. extern "C" char *_ldfcvt(long_double, int, int *, int *);
  184.  
  185. #endif
  186.  
  187. #endif /* __hpux */
  188.  
  189. _STLP_BEGIN_NAMESPACE
  190.  
  191. #if defined (__MWERKS__) || defined(__BEOS__)
  192. #  define USE_SPRINTF_INSTEAD
  193. #endif
  194.  
  195. # if defined (_AIX)
  196. // Some OS'es only provide non-reentrant primitives, so we have to use additional synchronization here
  197. # ifdef _REENTRANT
  198. static _STLP_STATIC_MUTEX __put_float_mutex _STLP_MUTEX_INITIALIZER;
  199. # define LOCK_CVT _STLP_auto_lock lock(__put_float_mutex);
  200. # define RETURN_CVT(ecvt, x, n, pt, sign, buf) strcpy(buf, ecvt(x, n, pt, sign)); return buf;
  201. # else
  202. # define LOCK_CVT
  203. # define RETURN_CVT(ecvt, x, n, pt, sign, buf) return ecvt(x, n, pt, sign);
  204. # endif
  205. # endif
  206.  
  207. // Tests for infinity and NaN differ on different OSs.  We encapsulate
  208. // these differences here.
  209.  
  210. #ifdef USE_SPRINTF_INSTEAD
  211.  
  212. #elif defined (__hpux) || defined (__DJGPP) || ( defined(_STLP_USE_GLIBC) && ! defined (__MSL__) )
  213. #  if defined (isfinite) 
  214. inline bool _Stl_is_nan_or_inf(double x) { return !isfinite(x); }
  215. #  else
  216. inline bool _Stl_is_nan_or_inf(double x) { return !finite(x); }
  217. #  endif
  218. inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && ( copysign(1., x) < 0 ); }
  219. inline bool _Stl_is_inf(double x)        { return isinf(x); }
  220. // inline bool _Stl_is_neg_inf(double x)    { return isinf(x) < 0; }  
  221. inline bool _Stl_is_neg_inf(double x)    { return isinf(x) && x < 0; }
  222. #elif defined(__unix) && !defined(__FreeBSD__)  && !defined(__NetBSD__) \
  223.       && !defined(__APPLE__)  && !defined(__DJGPP) && !defined(__osf__)
  224. inline bool _Stl_is_nan_or_inf(double x) { return IsNANorINF(x); }
  225. inline bool _Stl_is_inf(double x)        { return IsNANorINF(x) && IsINF(x); }
  226. inline bool _Stl_is_neg_inf(double x)    { return (IsINF(x)) && (x < 0.0); }
  227. inline bool _Stl_is_neg_nan(double x)    { return IsNegNAN(x); }
  228. # elif defined (__BORLANDC__) && ( __BORLANDC__ < 0x540 )
  229. inline bool _Stl_is_nan_or_inf(double x) {  return !_finite(x); }
  230. inline bool _Stl_is_inf(double x)        {  return _Stl_is_nan_or_inf(x) && ! _isnan(x);}
  231. inline bool _Stl_is_neg_inf(double x)    {  return _Stl_is_inf(x) && x < 0 ; }
  232. inline bool _Stl_is_neg_nan(double x)    { return _isnan(x) && x < 0 ; } 
  233. #elif defined (_MSC_VER) || defined (__MINGW32__) || defined (__BORLANDC__)
  234. inline bool _Stl_is_nan_or_inf(double x) { return !_finite(x); }
  235. inline bool _Stl_is_inf(double x)        { 
  236.   int fclass = _fpclass(x); 
  237.   return fclass == _FPCLASS_NINF || fclass == _FPCLASS_PINF; 
  238. }
  239. inline bool _Stl_is_neg_inf(double x)    { return _fpclass(x) == _FPCLASS_NINF; }
  240. inline bool _Stl_is_neg_nan(double x)    { return _isnan(x) && _copysign(1., x) < 0 ; } 
  241. #elif defined(__MRC__) || defined(__SC__)        //*TY 02/24/2000 - added support for MPW
  242. bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !isfinite(x); }
  243. bool _Stl_is_inf(double x)        { return !isfinite(x); }
  244. bool _Stl_is_neg_inf(double x)    { return !isfinite(x) && signbit(x); }
  245. bool _Stl_is_neg_nan(double x)    { return isnan(x) && signbit(x); }
  246. #elif /* defined (__FreeBSD__) */ ( defined (__GNUC__) && defined (__APPLE__) )
  247. inline bool _Stl_is_nan_or_inf(double x) { return !finite(x); }
  248. inline bool _Stl_is_inf(double x)        {   return _Stl_is_nan_or_inf(x) && ! isnan(x); }
  249. inline bool _Stl_is_neg_inf(double x)    {   return _Stl_is_inf(x) && x < 0 ; }
  250. inline bool _Stl_is_neg_nan(double x)    { return isnan(x) && copysign(1., x) < 0 ; } 
  251. #elif defined( _AIX ) // JFA 11-Aug-2000
  252. bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !finite(x); }
  253. bool _Stl_is_inf(double x)        { return !finite(x); }
  254. // bool _Stl_is_neg_inf(double x)    { return _class(x) == FP_MINUS_INF; }
  255. bool _Stl_is_neg_inf(double x)    { return _Stl_is_inf(x) && ( copysign(1., x) < 0 );  }
  256. bool _Stl_is_neg_nan(double x)    { return isnan(x) && ( copysign(1., x) < 0 );  }
  257. #elif defined (__ISCPP__)
  258. inline bool _Stl_is_nan_or_inf  (double x) { return _fp_isINF(x) || _fp_isNAN(x); }
  259. inline bool _Stl_is_inf         (double x) { return _fp_isINF(x); }
  260. inline bool _Stl_is_neg_inf     (double x) { return _fp_isINF(x) && x < 0; }
  261. inline bool _Stl_is_neg_nan     (double x) { return _fp_isNAN(x) && x < 0; }
  262. #elif ! defined (USE_SPRINTF_INSTEAD)
  263. # define USE_SPRINTF_INSTEAD
  264. #endif
  265.  
  266.  
  267. # ifndef  USE_SPRINTF_INSTEAD
  268. // Reentrant versions of floating-point conversion functions.  The argument
  269. // lists look slightly different on different operating systems, so we're
  270. // encapsulating the differences here.
  271.  
  272. #if defined (__CYGWIN__) || defined(__DJGPP)
  273.   inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  274.     { return ecvtbuf(x, n, pt, sign, buf); }
  275.   inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  276.     { return fcvtbuf(x, n, pt, sign, buf); }
  277. # ifndef _STLP_NO_LONG_DOUBLE
  278.   inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  279.     { return ecvtbuf(x, n, pt, sign, buf); }
  280.   inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  281.     { return fcvtbuf(x, n, pt, sign, buf); }
  282. # endif
  283. #elif defined (_STLP_USE_GLIBC)
  284.   inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  285.     { return buf + ecvt_r(x, n, pt, sign, buf, NDIG+2); }
  286.   inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  287.     { return buf + fcvt_r(x, n, pt, sign, buf, NDIG+2); }
  288. #  ifndef _STLP_NO_LONG_DOUBLE
  289.   inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  290.     { return buf + qecvt_r(x, n, pt, sign, buf, NDIG+2); }
  291.   inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  292.     { return buf + qfcvt_r(x, n, pt, sign, buf, NDIG+2); }
  293. #  endif
  294. #elif defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
  295.   inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  296.     { return ecvt(x, n, pt, sign); }
  297.   inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  298.     { return fcvt(x, n, pt, sign); }
  299. #  ifndef _STLP_NO_LONG_DOUBLE
  300.   inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  301.     { return ecvtl(x, n, pt, sign); }
  302.   inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  303.     { return fcvtl(x, n, pt, sign); }
  304. #  endif
  305. #elif defined (__sun)
  306.   inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  307.     { return econvert(x, n, pt, sign, buf); }
  308.   inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  309.     { return fconvert(x, n, pt, sign, buf); }
  310. #  ifndef _STLP_NO_LONG_DOUBLE
  311.   inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  312.     { return qeconvert(&x, n, pt, sign, buf); }
  313.   inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  314.     { return qfconvert(&x, n, pt, sign, buf); }
  315. #  endif
  316. #elif defined (__DECCXX) 
  317.   inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  318.     { return (ecvt_r(x, n, pt, sign, buf, NDIG)==0 ? buf : 0); }
  319.   inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  320.     { return (fcvt_r(x, n, pt, sign, buf, NDIG)==0 ? buf : 0); }
  321. #  ifndef _STLP_NO_LONG_DOUBLE
  322. // fbp : no "long double" conversions !
  323.   inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  324.     { return (ecvt_r((double)x, n, pt, sign, buf, NDIG)==0 ? buf : 0) ; }
  325.   inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  326.     { return (fcvt_r((double)x, n, pt, sign, buf, NDIG)==0 ? buf : 0); }
  327. #  endif
  328. #elif defined (__hpux)
  329.    inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  330.      { return ecvt(x, n, pt, sign); }
  331.    inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  332.      { return fcvt(x, n, pt, sign); }
  333. # ifndef _STLP_NO_LONG_DOUBLE
  334.  
  335. #  if defined( _REENTRANT ) && (defined(_PTHREADS_DRAFT4) || defined(PTHREAD_THREADS_MAX))
  336.    inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  337.      { return (_ldecvt_r(*(long_double*)&x, n, pt, sign, buf, NDIG+2)==0 ? buf : 0); }
  338.    inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  339.      { return (_ldfcvt_r(*(long_double*)&x, n, pt, sign, buf, NDIG+2)==0 ? buf : 0); }
  340. #  else
  341.    inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  342.      { return _ldecvt(*(long_double*)&x, n, pt, sign); }
  343.    inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  344.      { return _ldfcvt(*(long_double*)&x, n, pt, sign); }
  345. #  endif
  346. # endif
  347. #elif defined (_AIX)
  348.   inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  349.     { LOCK_CVT RETURN_CVT(ecvt, x, n, pt, sign, buf) }
  350.   inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  351.     { LOCK_CVT RETURN_CVT(fcvt, x, n, pt, sign, buf) }
  352. # ifndef _STLP_NO_LONG_DOUBLE
  353.   inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  354.     { LOCK_CVT RETURN_CVT(ecvt, x, n, pt, sign, buf) }
  355.   inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  356.     { LOCK_CVT RETURN_CVT(fcvt, x, n, pt, sign, buf) }
  357. # endif
  358. #elif defined (__unix)  && !defined(__FreeBSD__)  && !defined(__NetBSD__) && !defined(__APPLE__)
  359.   inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  360.     { return ecvt_r(x, n, pt, sign, buf); }
  361.   inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  362.     { return fcvt_r(x, n, pt, sign, buf); }
  363. # ifndef _STLP_NO_LONG_DOUBLE
  364.   inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  365.     { return qecvt_r(x, n, pt, sign, buf); }
  366.   inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  367.     { return qfcvt_r(x, n, pt, sign, buf); }
  368. #  endif
  369. #elif defined (_MSC_VER) || defined (__MINGW32__) || defined (__BORLANDC__)
  370. // those guys claim _cvt functions being reentrant.
  371. inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) {  return _ecvt(x, n, pt, sign); }
  372. inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) { return _fcvt(x, n, pt, sign); }
  373. # ifndef _STLP_NO_LONG_DOUBLE
  374. inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf) { return _ecvt((double)x, n, pt, sign); }
  375. inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf) { return _fcvt((double)x, n, pt, sign); }
  376. # endif
  377. #elif defined (__ISCPP__)
  378. inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
  379. { return _fp_ecvt( x, n, pt, sign, buf); }
  380.  
  381. inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
  382. { return _fp_fcvt(x, n, pt, sign, buf); }
  383.  
  384. # ifndef _STLP_NO_LONG_DOUBLE
  385. inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* buf)
  386. { return _fp_ecvt( x, n, pt, sign, buf); }
  387.  
  388. inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* buf)
  389. { return _fp_fcvt(x, n, pt, sign, buf); }
  390. # endif
  391. #elif defined (__MRC__) || defined(__SC__)
  392. inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* )
  393. { return ecvt( x, n, pt, sign ); }
  394. inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* )
  395. { return fcvt(x, n, pt, sign); }
  396. #ifndef _STLP_NO_LONG_DOUBLE
  397. inline char* _Stl_qecvtR(long double x, int n, int* pt, int* sign, char* )
  398. { return ecvt( x, n, pt, sign ); }
  399. inline char* _Stl_qfcvtR(long double x, int n, int* pt, int* sign, char* )
  400. { return fcvt(x, n, pt, sign); }
  401. #endif
  402. #endif
  403.  
  404.  
  405. //----------------------------------------------------------------------
  406. // num_put
  407.  
  408. // Helper functions for _M_do_put_float
  409.  
  410. // __format_float formats a mantissa and exponent as returned by
  411. // one of the conversion functions (ecvt_r, fcvt_r, qecvt_r, qfcvt_r)
  412. // according to the specified precision and format flags.  This is
  413. // based on doprnt but is much simpler since it is concerned only
  414. // with floating point input and does not consider all formats.  It
  415. // also does not deal with blank padding, which is handled by
  416. // __copy_float_and_fill. 
  417.  
  418. void __format_float_scientific(char * buf, const char * bp, 
  419.                    int decpt, int sign, bool is_zero,
  420.                    ios_base::fmtflags flags,
  421.                    int precision, bool /* islong */)
  422. {
  423.   char * suffix;
  424.   char expbuf[MAXESIZ + 2];
  425.   // sign if required
  426.   if (sign)
  427.     *buf++ = '-';
  428.   else if (flags & ios_base::showpos)
  429.     *buf++ = '+';
  430.   
  431.   // first digit of mantissa
  432.   *buf++ = *bp++;
  433.  
  434.   // decimal point if required
  435.   if (precision != 0 || flags & ios_base::showpoint)
  436.     *buf++ = '.';
  437.   // rest of mantissa
  438.   int rz = precision;
  439.   while (rz-- > 0 && *bp != 0)
  440.     *buf++ = *bp++;
  441.  
  442.   // exponent
  443.   *(suffix = &expbuf[MAXESIZ]) = 0;
  444.   if (!is_zero) {
  445.     int nn = decpt - 1;
  446.     if (nn < 0)
  447.       nn = -nn;
  448.     for (; nn > 9; nn /= 10)
  449.       *--suffix = (char) todigit(nn % 10);
  450.     *--suffix = (char) todigit(nn);
  451.   }
  452.       
  453.   // prepend leading zeros to exponent
  454.   while (suffix > &expbuf[MAXESIZ - 2])
  455.     *--suffix = '0';
  456.   
  457.   // put in the exponent sign
  458.   *--suffix = (char) ((decpt > 0 || is_zero ) ? '+' : '-');
  459.   
  460.   // put in the e
  461.   *--suffix = flags & ios_base::uppercase ? 'E' : 'e';
  462.  
  463.   // copy the suffix
  464.   strcpy(buf, suffix);
  465. }
  466.   
  467. void __format_float_fixed(char * buf, const char * bp, 
  468.               int decpt, int sign, bool /* x */,
  469.               ios_base::fmtflags flags,
  470.               int precision, bool islong )
  471. {
  472.   if (sign && decpt > -precision && *bp != 0)
  473.     *buf++ = '-';
  474.   else if (flags & ios_base::showpos)
  475.     *buf++ = '+';
  476.   
  477.   int rzero   = 0;
  478.   int nn      = decpt;
  479.   int k       = 0;
  480.   int maxfsig = islong ? 2*MAXFSIG : MAXFSIG;
  481.  
  482.   do {
  483.     *buf++ = (char) ((nn <= 0 || *bp == 0 || k >= maxfsig) ?
  484.       '0' : (k++, *bp++));
  485.   } while (--nn > 0);
  486.  
  487.   // decimal point if needed
  488.   if (flags & ios_base::showpoint || precision > 0)
  489.     *buf++ = '.';
  490.  
  491.   // digits after decimal point if any
  492.   nn = (min) (precision, MAXFCVT);
  493.   if (precision > nn)
  494.     rzero = precision - nn;
  495.   while (--nn >= 0)
  496.     *buf++ = (++decpt <= 0 || *bp == '\0' || k >= maxfsig)
  497.               ? '0' : (k++, *bp++);
  498.  
  499.   // trailing zeros if needed
  500.   while (rzero-- > 0)
  501.     *buf++ = '0';
  502.   *buf++ = '\0';
  503. }
  504.  
  505.  
  506. void __format_nan_or_inf(char * buf, double x,
  507.              ios_base::fmtflags flags)
  508. {
  509.   static const char* inf[2] = { "inf", "Inf" };
  510.   static const char* nan[2] = { "nan", "NaN" };
  511.   const char** inf_or_nan = 0;
  512.   if (_Stl_is_inf((double)x)) {            // Infinity
  513.     inf_or_nan = inf;
  514.     if (_Stl_is_neg_inf((double)x))
  515.       *buf++ = '-';
  516.     else if (flags & ios_base::showpos)
  517.       *buf++ = '+';
  518.   }
  519.   else {                      // NaN
  520.     inf_or_nan = nan;
  521.     if (_Stl_is_neg_nan((double)x))
  522.       *buf++ = '-';
  523.     else if (flags & ios_base::showpos)
  524.       *buf++ = '+';
  525.   }
  526.   strcpy(buf, flags & ios_base::uppercase ? inf_or_nan[1] : inf_or_nan[0]);  
  527. }
  528.  
  529. template <class max_double_type>
  530. static inline 
  531. void __format_float(char * buf, const char * bp, 
  532.                     int decpt, int sign, max_double_type x,
  533.                     ios_base::fmtflags flags,
  534.                     int precision, bool islong)
  535. {
  536.   // Output of infinities and NANs does not depend on the format flags
  537.   if (_Stl_is_nan_or_inf((double)x)) {       // Infinity or NaN
  538.     __format_nan_or_inf(buf, x, flags);
  539.   } 
  540.   else {                        // representable number
  541.     switch (flags & ios_base::floatfield) {
  542.     case ios_base::scientific:
  543.       __format_float_scientific(buf, bp, decpt, sign, x == 0.0, flags,
  544.                                 precision, islong);
  545.       break;
  546.       
  547.     case ios_base::fixed:
  548.       __format_float_fixed(buf, bp, decpt, sign, true, flags,
  549.                            precision, islong);
  550.       break;
  551.       
  552.     default: // g format
  553.       // establish default precision
  554.       if (flags & ios_base::showpoint || precision > 0) {
  555.         if (precision == 0) precision = 1;
  556.       }
  557.       else
  558.         precision = 6;
  559.       
  560.       // reset exponent if value is zero
  561.       if (x == 0)
  562.         decpt = 1;
  563.       
  564.       int kk = precision;
  565.       if (!(flags & ios_base::showpoint)) {
  566.         size_t n = strlen(bp);
  567.         if (n < kk)
  568.           kk = (int)n;
  569.         while (kk >= 1 && bp[kk-1] == '0')
  570.           --kk;
  571.       }
  572.       
  573.       if (decpt < -3 || decpt > precision) {
  574.         precision = kk - 1;
  575.         __format_float_scientific(buf, bp, decpt, sign, x == 0,
  576.                                   flags, precision, islong);
  577.       }
  578.       else {
  579.         precision = kk - decpt;
  580.         __format_float_fixed(buf, bp, decpt, sign, true,
  581.                              flags, precision, islong);
  582.       }
  583.       break;
  584.     } /* switch */
  585.   } /* else */
  586. }
  587.  
  588. # else
  589. // Creates a format string for sprintf()
  590. static int fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier)
  591. {
  592.   fmtbuf[0] = '%';
  593.   int i = 1;
  594.  
  595.   if (flags & ios_base::showpos)
  596.     fmtbuf[i++] = '+';
  597.  
  598.   if (flags & ios_base::showpoint)
  599.     fmtbuf[i++] = '#';
  600.  
  601.   fmtbuf[i++] = '.';
  602.   fmtbuf[i++] = '*';
  603.   
  604.   if (long_modifier)
  605.     fmtbuf[i++] = long_modifier;
  606.  
  607.   switch (flags & ios_base::floatfield)
  608.     {
  609.     case ios_base::scientific:
  610.       fmtbuf[i++] = (flags & ios_base::uppercase) ?  'E' : 'e';      
  611.       break;
  612.     case ios_base::fixed:
  613.       fmtbuf[i++] = (flags & ios_base::uppercase) ?  'F' : 'f';      
  614.       break;
  615.     default:
  616.       fmtbuf[i++] = (flags & ios_base::uppercase) ?  'G' : 'g';      
  617.       break;
  618.     }
  619.  
  620.   fmtbuf[i] = 0;
  621.   return i;
  622. }
  623. # endif  /* USE_SPRINTF_INSTEAD */
  624.  
  625.  
  626. char*  _STLP_CALL
  627. __write_float(char* buf, ios_base::fmtflags flags, int precision,
  628.               double x)
  629. {
  630. # ifdef USE_SPRINTF_INSTEAD
  631.   char fmtbuf[32];
  632.   fill_fmtbuf(fmtbuf, flags, 0);
  633.   sprintf(buf, fmtbuf, precision, x);    
  634.   // we should be able to return buf + sprintf(), but we do not trust'em...
  635.   return buf + strlen(buf);
  636. # else
  637.   char cvtbuf[NDIG+2];
  638.   char * bp;
  639.   int decpt, sign;
  640.  
  641.   switch (flags & ios_base::floatfield) {
  642.   case ios_base::fixed:
  643.     bp = _Stl_fcvtR(x, (min) (precision, MAXFCVT), &decpt, &sign, cvtbuf);
  644.     break;
  645.   case ios_base::scientific :
  646.     bp = _Stl_ecvtR(x, (min) (precision + 1, MAXECVT), &decpt, &sign, cvtbuf);
  647.     break;
  648.   default :
  649.     bp = _Stl_ecvtR(x, (min) (precision, MAXECVT), &decpt, &sign, cvtbuf);
  650.     break;
  651.   }
  652.   __format_float(buf, bp, decpt, sign, x, flags, precision, false);
  653.   return buf + strlen(buf);
  654. # endif
  655.  
  656. }
  657.  
  658. # ifndef _STLP_NO_LONG_DOUBLE
  659. char*  _STLP_CALL
  660. __write_float(char* buf, ios_base::fmtflags flags, int precision,
  661.               long double x)
  662. {
  663. # ifdef USE_SPRINTF_INSTEAD
  664.   char fmtbuf[64];
  665.   int i = fill_fmtbuf(fmtbuf, flags, 'L');
  666.   sprintf(buf, fmtbuf, precision, x);    
  667.   // we should be able to return buf + sprintf(), but we do not trust'em...
  668.   return buf + strlen(buf);
  669. # else
  670.   char cvtbuf[NDIG+2];
  671.   char * bp;
  672.   int decpt, sign;
  673.  
  674.   switch (flags & ios_base::floatfield) {
  675.   case ios_base::fixed:
  676.     bp = _Stl_qfcvtR(x, (min) (precision, MAXFCVT), &decpt, &sign, cvtbuf);
  677.     break;
  678.   case ios_base::scientific :
  679.     bp = _Stl_qecvtR(x, (min) (precision + 1, MAXECVT),     &decpt, &sign, cvtbuf);
  680.     break;
  681.   default :
  682.     bp = _Stl_qecvtR(x, (min) (precision, MAXECVT), &decpt, &sign, cvtbuf);
  683.     break;
  684.   }
  685.   __format_float(buf, bp, decpt, sign, x, flags, precision, true);
  686.   return buf + strlen(buf);
  687. # endif
  688. }
  689. # endif
  690.  
  691.  
  692. # ifndef _STLP_NO_WCHAR_T
  693.  
  694. wchar_t* _STLP_CALL
  695. __convert_float_buffer(const char* first, const char* last, wchar_t* out,
  696.                        const ctype<wchar_t>& ct, wchar_t dot)
  697. {
  698.   ct.widen(first, last, out);
  699.   replace(out, out + (last - first), ct.widen('.'), dot);
  700.   return out + (last - first);
  701. }
  702.  
  703. # endif
  704.  
  705. void _STLP_CALL
  706. __adjust_float_buffer(char* first, char* last, char dot)
  707. {
  708.   replace(first, last, '.', dot);
  709. }
  710.  
  711. _STLP_END_NAMESPACE
  712.  
  713. // Local Variables:
  714. // mode:C++
  715. // End:
  716.