/home/ntakagi/work/STLport-5.1.5/src/num_get_float.cppGo to the documentation of this file.00001 /* 00002 * Copyright (c) 1999 00003 * Silicon Graphics Computer Systems, Inc. 00004 * 00005 * Copyright (c) 1999 00006 * Boris Fomitchev 00007 * 00008 * This material is provided "as is", with absolutely no warranty expressed 00009 * or implied. Any use is at your own risk. 00010 * 00011 * Permission to use or copy this software for any purpose is hereby granted 00012 * without fee, provided the above notices are retained on all copies. 00013 * Permission to modify the code and to distribute modified code is granted, 00014 * provided the above notices are retained, and a notice that the code was 00015 * modified is included with the above copyright notice. 00016 * 00017 */ 00018 00019 #include "stlport_prefix.h" 00020 00021 #include <limits> 00022 #include <locale> 00023 #include <istream> 00024 00025 #if defined (__GNUC__) && !defined (__sun) || \ 00026 defined (__DMC__) 00027 # include <stdint.h> 00028 #endif 00029 00030 #if defined (__linux__) 00031 # include <ieee754.h> 00032 00033 union _ll { 00034 uint64_t i64; 00035 struct { 00036 # if defined (_STLP_BIG_ENDIAN) 00037 uint32_t hi; 00038 uint32_t lo; 00039 # elif defined (_STLP_LITTLE_ENDIAN) 00040 uint32_t lo; 00041 uint32_t hi; 00042 # else 00043 # error Unknown endianess 00044 # endif 00045 } i32; 00046 }; 00047 #endif 00048 00049 #if defined (N_PLAT_NLM) 00050 # include <nlm/nwintxx.h> 00051 00052 # if defined (INT64) 00053 typedef unsigned INT64 uint64_t; 00054 # else 00055 // #error "Can't find INT64" 00056 // 64-bit int really not defined in headers 00057 // (_INTEGRAL_MAX_BITS < 64 in any case?), but compiler indeed know __int64 00058 // - ptr, 2005-05-06 00059 typedef unsigned __int64 uint64_t; 00060 # endif 00061 00062 # if defined (INT32) 00063 typedef unsigned INT32 uint32_t; 00064 # else 00065 # error Can not find INT32 00066 # endif 00067 00068 union _ll { 00069 uint64_t i64; 00070 struct { 00071 uint32_t lo; 00072 uint32_t hi; 00073 } i32; 00074 }; 00075 #endif 00076 00077 _STLP_BEGIN_NAMESPACE 00078 _STLP_MOVE_TO_PRIV_NAMESPACE 00079 00080 //---------------------------------------------------------------------- 00081 // num_get 00082 00083 // Helper functions for _M_do_get_float. 00084 00085 #if !defined (_STLP_NO_WCHAR_T) 00086 void _STLP_CALL 00087 _Initialize_get_float( const ctype<wchar_t>& ct, 00088 wchar_t& Plus, wchar_t& Minus, 00089 wchar_t& pow_e, wchar_t& pow_E, 00090 wchar_t* digits) { 00091 char ndigits[11] = "0123456789"; 00092 Plus = ct.widen('+'); 00093 Minus = ct.widen('-'); 00094 pow_e = ct.widen('e'); 00095 pow_E = ct.widen('E'); 00096 ct.widen(ndigits + 0, ndigits + 10, digits); 00097 } 00098 #endif /* WCHAR_T */ 00099 00100 /* 00101 * __string_to_double is just lifted from atof, the difference being 00102 * that we just use '.' for the decimal point, rather than let it 00103 * be taken from the current C locale, which of course is not accessible 00104 * to us. 00105 */ 00106 #if defined (_STLP_MSVC) || defined (__BORLANDC__) || defined (__ICL) 00107 typedef unsigned long uint32; 00108 typedef unsigned __int64 uint64; 00109 # define ULL(x) x##Ui64 00110 #elif defined (__MRC__) || defined (__SC__) 00111 typedef unsigned long uint32; 00112 # include "uint64.h" //*TY 03/25/2000 - added 64bit math type definition 00113 #elif defined (__unix) || defined (__MINGW32__) || defined (N_PLAT_NLM) || \ 00114 (defined (__DMC__) && (__LONGLONG)) 00115 typedef uint32_t uint32; 00116 typedef uint64_t uint64; 00117 # define ULL(x) x##ULL 00118 #else 00119 # error There should be some unsigned 64-bit integer on the system! 00120 #endif 00121 00122 // Multiplication of two 64-bit integers, giving a 128-bit result. 00123 // Taken from Algorithm M in Knuth section 4.3.1, with the loop 00124 // hand-unrolled. 00125 static void _Stl_mult64(const uint64 u, const uint64 v, 00126 uint64& high, uint64& low) { 00127 const uint64 low_mask = ULL(0xffffffff); 00128 const uint64 u0 = u & low_mask; 00129 const uint64 u1 = u >> 32; 00130 const uint64 v0 = v & low_mask; 00131 const uint64 v1 = v >> 32; 00132 00133 uint64 t = u0 * v0; 00134 low = t & low_mask; 00135 00136 t = u1 * v0 + (t >> 32); 00137 uint64 w1 = t & low_mask; 00138 uint64 w2 = t >> 32; 00139 00140 uint64 x = u0 * v1 + w1; 00141 low += (x & low_mask) << 32; 00142 high = u1 * v1 + w2 + (x >> 32); 00143 } 00144 00145 #define bit11 ULL(0x7ff) 00146 #define exponent_mask (bit11 << 52) 00147 00148 #if !defined (__GNUC__) || (__GNUC__ != 3) || (__GNUC_MINOR__ != 4) || \ 00149 (!defined (__CYGWIN__) && !defined (__MINGW32__)) 00150 //Generate bad code when compiled with -O2 option. 00151 inline 00152 #endif 00153 void _Stl_set_exponent(uint64 &val, uint64 exp) 00154 { val = (val & ~exponent_mask) | ((exp & bit11) << 52); } 00155 00156 /* Power of ten fractions for tenscale*/ 00157 /* The constants are factored so that at most two constants 00158 * and two multiplies are needed. Furthermore, one of the constants 00159 * is represented exactly - 10**n where 1<= n <= 27. 00160 */ 00161 00162 #if !defined (__SC__) //*TY 03/25/2000 - no native 64bit integer under SCpp 00163 static const uint64 _Stl_tenpow[80] = { 00164 ULL(0xa000000000000000), /* _Stl_tenpow[0]=(10**1)/(2**4) */ 00165 ULL(0xc800000000000000), /* _Stl_tenpow[1]=(10**2)/(2**7) */ 00166 ULL(0xfa00000000000000), /* _Stl_tenpow[2]=(10**3)/(2**10) */ 00167 ULL(0x9c40000000000000), /* _Stl_tenpow[3]=(10**4)/(2**14) */ 00168 ULL(0xc350000000000000), /* _Stl_tenpow[4]=(10**5)/(2**17) */ 00169 ULL(0xf424000000000000), /* _Stl_tenpow[5]=(10**6)/(2**20) */ 00170 ULL(0x9896800000000000), /* _Stl_tenpow[6]=(10**7)/(2**24) */ 00171 ULL(0xbebc200000000000), /* _Stl_tenpow[7]=(10**8)/(2**27) */ 00172 ULL(0xee6b280000000000), /* _Stl_tenpow[8]=(10**9)/(2**30) */ 00173 ULL(0x9502f90000000000), /* _Stl_tenpow[9]=(10**10)/(2**34) */ 00174 ULL(0xba43b74000000000), /* _Stl_tenpow[10]=(10**11)/(2**37) */ 00175 ULL(0xe8d4a51000000000), /* _Stl_tenpow[11]=(10**12)/(2**40) */ 00176 ULL(0x9184e72a00000000), /* _Stl_tenpow[12]=(10**13)/(2**44) */ 00177 ULL(0xb5e620f480000000), /* _Stl_tenpow[13]=(10**14)/(2**47) */ 00178 ULL(0xe35fa931a0000000), /* _Stl_tenpow[14]=(10**15)/(2**50) */ 00179 ULL(0x8e1bc9bf04000000), /* _Stl_tenpow[15]=(10**16)/(2**54) */ 00180 ULL(0xb1a2bc2ec5000000), /* _Stl_tenpow[16]=(10**17)/(2**57) */ 00181 ULL(0xde0b6b3a76400000), /* _Stl_tenpow[17]=(10**18)/(2**60) */ 00182 ULL(0x8ac7230489e80000), /* _Stl_tenpow[18]=(10**19)/(2**64) */ 00183 ULL(0xad78ebc5ac620000), /* _Stl_tenpow[19]=(10**20)/(2**67) */ 00184 ULL(0xd8d726b7177a8000), /* _Stl_tenpow[20]=(10**21)/(2**70) */ 00185 ULL(0x878678326eac9000), /* _Stl_tenpow[21]=(10**22)/(2**74) */ 00186 ULL(0xa968163f0a57b400), /* _Stl_tenpow[22]=(10**23)/(2**77) */ 00187 ULL(0xd3c21bcecceda100), /* _Stl_tenpow[23]=(10**24)/(2**80) */ 00188 ULL(0x84595161401484a0), /* _Stl_tenpow[24]=(10**25)/(2**84) */ 00189 ULL(0xa56fa5b99019a5c8), /* _Stl_tenpow[25]=(10**26)/(2**87) */ 00190 ULL(0xcecb8f27f4200f3a), /* _Stl_tenpow[26]=(10**27)/(2**90) */ 00191 00192 ULL(0xd0cf4b50cfe20766), /* _Stl_tenpow[27]=(10**55)/(2**183) */ 00193 ULL(0xd2d80db02aabd62c), /* _Stl_tenpow[28]=(10**83)/(2**276) */ 00194 ULL(0xd4e5e2cdc1d1ea96), /* _Stl_tenpow[29]=(10**111)/(2**369) */ 00195 ULL(0xd6f8d7509292d603), /* _Stl_tenpow[30]=(10**139)/(2**462) */ 00196 ULL(0xd910f7ff28069da4), /* _Stl_tenpow[31]=(10**167)/(2**555) */ 00197 ULL(0xdb2e51bfe9d0696a), /* _Stl_tenpow[32]=(10**195)/(2**648) */ 00198 ULL(0xdd50f1996b947519), /* _Stl_tenpow[33]=(10**223)/(2**741) */ 00199 ULL(0xdf78e4b2bd342cf7), /* _Stl_tenpow[34]=(10**251)/(2**834) */ 00200 ULL(0xe1a63853bbd26451), /* _Stl_tenpow[35]=(10**279)/(2**927) */ 00201 ULL(0xe3d8f9e563a198e5), /* _Stl_tenpow[36]=(10**307)/(2**1020) */ 00202 00203 ULL(0xfd87b5f28300ca0e), /* _Stl_tenpow[37]=(10**-28)/(2**-93) */ 00204 ULL(0xfb158592be068d2f), /* _Stl_tenpow[38]=(10**-56)/(2**-186) */ 00205 ULL(0xf8a95fcf88747d94), /* _Stl_tenpow[39]=(10**-84)/(2**-279) */ 00206 ULL(0xf64335bcf065d37d), /* _Stl_tenpow[40]=(10**-112)/(2**-372) */ 00207 ULL(0xf3e2f893dec3f126), /* _Stl_tenpow[41]=(10**-140)/(2**-465) */ 00208 ULL(0xf18899b1bc3f8ca2), /* _Stl_tenpow[42]=(10**-168)/(2**-558) */ 00209 ULL(0xef340a98172aace5), /* _Stl_tenpow[43]=(10**-196)/(2**-651) */ 00210 ULL(0xece53cec4a314ebe), /* _Stl_tenpow[44]=(10**-224)/(2**-744) */ 00211 ULL(0xea9c227723ee8bcb), /* _Stl_tenpow[45]=(10**-252)/(2**-837) */ 00212 ULL(0xe858ad248f5c22ca), /* _Stl_tenpow[46]=(10**-280)/(2**-930) */ 00213 ULL(0xe61acf033d1a45df), /* _Stl_tenpow[47]=(10**-308)/(2**-1023) */ 00214 ULL(0xe3e27a444d8d98b8), /* _Stl_tenpow[48]=(10**-336)/(2**-1116) */ 00215 ULL(0xe1afa13afbd14d6e) /* _Stl_tenpow[49]=(10**-364)/(2**-1209) */ 00216 00217 #else //*TY 03/20/2000 - added support for SCpp which lacks native 64bit integer type 00218 static const UnsignedWide _Stl_tenpow[80] = { 00219 ULL2(0xa0000000,0x00000000), /* _Stl_tenpow[0]=(10**1)/(2**4) */ 00220 ULL2(0xc8000000,0x00000000), /* _Stl_tenpow[1]=(10**2)/(2**7) */ 00221 ULL2(0xfa000000,0x00000000), /* _Stl_tenpow[2]=(10**3)/(2**10) */ 00222 ULL2(0x9c400000,0x00000000), /* _Stl_tenpow[3]=(10**4)/(2**14) */ 00223 ULL2(0xc3500000,0x00000000), /* _Stl_tenpow[4]=(10**5)/(2**17) */ 00224 ULL2(0xf4240000,0x00000000), /* _Stl_tenpow[5]=(10**6)/(2**20) */ 00225 ULL2(0x98968000,0x00000000), /* _Stl_tenpow[6]=(10**7)/(2**24) */ 00226 ULL2(0xbebc2000,0x00000000), /* _Stl_tenpow[7]=(10**8)/(2**27) */ 00227 ULL2(0xee6b2800,0x00000000), /* _Stl_tenpow[8]=(10**9)/(2**30) */ 00228 ULL2(0x9502f900,0x00000000), /* _Stl_tenpow[9]=(10**10)/(2**34) */ 00229 ULL2(0xba43b740,0x00000000), /* _Stl_tenpow[10]=(10**11)/(2**37) */ 00230 ULL2(0xe8d4a510,0x00000000), /* _Stl_tenpow[11]=(10**12)/(2**40) */ 00231 ULL2(0x9184e72a,0x00000000), /* _Stl_tenpow[12]=(10**13)/(2**44) */ 00232 ULL2(0xb5e620f4,0x80000000), /* _Stl_tenpow[13]=(10**14)/(2**47) */ 00233 ULL2(0xe35fa931,0xa0000000), /* _Stl_tenpow[14]=(10**15)/(2**50) */ 00234 ULL2(0x8e1bc9bf,0x04000000), /* _Stl_tenpow[15]=(10**16)/(2**54) */ 00235 ULL2(0xb1a2bc2e,0xc5000000), /* _Stl_tenpow[16]=(10**17)/(2**57) */ 00236 ULL2(0xde0b6b3a,0x76400000), /* _Stl_tenpow[17]=(10**18)/(2**60) */ 00237 ULL2(0x8ac72304,0x89e80000), /* _Stl_tenpow[18]=(10**19)/(2**64) */ 00238 ULL2(0xad78ebc5,0xac620000), /* _Stl_tenpow[19]=(10**20)/(2**67) */ 00239 ULL2(0xd8d726b7,0x177a8000), /* _Stl_tenpow[20]=(10**21)/(2**70) */ 00240 ULL2(0x87867832,0x6eac9000), /* _Stl_tenpow[21]=(10**22)/(2**74) */ 00241 ULL2(0xa968163f,0x0a57b400), /* _Stl_tenpow[22]=(10**23)/(2**77) */ 00242 ULL2(0xd3c21bce,0xcceda100), /* _Stl_tenpow[23]=(10**24)/(2**80) */ 00243 ULL2(0x84595161,0x401484a0), /* _Stl_tenpow[24]=(10**25)/(2**84) */ 00244 ULL2(0xa56fa5b9,0x9019a5c8), /* _Stl_tenpow[25]=(10**26)/(2**87) */ 00245 ULL2(0xcecb8f27,0xf4200f3a), /* _Stl_tenpow[26]=(10**27)/(2**90) */ 00246 00247 ULL2(0xd0cf4b50,0xcfe20766), /* _Stl_tenpow[27]=(10**55)/(2**183) */ 00248 ULL2(0xd2d80db0,0x2aabd62c), /* _Stl_tenpow[28]=(10**83)/(2**276) */ 00249 ULL2(0xd4e5e2cd,0xc1d1ea96), /* _Stl_tenpow[29]=(10**111)/(2**369) */ 00250 ULL2(0xd6f8d750,0x9292d603), /* _Stl_tenpow[30]=(10**139)/(2**462) */ 00251 ULL2(0xd910f7ff,0x28069da4), /* _Stl_tenpow[31]=(10**167)/(2**555) */ 00252 ULL2(0xdb2e51bf,0xe9d0696a), /* _Stl_tenpow[32]=(10**195)/(2**648) */ 00253 ULL2(0xdd50f199,0x6b947519), /* _Stl_tenpow[33]=(10**223)/(2**741) */ 00254 ULL2(0xdf78e4b2,0xbd342cf7), /* _Stl_tenpow[34]=(10**251)/(2**834) */ 00255 ULL2(0xe1a63853,0xbbd26451), /* _Stl_tenpow[35]=(10**279)/(2**927) */ 00256 ULL2(0xe3d8f9e5,0x63a198e5), /* _Stl_tenpow[36]=(10**307)/(2**1020) */ 00257 00258 ULL2(0xfd87b5f2,0x8300ca0e), /* _Stl_tenpow[37]=(10**-28)/(2**-93) */ 00259 ULL2(0xfb158592,0xbe068d2f), /* _Stl_tenpow[38]=(10**-56)/(2**-186) */ 00260 ULL2(0xf8a95fcf,0x88747d94), /* _Stl_tenpow[39]=(10**-84)/(2**-279) */ 00261 ULL2(0xf64335bc,0xf065d37d), /* _Stl_tenpow[40]=(10**-112)/(2**-372) */ 00262 ULL2(0xf3e2f893,0xdec3f126), /* _Stl_tenpow[41]=(10**-140)/(2**-465) */ 00263 ULL2(0xf18899b1,0xbc3f8ca2), /* _Stl_tenpow[42]=(10**-168)/(2**-558) */ 00264 ULL2(0xef340a98,0x172aace5), /* _Stl_tenpow[43]=(10**-196)/(2**-651) */ 00265 ULL2(0xece53cec,0x4a314ebe), /* _Stl_tenpow[44]=(10**-224)/(2**-744) */ 00266 ULL2(0xea9c2277,0x23ee8bcb), /* _Stl_tenpow[45]=(10**-252)/(2**-837) */ 00267 ULL2(0xe858ad24,0x8f5c22ca), /* _Stl_tenpow[46]=(10**-280)/(2**-930) */ 00268 ULL2(0xe61acf03,0x3d1a45df), /* _Stl_tenpow[47]=(10**-308)/(2**-1023) */ 00269 ULL2(0xe3e27a44,0x4d8d98b8), /* _Stl_tenpow[48]=(10**-336)/(2**-1116) */ 00270 ULL2(0xe1afa13a,0xfbd14d6e) /* _Stl_tenpow[49]=(10**-364)/(2**-1209) */ 00271 #endif 00272 }; 00273 00274 static const short _Stl_twoexp[80] = { 00275 4,7,10,14,17,20,24,27,30,34,37,40,44,47,50,54,57,60,64,67,70,74,77,80,84,87,90, 00276 183,276,369,462,555,648,741,834,927,1020, 00277 -93,-186,-279,-372,-465,-558,-651,-744,-837,-930,-1023,-1116,-1209 00278 }; 00279 00280 #define TEN_1 0 /* offset to 10 ** 1 */ 00281 #define TEN_27 26 /* offset to 10 ** 27 */ 00282 #define TEN_M28 37 /* offset to 10 ** -28 */ 00283 #define NUM_HI_P 11 00284 #define NUM_HI_N 13 00285 00286 #define _Stl_HIBITULL (ULL(1) << 63) 00287 00288 static void _Stl_norm_and_round(uint64& p, int& norm, uint64 prodhi, uint64 prodlo) { 00289 norm = 0; 00290 if ((prodhi & _Stl_HIBITULL) == 0) { 00291 /* leading bit is a zero 00292 * may have to normalize 00293 */ 00294 if ((prodhi == ~_Stl_HIBITULL) && 00295 ((prodlo >> 62) == 0x3)) { /* normalization followed by round 00296 * would cause carry to create 00297 * extra bit, so don't normalize 00298 */ 00299 p = _Stl_HIBITULL; 00300 return; 00301 } 00302 p = (prodhi << 1) | (prodlo >> 63); /* normalize */ 00303 norm = 1; 00304 prodlo <<= 1; 00305 } 00306 else { 00307 p = prodhi; 00308 } 00309 00310 if ((prodlo & _Stl_HIBITULL) != 0) { /* first guard bit a one */ //*TY 03/25/2000 - added explicit comparison to zero to avoid reliance to the implicit conversion from uint64 to bool 00311 #if !defined (__SC__) //*TY 03/25/2000 - 00312 if (((p & 0x1) != 0) || 00313 prodlo != _Stl_HIBITULL ) { /* not borderline for round to even */ 00314 #else //*TY 03/25/2000 - added workaround for SCpp compiler 00315 bool b1 = ((p & 0x1) != 0); 00316 if (b1 || prodlo != _Stl_HIBITULL) { //*TY 03/25/2000 - SCpp confuses on this particular original boolean expression 00317 #endif //*TY 03/25/2000 - 00318 /* round */ 00319 ++p; 00320 if (p == 0) 00321 ++p; 00322 } 00323 } 00324 00325 return; 00326 } 00327 00328 // Convert a 64-bitb fraction * 10^exp to a 64-bit fraction * 2^bexp. 00329 // p: 64-bit fraction 00330 // exp: base-10 exponent 00331 // bexp: base-2 exponent (output parameter) 00332 static void _Stl_tenscale(uint64& p, int exp, int& bexp) { 00333 uint64 prodhi, prodlo; /* 128b product */ 00334 int exp_hi, exp_lo; /* exp = exp_hi*32 + exp_lo */ 00335 int hi, lo, tlo, thi; /* offsets in power of ten table */ 00336 int norm; /* number of bits of normalization */ 00337 int num_hi; /* number of high exponent powers */ 00338 00339 bexp = 0; 00340 if (exp > 0) { /* split exponent */ 00341 exp_lo = exp; 00342 exp_hi = 0; 00343 if (exp_lo > 27) { 00344 exp_lo++; 00345 while (exp_lo > 27) { 00346 exp_hi++; 00347 exp_lo -= 28; 00348 } 00349 } 00350 tlo = TEN_1; 00351 thi = TEN_27; 00352 num_hi = NUM_HI_P; 00353 } 00354 else if (exp < 0) { 00355 exp_lo = exp; 00356 exp_hi = 0; 00357 while (exp_lo < 0) { 00358 exp_hi++; 00359 exp_lo += 28; 00360 } 00361 tlo = TEN_1; 00362 thi = TEN_M28; 00363 num_hi = NUM_HI_N; 00364 } 00365 else { /* no scaling needed */ 00366 return; 00367 } 00368 while (exp_hi) { /* scale */ 00369 hi = (min) (exp_hi, num_hi); /* only a few large powers of 10 */ 00370 exp_hi -= hi; /* could iterate in extreme case */ 00371 hi += thi-1; 00372 _Stl_mult64(p, _Stl_tenpow[hi], prodhi, prodlo); 00373 _Stl_norm_and_round(p, norm, prodhi, prodlo); 00374 bexp += _Stl_twoexp[hi] - norm; 00375 } 00376 if (exp_lo) { 00377 lo = tlo + exp_lo -1; 00378 _Stl_mult64(p, _Stl_tenpow[lo], prodhi, prodlo); 00379 _Stl_norm_and_round(p, norm, prodhi, prodlo); 00380 bexp += _Stl_twoexp[lo] - norm; 00381 } 00382 00383 return; 00384 } 00385 00386 // First argument is a buffer of values from 0 to 9, NOT ascii. 00387 // Second argument is number of digits in buffer, 1 <= digits <= 17. 00388 // Third argument is base-10 exponent. 00389 00390 #if defined (__SC__) || defined (__MRC__) 00391 00392 //*TY 04/06/2000 - powermac's 68K emulator utilizes apple's SANE floating point, which is not compatible with IEEE format. 00393 _STLP_MOVE_TO_STD_NAMESPACE 00394 _STLP_END_NAMESPACE 00395 00396 # include <fp.h> 00397 00398 _STLP_BEGIN_NAMESPACE 00399 _STLP_MOVE_TO_PRIV_NAMESPACE 00400 00401 static inline double _Stl_atod(char *buffer, int ndigit, int dexp) { 00402 decimal d; // ref. inside macintosh powerpc numerics p.9-13 00403 00404 d.sgn = 0; 00405 d.exp = dexp; 00406 d.sig.length = ndigit; 00407 for (int i = 0; i < ndigit; ++i) { 00408 d.sig.text[i] = buffer[i] + '0'; 00409 } 00410 return dec2num(&d); 00411 } 00412 00413 #else /* IEEE representation */ 00414 00415 # if !defined (__linux__) 00416 static double _Stl_atod(char *buffer, int ndigit, int dexp) { 00417 uint64 value; /* Value develops as follows: 00418 * 1) decimal digits as an integer 00419 * 2) left adjusted fraction 00420 * 3) right adjusted fraction 00421 * 4) exponent and fraction 00422 */ 00423 00424 uint32 guard; /* First guard bit */ 00425 uint64 rest; /* Remaining guard bits */ 00426 00427 int bexp; /* binary exponent */ 00428 int nzero; /* number of non-zero bits */ 00429 int sexp; /* scaling exponent */ 00430 00431 char *bufferend; /* pointer to char after last digit */ 00432 00433 /* Check for zero and treat it as a special case */ 00434 if (buffer == 0){ 00435 return 0.0; 00436 } 00437 00438 /* Convert the decimal digits to a binary integer. */ 00439 00440 bufferend = buffer + ndigit; 00441 value = 0; 00442 00443 while (buffer < bufferend) { 00444 value *= 10; 00445 value += *buffer++; 00446 } 00447 00448 /* Check for zero and treat it as a special case */ 00449 if (value == 0) { 00450 return 0.0; 00451 } 00452 00453 /* Normalize value */ 00454 bexp = 64; /* convert from 64b int to fraction */ 00455 00456 /* Count number of non-zeroes in value */ 00457 nzero = 0; 00458 if ((value >> 32) != 0) { nzero = 32; } //*TY 03/25/2000 - added explicit comparison to zero to avoid uint64 to bool conversion operator 00459 if ((value >> (16 + nzero)) != 0) { nzero += 16; } 00460 if ((value >> ( 8 + nzero)) != 0) { nzero += 8; } 00461 if ((value >> ( 4 + nzero)) != 0) { nzero += 4; } 00462 if ((value >> ( 2 + nzero)) != 0) { nzero += 2; } 00463 if ((value >> ( 1 + nzero)) != 0) { nzero += 1; } 00464 if ((value >> ( nzero)) != 0) { nzero += 1; } 00465 00466 /* Normalize */ 00467 value <<= /*(uint64)*/ (64 - nzero); //*TY 03/25/2000 - removed extraneous cast to uint64 00468 bexp -= 64 - nzero; 00469 00470 /* At this point we have a 64b fraction and a binary exponent 00471 * but have yet to incorporate the decimal exponent. 00472 */ 00473 00474 /* multiply by 10^dexp */ 00475 _Stl_tenscale(value, dexp, sexp); 00476 bexp += sexp; 00477 00478 if (bexp <= -1022) { /* HI denorm or underflow */ 00479 bexp += 1022; 00480 if (bexp < -53) { /* guaranteed underflow */ 00481 value = 0; 00482 } 00483 else { /* denorm or possible underflow */ 00484 int lead0 = 12 - bexp; /* 12 sign and exponent bits */ 00485 00486 /* we must special case right shifts of more than 63 */ 00487 if (lead0 > 64) { 00488 rest = value; 00489 guard = 0; 00490 value = 0; 00491 } 00492 else if (lead0 == 64) { 00493 rest = value & ((ULL(1)<< 63)-1); 00494 #if !defined(__SC__) 00495 guard = (uint32) ((value>> 63) & 1 ); 00496 #else 00497 guard = to_ulong((value>> 63) & 1 ); //*TY 03/25/2000 - use member function instead of problematic conversion operator utilization 00498 #endif 00499 value = 0; 00500 } 00501 else { 00502 rest = value & (((ULL(1) << lead0)-1)-1); 00503 #if !defined(__SC__) 00504 guard = (uint32) (((value>> lead0)-1) & 1); 00505 #else //*TY 03/25/2000 - 00506 guard = to_ulong(((value>> lead0)-1) & 1); 00507 #endif //*TY 03/25/2000 - 00508 value >>= /*(uint64)*/ lead0; /* exponent is zero */ 00509 } 00510 00511 /* Round */ 00512 if (guard && ((value & 1) || rest) ) { 00513 ++value; 00514 if (value == (ULL(1) << 52)) { /* carry created normal number */ 00515 value = 0; 00516 _Stl_set_exponent(value, 1); 00517 } 00518 } 00519 } 00520 } 00521 else { /* not zero or denorm */ 00522 /* Round to 53 bits */ 00523 rest = value & (1<<10)-1; 00524 value >>= 10; 00525 #if !defined(__SC__) 00526 guard = (uint32) value & 1; 00527 #else //*TY 03/25/2000 - 00528 guard = to_ulong(value & 1); 00529 #endif 00530 value >>= 1; 00531 00532 /* value&1 guard rest Action 00533 * 00534 * dc 0 dc none 00535 * 1 1 dc round 00536 * 0 1 0 none 00537 * 0 1 !=0 round 00538 */ 00539 if (guard) { 00540 if (((value&1)!=0) || (rest!=0)) { 00541 ++value; /* round */ 00542 if ((value >> 53) != 0) { /* carry all the way across */ 00543 value >>= 1; /* renormalize */ 00544 ++bexp; 00545 } 00546 } 00547 } 00548 /* 00549 * Check for overflow 00550 * IEEE Double Precision Format 00551 * (From Table 7-8 of Kane and Heinrich) 00552 * 00553 * Fraction bits 52 00554 * Emax +1023 00555 * Emin -1022 00556 * Exponent bias +1023 00557 * Exponent bits 11 00558 * Integer bit hidden 00559 * Total width in bits 64 00560 */ 00561 00562 if (bexp > 1024) { /* overflow */ 00563 return numeric_limits<double>::infinity(); 00564 } 00565 else { /* value is normal */ 00566 value &= ~(ULL(1) << 52); /* hide hidden bit */ 00567 _Stl_set_exponent(value, bexp + 1022); /* add bias */ 00568 } 00569 } 00570 00571 _STLP_STATIC_ASSERT(sizeof(value) == sizeof(double)) 00572 return *((double *) &value); 00573 } 00574 00575 # else // __linux__ 00576 00577 static double _Stl_atod(char *buffer, int ndigit, int dexp) { 00578 ieee754_double v; 00579 00580 char *bufferend; /* pointer to char after last digit */ 00581 00582 /* Check for zero and treat it as a special case */ 00583 00584 if (buffer == 0) { 00585 return 0.0; 00586 } 00587 00588 /* Convert the decimal digits to a binary integer. */ 00589 00590 bufferend = buffer + ndigit; 00591 _ll vv; 00592 vv.i64 = 0L; 00593 00594 while (buffer < bufferend) { 00595 vv.i64 *= 10; 00596 vv.i64 += *buffer++; 00597 } 00598 00599 /* Check for zero and treat it as a special case */ 00600 if (vv.i64 == 0){ 00601 return 0.0; 00602 } 00603 00604 /* Normalize value */ 00605 int bexp = 64; /* convert from 64b int to fraction */ 00606 00607 /* Count number of non-zeroes in value */ 00608 int nzero = 0; 00609 if ((vv.i64 >> 32) !=0 ) { nzero = 32; } //*TY 03/25/2000 - added explicit comparison to zero to avoid uint64 to bool conversion operator 00610 if ((vv.i64 >> (16 + nzero)) != 0) { nzero += 16; } 00611 if ((vv.i64 >> ( 8 + nzero)) != 0) { nzero += 8; } 00612 if ((vv.i64 >> ( 4 + nzero)) != 0) { nzero += 4; } 00613 if ((vv.i64 >> ( 2 + nzero)) != 0) { nzero += 2; } 00614 if ((vv.i64 >> ( 1 + nzero)) != 0) { nzero += 1; } 00615 if ((vv.i64 >> ( nzero)) != 0) { nzero += 1; } 00616 00617 /* Normalize */ 00618 nzero = 64 - nzero; 00619 vv.i64 <<= nzero; //*TY 03/25/2000 - removed extraneous cast to uint64 00620 bexp -= nzero; 00621 00622 /* At this point we have a 64b fraction and a binary exponent 00623 * but have yet to incorporate the decimal exponent. 00624 */ 00625 00626 /* multiply by 10^dexp */ 00627 int sexp; 00628 _Stl_tenscale(vv.i64, dexp, sexp); 00629 bexp += sexp; 00630 00631 if (bexp <= -1022) { /* HI denorm or underflow */ 00632 bexp += 1022; 00633 if (bexp < -53) { /* guaranteed underflow */ 00634 vv.i64 = 0; 00635 } 00636 else { /* denorm or possible underflow */ 00637 int lead0; 00638 uint64_t rest; 00639 uint32_t guard; 00640 00641 lead0 = 12-bexp; /* 12 sign and exponent bits */ 00642 00643 /* we must special case right shifts of more than 63 */ 00644 if (lead0 > 64) { 00645 rest = vv.i64; 00646 guard = 0; 00647 vv.i64 = 0; 00648 } 00649 else if (lead0 == 64) { 00650 rest = vv.i64 & ((ULL(1) << 63)-1); 00651 #if !defined(__SC__) 00652 guard = (uint32) ((vv.i64 >> 63) & 1 ); 00653 #else 00654 guard = to_ulong((vv.i64 >> 63) & 1 ); //*TY 03/25/2000 - use member function instead of problematic conversion operator utilization 00655 #endif 00656 vv.i64 = 0; 00657 } 00658 else { 00659 rest = vv.i64 & (((ULL(1) << lead0)-1)-1); 00660 #if !defined(__SC__) 00661 guard = (uint32) (((vv.i64 >> lead0)-1) & 1); 00662 #else //*TY 03/25/2000 - 00663 guard = to_ulong(((vv.i64 >> lead0)-1) & 1); 00664 #endif //*TY 03/25/2000 - 00665 vv.i64 >>= /*(uint64)*/ lead0; /* exponent is zero */ 00666 } 00667 00668 /* Round */ 00669 if (guard && ( (vv.i64 & 1) || rest)) { 00670 vv.i64++; 00671 if (vv.i64 == (ULL(1) << 52)) { /* carry created normal number */ 00672 v.ieee.mantissa0 = 0; 00673 v.ieee.mantissa1 = 0; 00674 v.ieee.negative = 0; 00675 v.ieee.exponent = 1; 00676 return v.d; 00677 } 00678 } 00679 } 00680 } 00681 else { /* not zero or denorm */ 00682 /* Round to 53 bits */ 00683 uint64_t rest = vv.i64 & (1<<10)-1; 00684 vv.i64 >>= 10; 00685 #if !defined(__SC__) 00686 uint32_t guard = (uint32) vv.i64 & 1; 00687 #else //*TY 03/25/2000 - 00688 uint32_t guard = to_ulong(vv.i64 & 1); 00689 #endif 00690 vv.i64 >>= 1; 00691 00692 /* value&1 guard rest Action 00693 * 00694 * dc 0 dc none 00695 * 1 1 dc round 00696 * 0 1 0 none 00697 * 0 1 !=0 round 00698 */ 00699 if (guard) { 00700 if (((vv.i64&1)!=0) || (rest!=0)) { 00701 vv.i64++; /* round */ 00702 if ((vv.i64>>53)!=0) { /* carry all the way across */ 00703 vv.i64 >>= 1; /* renormalize */ 00704 ++bexp; 00705 } 00706 } 00707 } 00708 /* 00709 * Check for overflow 00710 * IEEE Double Precision Format 00711 * (From Table 7-8 of Kane and Heinrich) 00712 * 00713 * Fraction bits 52 00714 * Emax +1023 00715 * Emin -1022 00716 * Exponent bias +1023 00717 * Exponent bits 11 00718 * Integer bit hidden 00719 * Total width in bits 64 00720 */ 00721 00722 if (bexp > 1024) { /* overflow */ 00723 return numeric_limits<double>::infinity(); 00724 } 00725 else { /* value is normal */ 00726 vv.i64 &= ~(ULL(1) << 52); /* hide hidden bit */ 00727 v.ieee.mantissa0 = vv.i32.hi; 00728 v.ieee.mantissa1 = vv.i32.lo; 00729 v.ieee.negative = 0; 00730 v.ieee.exponent = bexp + 1022; 00731 return v.d; 00732 } 00733 } 00734 00735 v.ieee.mantissa0 = vv.i32.hi; 00736 v.ieee.mantissa1 = vv.i32.lo; 00737 v.ieee.negative = 0; 00738 v.ieee.exponent = 0; 00739 00740 return v.d; 00741 } 00742 # endif // __linux__ 00743 00744 #endif 00745 00746 static double _Stl_string_to_double(const char *s) { 00747 const int max_digits = 17; 00748 unsigned c; 00749 unsigned Negate, decimal_point; 00750 char *d; 00751 int exp; 00752 double x; 00753 int dpchar; 00754 char digits[max_digits]; 00755 00756 // Skip leading whitespace, if any. 00757 const ctype<char>& ct = use_facet<ctype<char> >(locale::classic()); 00758 while (c = *s++, ct.is(ctype_base::space, char(c))) {} 00759 00760 /* process sign */ 00761 Negate = 0; 00762 if (c == '+') { 00763 c = *s++; 00764 } 00765 else if (c == '-') { 00766 Negate = 1; 00767 c = *s++; 00768 } 00769 d = digits; 00770 dpchar = '.' - '0'; 00771 decimal_point = 0; 00772 exp = 0; 00773 for (;;) { 00774 c -= '0'; 00775 if (c < 10) { 00776 if (d == digits + max_digits) { 00777 /* ignore more than 17 digits, but adjust exponent */ 00778 exp += (decimal_point ^ 1); 00779 } 00780 else { 00781 if (c == 0 && d == digits) { 00782 /* ignore leading zeros */ 00783 } 00784 else { 00785 *d++ = (char) c; 00786 } 00787 exp -= decimal_point; 00788 } 00789 } 00790 else if (c == (unsigned int) dpchar && !decimal_point) { /* INTERNATIONAL */ 00791 decimal_point = 1; 00792 } 00793 else { 00794 break; 00795 } 00796 c = *s++; 00797 } 00798 /* strtod cant return until it finds the end of the exponent */ 00799 if (d == digits) { 00800 return 0.0; 00801 } 00802 00803 if (c == 'e'-'0' || c == 'E'-'0') { 00804 register unsigned negate_exp = 0; 00805 register int e = 0; 00806 c = *s++; 00807 if (c == '+' || c == ' ') { 00808 c = *s++; 00809 } 00810 else if (c == '-') { 00811 negate_exp = 1; 00812 c = *s++; 00813 } 00814 if (c -= '0', c < 10) { 00815 do { 00816 if (e <= 340) 00817 e = e * 10 + (int)c; 00818 else break; 00819 c = *s++; 00820 } 00821 while (c -= '0', c < 10); 00822 if (negate_exp) { 00823 e = -e; 00824 } 00825 if (e < -340 || e > 340) 00826 exp = e; 00827 else 00828 exp += e; 00829 } 00830 } 00831 00832 if (exp < -340) { 00833 x = 0; 00834 } 00835 else if (exp > 308) { 00836 x = numeric_limits<double>::infinity(); 00837 } 00838 else { 00839 /* let _Stl_atod diagnose under- and over-flows */ 00840 /* if the input was == 0.0, we have already returned, 00841 so retval of +-Inf signals OVERFLOW, 0.0 UNDERFLOW 00842 */ 00843 x = _Stl_atod(digits, (int)(d - digits), exp); 00844 } 00845 if (Negate) { 00846 x = -x; 00847 } 00848 return x; 00849 } 00850 00851 00852 #if !defined (_STLP_NO_LONG_DOUBLE) 00853 /* 00854 * __string_to_long_double is just lifted from atold, the difference being 00855 * that we just use '.' for the decimal point, rather than let it 00856 * be taken from the current C locale, which of course is not accessible 00857 * to us. 00858 */ 00859 00860 static long double 00861 _Stl_string_to_long_double(const char * s) { 00862 const int max_digits = 34; 00863 register unsigned c; 00864 register unsigned Negate, decimal_point; 00865 register char *d; 00866 register int exp; 00867 long double x; 00868 register int dpchar; 00869 char digits[max_digits]; 00870 00871 const ctype<char>& ct = use_facet<ctype<char> >(locale::classic()); 00872 while (c = *s++, ct.is(ctype_base::space, char(c))) 00873 ; 00874 00875 /* process sign */ 00876 Negate = 0; 00877 if (c == '+') { 00878 c = *s++; 00879 } 00880 else if (c == '-') { 00881 Negate = 1; 00882 c = *s++; 00883 } 00884 00885 d = digits; 00886 dpchar = '.' - '0'; 00887 decimal_point = 0; 00888 exp = 0; 00889 00890 for (;;) { 00891 c -= '0'; 00892 if (c < 10) { 00893 if (d == digits+max_digits) { 00894 /* ignore more than 34 digits, but adjust exponent */ 00895 exp += (decimal_point ^ 1); 00896 } 00897 else { 00898 if (c == 0 && d == digits) { 00899 /* ignore leading zeros */ 00900 ; 00901 } 00902 else { 00903 *d++ = (char)c; 00904 } 00905 exp -= decimal_point; 00906 } 00907 } 00908 else if ((char)c == dpchar && !decimal_point) { /* INTERNATIONAL */ 00909 decimal_point = 1; 00910 } 00911 else { 00912 break; 00913 } 00914 c = *s++; 00915 } /* for */ 00916 00917 if (d == digits) { 00918 return 0.0L; 00919 } 00920 if (c == 'e'-'0' || c == 'E'-'0') { 00921 register unsigned negate_exp = 0; 00922 register int e = 0; 00923 c = *s++; 00924 if (c == '+' || c == ' ') { 00925 c = *s++; 00926 } 00927 else if (c == '-') { 00928 negate_exp = 1; 00929 c = *s++; 00930 } 00931 if (c -= '0', c < 10) { 00932 do { 00933 if (e <= 340) 00934 e = e * 10 + c; 00935 else break; 00936 c = *s++; 00937 } 00938 while (c -= '0', c < 10); 00939 if (negate_exp) { 00940 e = -e; 00941 } 00942 if (e < -(323+max_digits) || e > 308) 00943 exp = e; 00944 else 00945 exp += e; 00946 } 00947 } 00948 00949 if (exp < -(324+max_digits)) { 00950 x = 0; 00951 } 00952 else if (exp > 308) { 00953 x = numeric_limits<long double>::infinity(); 00954 } 00955 else { 00956 /* let _Stl_atod diagnose under- and over-flows */ 00957 /* if the input was == 0.0, we have already returned, 00958 so retval of +-Inf signals OVERFLOW, 0.0 UNDERFLOW 00959 */ 00960 00961 // x = _Stl_atod (digits, (int)(d - digits), exp); // TEMPORARY!!:1 00962 double tmp = _Stl_atod (digits, (int)(d - digits), exp); // TEMPORARY!!:1 00963 x = tmp == numeric_limits<double>::infinity() 00964 ? numeric_limits<long double>::infinity() 00965 : tmp; 00966 } 00967 00968 if (Negate) { 00969 x = -x; 00970 } 00971 00972 return x; 00973 } 00974 #endif 00975 00976 void _STLP_CALL 00977 __string_to_float(const __iostring& v, float& val) 00978 { val = (float)_Stl_string_to_double(v.c_str()); } 00979 00980 void _STLP_CALL 00981 __string_to_float(const __iostring& v, double& val) 00982 { val = _Stl_string_to_double(v.c_str()); } 00983 00984 #if !defined (_STLP_NO_LONG_DOUBLE) 00985 void _STLP_CALL 00986 __string_to_float(const __iostring& v, long double& val) 00987 { val = _Stl_string_to_long_double(v.c_str()); } 00988 #endif 00989 00990 _STLP_MOVE_TO_STD_NAMESPACE 00991 _STLP_END_NAMESPACE 00992 00993 // Local Variables: 00994 // mode:C++ 00995 // End:
Generated on Mon Mar 10 15:32:17 2008 by ![]() |