Changeset d43c117 in mainline
 Timestamp:
 20110724T21:26:19Z (10 years ago)
 Branches:
 lfn, master
 Children:
 d542aad
 Parents:
 cfbb5d18
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

uspace/lib/posix/stdlib/strtold.c
rcfbb5d18 rd43c117 46 46 #include "../strings.h" 47 47 #include "../errno.h" 48 #include "../limits.h" 49 50 // FIXME: #include <float.h> 48 51 49 52 #ifndef HUGE_VALL … … 52 55 53 56 #ifndef abs 54 #define abs(x) ((x < 0) ? x : x) 55 #endif 56 57 // TODO: clean up 58 59 // FIXME: ensure it builds and works on all platforms 60 61 const int max_small_pow5 = 15; 62 63 /* The value at index i is approximately 5**i. */ 64 long double small_pow5[] = { 65 0x1P0, 66 0x5P0, 67 0x19P0, 68 0x7dP0, 69 0x271P0, 70 0xc35P0, 71 0x3d09P0, 72 0x1312dP0, 73 0x5f5e1P0, 74 0x1dcd65P0, 75 0x9502f9P0, 76 0x2e90eddP0, 77 0xe8d4a51P0, 78 0x48c27395P0, 79 0x16bcc41e9P0, 80 0x71afd498dP0 57 #define abs(x) (((x) < 0) ? (x) : (x)) 58 #endif 59 60 /* If the constants are not defined, use double precision as default. */ 61 #ifndef LDBL_MANT_DIG 62 #define LDBL_MANT_DIG 53 63 #endif 64 #ifndef LDBL_MAX_EXP 65 #define LDBL_MAX_EXP 1024 66 #endif 67 #ifndef LDBL_MIN_EXP 68 #define LDBL_MIN_EXP (1021) 69 #endif 70 #ifndef LDBL_DIG 71 #define LDBL_DIG 15 72 #endif 73 #ifndef LDBL_MIN 74 #define LDBL_MIN 2.2250738585072014E308 75 #endif 76 77 /* power functions ************************************************************/ 78 79 #if LDBL_MAX_EXP >= 16384 80 const int MAX_POW5 = 12; 81 #else 82 const int MAX_POW5 = 8; 83 #endif 84 85 /* The value at index i is approximately 5**(2**i). */ 86 long double pow5[] = { 87 0x5p0l, 88 0x19p0l, 89 0x271p0l, 90 0x5F5E1p0l, 91 0x2386F26FC1p0l, 92 0x4EE2D6D415B85ACEF81p0l, 93 0x184F03E93FF9F4DAA797ED6E38ED6p36l, 94 0x127748F9301D319BF8CDE66D86D62p185l, 95 0x154FDD7F73BF3BD1BBB77203731FDp482l, 96 #if LDBL_MAX_EXP >= 16384 97 0x1C633415D4C1D238D98CAB8A978A0p1076l, 98 0x192ECEB0D02EA182ECA1A7A51E316p2265l, 99 0x13D1676BB8A7ABBC94E9A519C6535p4643l, 100 0x188C0A40514412F3592982A7F0094p9398l, 101 #endif 81 102 }; 82 103 83 /* The value at index i is approximately 5**(2**i). */ 84 long double large_pow5[] = { 85 0x5P0l, 86 0x19P0l, 87 0x271P0l, 88 0x5f5e1P0l, 89 0x2386f26fc1P0l, 90 0x4ee2d6d415b85acef81P0l, 91 0x184f03e93ff9f4daa797ed6e38ed64bf6a1f01P0l, 92 0x24ee91f2603a6337f19bccdb0dac404dc08d3cff5ecP128l, 93 0x553f75fdcefcef46eeddcP512l, 94 0x1c633415d4c1d238d98cab8a978a0b1f138cb07303P1024l, 95 0x325d9d61a05d4305d9434f4a3c62d433949ae6209d492P2200l, 96 0x9e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba1964P4500l, 97 0x6230290145104bcd64a60a9fc025254932bb0fd922271133eeae7P9300l 98 }; 104 #if LDBL_MAX_EXP >= 16384 105 const int MAX_POW2 = 15; 106 #else 107 const int MAX_POW2 = 9; 108 #endif 99 109 100 110 /* Powers of two. */ … … 110 120 0x1P256l, 111 121 0x1P512l, 122 #if LDBL_MAX_EXP >= 16384 112 123 0x1P1024l, 113 124 0x1P2048l, 114 125 0x1P4096l, 115 0x1P8192l 126 0x1P8192l, 127 #endif 116 128 }; 117 129 118 130 /** 119 * Decides whether the argument is still in range representable by120 * long double or not.121 *122 * @param num Floating point number to be checked.123 * @return True if the argument is out of range, false otherwise.124 */125 static inline bool out_of_range(long double num)126 {127 return num == 0.0l  num == HUGE_VALL;128 }129 130 /**131 131 * Multiplies a number by a power of five. 132 * The result is not exact and may not be the best possible approximation. 133 * 134 * @param base Number to be multiplied. 135 * @param exponent Base 5 exponent. 136 * @return base multiplied by 5**exponent. 137 */ 138 static long double mul_pow5(long double base, int exponent) 139 { 140 if (out_of_range(base)) { 141 return base; 142 } 143 144 if (abs(exponent) >> 13 != 0) { 132 * The result may be inexact and may not be the best possible approximation. 133 * 134 * @param mant Number to be multiplied. 135 * @param exp Base 5 exponent. 136 * @return mant multiplied by 5**exp 137 */ 138 static long double mul_pow5(long double mant, int exp) 139 { 140 if (mant == 0.0l  mant == HUGE_VALL) { 141 return mant; 142 } 143 144 if (abs(exp) >> (MAX_POW5 + 1) != 0) { 145 /* Too large exponent. */ 145 146 errno = ERANGE; 146 return exponent < 0 ? 0.0l : HUGE_VALL; 147 } 148 149 if (exponent < 0) { 150 exponent = exponent; 151 base /= small_pow5[exponent & 0xF]; 152 for (int i = 4; i < 13; ++i) { 153 if (((exponent >> i) & 1) != 0) { 154 base /= large_pow5[i]; 155 if (out_of_range(base)) { 147 return exp < 0 ? LDBL_MIN : HUGE_VALL; 148 } 149 150 if (exp < 0) { 151 exp = abs(exp); 152 for (int bit = 0; bit <= MAX_POW5; ++bit) { 153 /* Multiply by powers of five bitbybit. */ 154 if (((exp >> bit) & 1) != 0) { 155 mant /= pow5[bit]; 156 if (mant == 0.0l) { 157 /* Underflow. */ 158 mant = LDBL_MIN; 156 159 errno = ERANGE; 157 160 break; … … 160 163 } 161 164 } else { 162 base *= small_pow5[exponent & 0xF]; 163 for (int i = 4; i < 13; ++i) { 164 if (((exponent >> i) & 1) != 0) { 165 base *= large_pow5[i]; 166 if (out_of_range(base)) { 165 for (int bit = 0; bit <= MAX_POW5; ++bit) { 166 /* Multiply by powers of five bitbybit. */ 167 if (((exp >> bit) & 1) != 0) { 168 mant *= pow5[bit]; 169 if (mant == HUGE_VALL) { 170 /* Overflow. */ 167 171 errno = ERANGE; 168 172 break; … … 172 176 } 173 177 174 return base;175 } 176 177 /** 178 * Multiplies a number by a power of two. 179 * 180 * @param baseNumber to be multiplied.181 * @param exp onentBase 2 exponent.182 * @return base multiplied by 2**exponent.183 */ 184 static long double mul_pow2(long double base, int exponent)185 { 186 if ( out_of_range(base)) {187 return base;188 } 189 190 if ( abs(exponent) >> 14 != 0) {178 return mant; 179 } 180 181 /** 182 * Multiplies a number by a power of two. This is always exact. 183 * 184 * @param mant Number to be multiplied. 185 * @param exp Base 2 exponent. 186 * @return mant multiplied by 2**exp. 187 */ 188 static long double mul_pow2(long double mant, int exp) 189 { 190 if (mant == 0.0l  mant == HUGE_VALL) { 191 return mant; 192 } 193 194 if (exp > LDBL_MAX_EXP  exp < LDBL_MIN_EXP) { 191 195 errno = ERANGE; 192 return exponent < 0 ? 0.0l : HUGE_VALL; 193 } 194 195 if (exponent < 0) { 196 exponent = exponent; 197 for (int i = 0; i < 14; ++i) { 198 if (((exponent >> i) & 1) != 0) { 199 base /= pow2[i]; 200 if (out_of_range(base)) { 196 return exp < 0 ? LDBL_MIN : HUGE_VALL; 197 } 198 199 if (exp < 0) { 200 exp = abs(exp); 201 for (int i = 0; i <= MAX_POW2; ++i) { 202 if (((exp >> i) & 1) != 0) { 203 mant /= pow2[i]; 204 if (mant == 0.0l) { 205 mant = LDBL_MIN; 201 206 errno = ERANGE; 202 207 break; … … 205 210 } 206 211 } else { 207 for (int i = 0; i < 14; ++i) {208 if (((exp onent>> i) & 1) != 0) {209 base*= pow2[i];210 if ( out_of_range(base)) {212 for (int i = 0; i <= MAX_POW2; ++i) { 213 if (((exp >> i) & 1) != 0) { 214 mant *= pow2[i]; 215 if (mant == HUGE_VALL) { 211 216 errno = ERANGE; 212 217 break; … … 216 221 } 217 222 218 return base; 219 } 223 return mant; 224 } 225 226 /* end power functions ********************************************************/ 227 228 220 229 221 230 /** … … 231 240 static long double parse_decimal(const char **sptr) 232 241 { 233 // TODO: Use strtol(), at least for exponent. 242 assert(sptr != NULL); 243 assert (*sptr != NULL); 234 244 235 245 const int DEC_BASE = 10; 236 246 const char DECIMAL_POINT = '.'; 237 247 const char EXPONENT_MARK = 'e'; 238 /* The highest amount of digits that can be safely parsed 239 * before an overflow occurs. 240 */ 241 const int PARSE_DECIMAL_DIGS = 19; 242 243 /* significand */ 244 uint64_t significand = 0; 245 246 /* position in the input string */ 247 int i = 0; 248 249 const char *str = *sptr; 250 long double significand = 0; 251 long exponent = 0; 248 252 249 253 /* number of digits parsed so far */ 250 254 int parsed_digits = 0; 251 252 int exponent = 0; 253 254 const char *str = *sptr; 255 256 /* digits before decimal point */ 257 while (isdigit(str[i])) { 258 if (parsed_digits == 0 && str[i] == '0') { 255 bool after_decimal = false; 256 257 while (isdigit(*str)  (!after_decimal && *str == DECIMAL_POINT)) { 258 if (*str == DECIMAL_POINT) { 259 after_decimal = true; 260 str++; 261 continue; 262 } 263 264 if (parsed_digits == 0 && *str == '0') { 259 265 /* Nothing, just skip leading zeros. */ 260 } else if (parsed_digits < PARSE_DECIMAL_DIGS) { 261 significand *= DEC_BASE; 262 significand += str[i]  '0'; 266 } else if (parsed_digits < LDBL_DIG) { 267 significand = significand * DEC_BASE + (*str  '0'); 263 268 parsed_digits++; 264 269 } else { … … 266 271 } 267 272 268 i++; 269 } 270 271 if (str[i] == DECIMAL_POINT) { 272 i++; 273 274 /* digits after decimal point */ 275 while (isdigit(str[i])) { 276 if (parsed_digits == 0 && str[i] == '0') { 277 /* Skip leading zeros and decrement exponent. */ 278 exponent; 279 } else if (parsed_digits < PARSE_DECIMAL_DIGS) { 280 significand *= DEC_BASE; 281 significand += str[i]  '0'; 282 exponent; 283 parsed_digits++; 284 } else { 285 /* ignore */ 286 } 287 288 i++; 289 } 273 if (after_decimal) { 274 /* Decrement exponent if we are parsing the fractional part. */ 275 exponent; 276 } 277 278 str++; 290 279 } 291 280 292 281 /* exponent */ 293 if (tolower(str[i]) == EXPONENT_MARK) { 294 i++; 295 296 bool negative = false; 297 int exp = 0; 298 299 switch (str[i]) { 300 case '': 301 negative = true; 302 /* fallthrough */ 303 case '+': 304 i++; 305 } 306 307 while (isdigit(str[i])) { 308 if (exp < 65536) { 309 exp *= DEC_BASE; 310 exp += str[i]  '0'; 311 } 312 313 i++; 314 } 315 316 if (negative) { 317 exp = exp; 318 } 319 320 exponent += exp; 321 } 322 323 long double result = (long double) significand; 324 result = mul_pow5(result, exponent); 325 if (result != HUGE_VALL) { 326 result = mul_pow2(result, exponent); 327 } 328 329 *sptr = &str[i]; 330 return result; 282 if (tolower(*str) == EXPONENT_MARK) { 283 str++; 284 285 /* Returns MIN/MAX value on error, which is ok. */ 286 long exp = strtol(str, (char **) &str, DEC_BASE); 287 288 if (exponent > 0 && exp > LONG_MAX  exponent) { 289 exponent = LONG_MAX; 290 } else if (exponent < 0 && exp < LONG_MIN  exponent) { 291 exponent = LONG_MIN; 292 } else { 293 exponent += exp; 294 } 295 } 296 297 *sptr = str; 298 299 /* Return multiplied by a power of ten. */ 300 return mul_pow2(mul_pow5(significand, exponent), exponent); 331 301 } 332 302 … … 347 317 348 318 /** 349 * Get the count of leading zero bits up to the maximum of 3 zero bits.350 *351 * @param val Integer value.352 * @return How many leading zero bits there are. (Maximum is 3)353 */354 static inline int leading_zeros(uint64_t val)355 {356 for (int i = 3; i > 0; i) {357 if ((val >> (64  i)) == 0) {358 return i;359 }360 }361 362 return 0;363 }364 365 /**366 319 * Convert hexadecimal string representation of the floating point number. 367 320 * Function expects the string pointer to be already pointed at the first … … 376 329 static long double parse_hexadecimal(const char **sptr) 377 330 { 378 // TODO: Use strtol(), at least for exponent. 379 380 /* this function currently always rounds to zero */ 381 // TODO: honor rounding mode 331 assert(sptr != NULL && *sptr != NULL); 382 332 383 333 const int DEC_BASE = 10; … … 385 335 const char DECIMAL_POINT = '.'; 386 336 const char EXPONENT_MARK = 'p'; 387 /* The highest amount of digits that can be safely parsed388 * before an overflow occurs.389 */390 const int PARSE_HEX_DIGS = 16;391 392 /* significand */393 uint64_t significand = 0;394 395 /* position in the input string */396 int i = 0;397 398 /* number of digits parsed so far */399 int parsed_digits = 0;400 401 int exponent = 0;402 337 403 338 const char *str = *sptr; 404 405 /* digits before decimal point */ 406 while (posix_isxdigit(str[i])) { 407 if (parsed_digits == 0 && str[i] == '0') { 339 long double significand = 0; 340 long exponent = 0; 341 342 /* number of bits parsed so far */ 343 int parsed_bits = 0; 344 bool after_decimal = false; 345 346 while (posix_isxdigit(*str)  (!after_decimal && *str == DECIMAL_POINT)) { 347 if (*str == DECIMAL_POINT) { 348 after_decimal = true; 349 str++; 350 continue; 351 } 352 353 if (parsed_bits == 0 && *str == '0') { 408 354 /* Nothing, just skip leading zeros. */ 409 } else if (parsed_digits < PARSE_HEX_DIGS) { 410 significand *= HEX_BASE; 411 significand += hex_value(str[i]); 412 parsed_digits++; 413 } else if (parsed_digits == PARSE_HEX_DIGS) { 414 /* The first digit may have had leading zeros, 415 * so we need to parse one more digit and shift 416 * the value accordingly. 417 */ 418 419 int zeros = leading_zeros(significand); 420 significand = (significand << zeros)  421 (hex_value(str[i]) >> (4  zeros)); 422 423 exponent += (4  zeros); 424 parsed_digits++; 355 } else if (parsed_bits <= LDBL_MANT_DIG) { 356 significand = significand * HEX_BASE + hex_value(*str); 357 parsed_bits += 4; 425 358 } else { 426 359 exponent += 4; 427 360 } 428 361 429 i++; 430 } 431 432 if (str[i] == DECIMAL_POINT) { 433 i++; 434 435 /* digits after decimal point */ 436 while (posix_isxdigit(str[i])) { 437 if (parsed_digits == 0 && str[i] == '0') { 438 /* Skip leading zeros and decrement exponent. */ 439 exponent = 4; 440 } else if (parsed_digits < PARSE_HEX_DIGS) { 441 significand *= HEX_BASE; 442 significand += hex_value(str[i]); 443 exponent = 4; 444 parsed_digits++; 445 } else if (parsed_digits == PARSE_HEX_DIGS) { 446 /* The first digit may have had leading zeros, 447 * so we need to parse one more digit and shift 448 * the value accordingly. 449 */ 450 451 int zeros = leading_zeros(significand); 452 significand = (significand << zeros)  453 (hex_value(str[i]) >> (4  zeros)); 454 455 exponent = zeros; 456 parsed_digits++; 457 } else { 458 /* ignore */ 459 } 460 461 i++; 462 } 362 if (after_decimal) { 363 exponent = 4; 364 } 365 366 str++; 463 367 } 464 368 465 369 /* exponent */ 466 if (tolower(str[i]) == EXPONENT_MARK) { 467 i++; 468 469 bool negative = false; 470 int exp = 0; 471 472 switch (str[i]) { 473 case '': 474 negative = true; 475 /* fallthrough */ 476 case '+': 477 i++; 478 } 479 480 while (isdigit(str[i])) { 481 if (exp < 65536) { 482 exp *= DEC_BASE; 483 exp += str[i]  '0'; 484 } 485 486 i++; 487 } 488 489 if (negative) { 490 exp = exp; 491 } 492 493 exponent += exp; 494 } 495 496 long double result = (long double) significand; 497 result = mul_pow2(result, exponent); 498 499 *sptr = &str[i]; 500 return result; 370 if (tolower(*str) == EXPONENT_MARK) { 371 str++; 372 373 /* Returns MIN/MAX value on error, which is ok. */ 374 long exp = strtol(str, (char **) &str, DEC_BASE); 375 376 if (exponent > 0 && exp > LONG_MAX  exponent) { 377 exponent = LONG_MAX; 378 } else if (exponent < 0 && exp < LONG_MIN  exponent) { 379 exponent = LONG_MIN; 380 } else { 381 exponent += exp; 382 } 383 } 384 385 *sptr = str; 386 387 /* Return multiplied by a power of two. */ 388 return mul_pow2(significand, exponent); 501 389 } 502 390
Note: See TracChangeset
for help on using the changeset viewer.