Changeset 1b20da0 in mainline for uspace/lib/c/generic/double_to_str.c
- Timestamp:
- 2018-02-28T17:52:03Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3061bc1
- Parents:
- df6ded8
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:26:03)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:52:03)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/double_to_str.c
rdf6ded8 r1b20da0 103 103 104 104 /* Denote 32 bit parts of x a y as: x == a b, y == c d. Then: 105 * a b 105 * a b 106 106 * * c d 107 107 * ---------- … … 126 126 ret.exponent = x.exponent + y.exponent + significand_width; 127 127 128 return ret; 128 return ret; 129 129 } 130 130 … … 146 146 147 147 /** Returns the interval [low, high] of numbers that convert to binary val. */ 148 static void get_normalized_bounds(ieee_double_t val, fp_num_t *high, 148 static void get_normalized_bounds(ieee_double_t val, fp_num_t *high, 149 149 fp_num_t *low, fp_num_t *val_dist) 150 150 { 151 /* 151 /* 152 152 * Only works if val comes directly from extract_ieee_double without 153 * being manipulated in any way (eg it must not be normalized). 153 * being manipulated in any way (eg it must not be normalized). 154 154 */ 155 155 assert(!is_normalized(val.pos_val)); … … 173 173 *high = normalize(*high); 174 174 175 /* 175 /* 176 176 * Lower bound may not be normalized if subtracting 1 unit 177 * reset the most-significant bit to 0. 177 * reset the most-significant bit to 0. 178 178 */ 179 179 low->significand = low->significand << (low->exponent - high->exponent); 180 180 low->exponent = high->exponent; 181 181 182 val_dist->significand = 182 val_dist->significand = 183 183 val_dist->significand << (val_dist->exponent - high->exponent); 184 184 val_dist->exponent = high->exponent; 185 185 } 186 186 187 /** Determines the interval of numbers that have the binary representation 187 /** Determines the interval of numbers that have the binary representation 188 188 * of val. 189 * 189 * 190 190 * Numbers in the range [scaled_upper_bound - bounds_delta, scaled_upper_bound] 191 * have the same double binary representation as val. 191 * have the same double binary representation as val. 192 192 * 193 193 * Bounds are scaled by 10^scale so that alpha <= exponent <= gamma. … … 197 197 * val_dist == (upper_bound - val) * 10^scale 198 198 */ 199 static void calc_scaled_bounds(ieee_double_t val, fp_num_t *scaled_upper_bound, 199 static void calc_scaled_bounds(ieee_double_t val, fp_num_t *scaled_upper_bound, 200 200 fp_num_t *bounds_delta, fp_num_t *val_dist, int *scale) 201 201 { … … 208 208 assert(normalize(val.pos_val).exponent == upper_bound.exponent); 209 209 210 /* 210 /* 211 211 * Find such a cached normalized power of 10 that if multiplied 212 * by upper_bound the binary exponent of upper_bound almost vanishes, 212 * by upper_bound the binary exponent of upper_bound almost vanishes, 213 213 * ie: 214 214 * upper_scaled := upper_bound * 10^scale … … 231 231 assert(alpha <= upper_scaled.exponent && upper_scaled.exponent <= gamma); 232 232 233 /* 233 /* 234 234 * Any value between lower and upper bound would be represented 235 235 * in binary as the double val originated from. The bounds were 236 * however scaled by an imprecise power of 10 (error less than 237 * 1 ulp) so the scaled bounds have an error of less than 1 ulp. 238 * Conservatively round the lower bound up and the upper bound 236 * however scaled by an imprecise power of 10 (error less than 237 * 1 ulp) so the scaled bounds have an error of less than 1 ulp. 238 * Conservatively round the lower bound up and the upper bound 239 239 * down by 1 ulp just to be on the safe side. It avoids pronouncing 240 240 * produced decimal digits as correct if such a decimal number 241 * is close to the bounds to within 1 ulp. 241 * is close to the bounds to within 1 ulp. 242 242 */ 243 243 upper_scaled.significand -= 1; … … 263 263 * 264 264 * delta = upper - lower .. conservative/safe interval 265 * w_dist = upper - w 265 * w_dist = upper - w 266 266 * upper = "number represented by digits in buf" + rest 267 * 268 * Changing buf[len - 1] changes the value represented by buf 267 * 268 * Changing buf[len - 1] changes the value represented by buf 269 269 * by digit_val_diff * scaling, where scaling is shared by 270 * all parameters. 270 * all parameters. 271 271 * 272 272 */ … … 277 277 bool next_in_val_rng = cur_greater_w && (rest + digit_val_diff < delta); 278 278 /* Rounding down by one would bring buf closer to the processed number. */ 279 bool next_closer = next_in_val_rng 279 bool next_closer = next_in_val_rng 280 280 && (rest + digit_val_diff < w_dist || rest - w_dist < w_dist - rest); 281 281 282 /* Of the shortest strings pick the one that is closest to the actual 282 /* Of the shortest strings pick the one that is closest to the actual 283 283 floating point number. */ 284 284 while (next_closer) { … … 291 291 cur_greater_w = rest < w_dist; 292 292 next_in_val_rng = cur_greater_w && (rest + digit_val_diff < delta); 293 next_closer = next_in_val_rng 293 next_closer = next_in_val_rng 294 294 && (rest + digit_val_diff < w_dist || rest - w_dist < w_dist - rest); 295 295 } … … 299 299 /** Generates the shortest accurate decimal string representation. 300 300 * 301 * Outputs (mostly) the shortest accurate string representation 301 * Outputs (mostly) the shortest accurate string representation 302 302 * for the number scaled_upper - val_dist. Numbers in the interval 303 303 * [scaled_upper - delta, scaled_upper] have the same binary … … 305 305 * shortest string representation (up to the rounding of the last 306 306 * digit to bring the shortest string also the closest to the 307 * actual number). 307 * actual number). 308 308 * 309 309 * @param scaled_upper Scaled upper bound of numbers that have the … … 315 315 * decimal string we're generating. 316 316 * @param scale Decimal scaling of the value to convert (ie scaled_upper). 317 * @param buf Buffer to store the string representation. Must be large 317 * @param buf Buffer to store the string representation. Must be large 318 318 * enough to store all digits and a null terminator. At most 319 319 * MAX_DOUBLE_STR_LEN digits will be written (not counting 320 320 * the null terminator). 321 * @param buf_size Size of buf in bytes. 322 * @param dec_exponent Will be set to the decimal exponent of the number 321 * @param buf_size Size of buf in bytes. 322 * @param dec_exponent Will be set to the decimal exponent of the number 323 323 * string in buf. 324 324 * 325 325 * @return Number of digits; negative on failure (eg buffer too small). 326 326 */ 327 static int gen_dec_digits(fp_num_t scaled_upper, fp_num_t delta, 327 static int gen_dec_digits(fp_num_t scaled_upper, fp_num_t delta, 328 328 fp_num_t val_dist, int scale, char *buf, size_t buf_size, int *dec_exponent) 329 329 { 330 /* 331 * The integral part of scaled_upper is 5 to 32 bits long while 330 /* 331 * The integral part of scaled_upper is 5 to 32 bits long while 332 332 * the remaining fractional part is 59 to 32 bits long because: 333 333 * -59 == alpha <= scaled_upper.e <= gamma == -32 … … 341 341 * ` lower 342 342 * 343 */ 343 */ 344 344 assert(scaled_upper.significand != 0); 345 345 assert(alpha <= scaled_upper.exponent && scaled_upper.exponent <= gamma); … … 359 359 360 360 /* 361 * Extract the integral part of scaled_upper. 362 * upper / one == upper >> -one.e 361 * Extract the integral part of scaled_upper. 362 * upper / one == upper >> -one.e 363 363 */ 364 364 uint32_t int_part = (uint32_t)(scaled_upper.significand >> (-one.exponent)); 365 365 366 /* 366 /* 367 367 * Fractional part of scaled_upper. 368 * upper % one == upper & (one.f - 1) 368 * upper % one == upper & (one.f - 1) 369 369 */ 370 370 uint64_t frac_part = scaled_upper.significand & (one.significand - 1); 371 371 372 372 /* 373 * The integral part of upper has at least 5 bits (64 + alpha) and 374 * at most 32 bits (64 + gamma). The integral part has at most 10 375 * decimal digits, so kappa <= 10. 373 * The integral part of upper has at least 5 bits (64 + alpha) and 374 * at most 32 bits (64 + gamma). The integral part has at most 10 375 * decimal digits, so kappa <= 10. 376 376 */ 377 377 int kappa = 10; … … 397 397 } 398 398 399 /* 399 /* 400 400 * Difference between the so far produced decimal number and upper 401 * is calculated as: remaining_int_part * one + frac_part 401 * is calculated as: remaining_int_part * one + frac_part 402 402 */ 403 403 uint64_t remainder = (((uint64_t)int_part) << -one.exponent) + frac_part; … … 422 422 /* 423 423 * Does not overflow because at least 5 upper bits were 424 * taken by the integral part and are now unused in frac_part. 424 * taken by the integral part and are now unused in frac_part. 425 425 */ 426 426 frac_part *= 10; … … 456 456 457 457 /* Of the shortest representations choose the numerically closest one. */ 458 round_last_digit(frac_part, val_dist.significand, delta.significand, 458 round_last_digit(frac_part, val_dist.significand, delta.significand, 459 459 one.significand, buf, len); 460 460 … … 476 476 477 477 478 /** Converts a non-special double into its shortest accurate string 478 /** Converts a non-special double into its shortest accurate string 479 479 * representation. 480 480 * 481 * Produces an accurate string representation, ie the string will 481 * Produces an accurate string representation, ie the string will 482 482 * convert back to the same binary double (eg via strtod). In the 483 483 * vast majority of cases (99%) the string will be the shortest such … … 492 492 * @param ieee_val Binary double description to convert. Must be the product 493 493 * of extract_ieee_double and it must not be a special number. 494 * @param buf Buffer to store the string representation. Must be large 494 * @param buf Buffer to store the string representation. Must be large 495 495 * enough to store all digits and a null terminator. At most 496 496 * MAX_DOUBLE_STR_LEN digits will be written (not counting 497 497 * the null terminator). 498 498 * @param buf_size Size of buf in bytes. 499 * @param dec_exponent Will be set to the decimal exponent of the number 499 * @param dec_exponent Will be set to the decimal exponent of the number 500 500 * string in buf. 501 501 * … … 503 503 * an error: buf too small (or ieee_val.is_special). 504 504 */ 505 int double_to_short_str(ieee_double_t ieee_val, char *buf, size_t buf_size, 505 int double_to_short_str(ieee_double_t ieee_val, char *buf, size_t buf_size, 506 506 int *dec_exponent) 507 507 { … … 523 523 int scale; 524 524 525 calc_scaled_bounds(ieee_val, &scaled_upper_bound, 525 calc_scaled_bounds(ieee_val, &scaled_upper_bound, 526 526 &delta, &val_dist, &scale); 527 527 528 int len = gen_dec_digits(scaled_upper_bound, delta, val_dist, scale, 528 int len = gen_dec_digits(scaled_upper_bound, delta, val_dist, scale, 529 529 buf, buf_size, dec_exponent); 530 530 … … 540 540 * alpha <= exponent <= gamma 541 541 * @param scale Decimal scaling of the value to convert (ie w_scaled). 542 * @param signif_d_cnt Maximum number of significant digits to output. 542 * @param signif_d_cnt Maximum number of significant digits to output. 543 543 * Negative if as many as possible are requested. 544 544 * @param frac_d_cnt Maximum number of fractional digits to output. 545 545 * Negative if as many as possible are requested. 546 546 * Eg. if 2 then 1.234 -> "1.23"; if 2 then 3e-9 -> "0". 547 * @param buf Buffer to store the string representation. Must be large 547 * @param buf Buffer to store the string representation. Must be large 548 548 * enough to store all digits and a null terminator. At most 549 549 * MAX_DOUBLE_STR_LEN digits will be written (not counting 550 550 * the null terminator). 551 * @param buf_size Size of buf in bytes. 551 * @param buf_size Size of buf in bytes. 552 552 * 553 553 * @return Number of digits; negative on failure (eg buffer too small). 554 554 */ 555 static int gen_fixed_dec_digits(fp_num_t w_scaled, int scale, int signif_d_cnt, 555 static int gen_fixed_dec_digits(fp_num_t w_scaled, int scale, int signif_d_cnt, 556 556 int frac_d_cnt, char *buf, size_t buf_size, int *dec_exponent) 557 557 { … … 561 561 } 562 562 563 /* 564 * The integral part of w_scaled is 5 to 32 bits long while the 563 /* 564 * The integral part of w_scaled is 5 to 32 bits long while the 565 565 * remaining fractional part is 59 to 32 bits long because: 566 566 * -59 == alpha <= w_scaled.e <= gamma == -32 567 * 567 * 568 568 * Therefore: 569 569 * | 5..32 bits | 32..59 bits | == w_scaled == w * 10^scale 570 570 * | int_part | frac_part | 571 571 * |0 0 .. 0 1|0 0 .. 0 0| == one == 1.0 572 * | 0 |0 0 .. 0 1| == w_err == 1 * 2^w_scaled.e 572 * | 0 |0 0 .. 0 1| == w_err == 1 * 2^w_scaled.e 573 573 */ 574 574 assert(alpha <= w_scaled.exponent && w_scaled.exponent <= gamma); 575 575 assert(0 != w_scaled.significand); 576 576 577 /* 577 /* 578 578 * Scaling the number being converted by 10^scale introduced 579 579 * an error of less that 1 ulp. The actual value of w_scaled 580 * could lie anywhere between w_scaled.signif +/- w_err. 580 * could lie anywhere between w_scaled.signif +/- w_err. 581 581 * Scale the error locally as we scale the fractional part 582 582 * of w_scaled. … … 589 589 one.exponent = w_scaled.exponent; 590 590 591 /* Extract the integral part of w_scaled. 591 /* Extract the integral part of w_scaled. 592 592 w_scaled / one == w_scaled >> -one.e */ 593 593 uint32_t int_part = (uint32_t)(w_scaled.significand >> (-one.exponent)); … … 598 598 599 599 size_t len = 0; 600 /* 601 * The integral part of w_scaled has at least 5 bits (64 + alpha = 5) 602 * and at most 32 bits (64 + gamma = 32). The integral part has 603 * at most 10 decimal digits, so kappa <= 10. 600 /* 601 * The integral part of w_scaled has at least 5 bits (64 + alpha = 5) 602 * and at most 32 bits (64 + gamma = 32). The integral part has 603 * at most 10 decimal digits, so kappa <= 10. 604 604 */ 605 605 int kappa = 10; … … 607 607 608 608 int rem_signif_d_cnt = signif_d_cnt; 609 int rem_frac_d_cnt = 609 int rem_frac_d_cnt = 610 610 (frac_d_cnt >= 0) ? (kappa - scale + frac_d_cnt) : INT_MAX; 611 611 … … 638 638 /* 639 639 * Does not overflow because at least 5 upper bits were 640 * taken by the integral part and are now unused in frac_part. 640 * taken by the integral part and are now unused in frac_part. 641 641 */ 642 642 frac_part *= 10; … … 673 673 assert(frac_d_cnt < 0 || -frac_d_cnt <= *dec_exponent); 674 674 } else { 675 /* 676 * The number of fractional digits was too limiting to produce 677 * any digits. 675 /* 676 * The number of fractional digits was too limiting to produce 677 * any digits. 678 678 */ 679 679 assert(rem_frac_d_cnt <= 0 || w_scaled.significand == 0); … … 699 699 * Conversion errors are tracked, so all produced digits except the 700 700 * last one are accurate. Garbage digits are never produced. 701 * If the requested number of digits cannot be produced accurately 702 * due to conversion errors less digits are produced than requested 701 * If the requested number of digits cannot be produced accurately 702 * due to conversion errors less digits are produced than requested 703 703 * and the last digit has an error of +/- 1 (so if '7' is the last 704 704 * converted digit it might have been converted to any of '6'..'8' 705 * had the conversion been completely precise). 706 * 707 * If no error occurs at least one digit is output. 708 * 709 * The conversion stops once the requested number of significant or 710 * fractional digits is reached or the conversion error is too large 705 * had the conversion been completely precise). 706 * 707 * If no error occurs at least one digit is output. 708 * 709 * The conversion stops once the requested number of significant or 710 * fractional digits is reached or the conversion error is too large 711 711 * to generate any more digits (whichever happens first). 712 712 * … … 731 731 * of extract_ieee_double and it must not be a special number. 732 732 * @param signif_d_cnt Maximum number of significant digits to produce. 733 * The output is not rounded. 733 * The output is not rounded. 734 734 * Set to a negative value to generate as many digits 735 735 * as accurately possible. 736 736 * @param frac_d_cnt Maximum number of fractional digits to produce including 737 * any zeros immediately trailing the decimal point. 738 * The output is not rounded. 737 * any zeros immediately trailing the decimal point. 738 * The output is not rounded. 739 739 * Set to a negative value to generate as many digits 740 740 * as accurately possible. 741 * @param buf Buffer to store the string representation. Must be large 741 * @param buf Buffer to store the string representation. Must be large 742 742 * enough to store all digits and a null terminator. At most 743 743 * MAX_DOUBLE_STR_LEN digits will be written (not counting 744 744 * the null terminator). 745 745 * @param buf_size Size of buf in bytes. 746 * @param dec_exponent Set to the decimal exponent of the number string 746 * @param dec_exponent Set to the decimal exponent of the number string 747 747 * in buf. 748 748 * 749 749 * @return The number of output digits. A negative value indicates 750 * an error: buf too small (or ieee_val.is_special, or 750 * an error: buf too small (or ieee_val.is_special, or 751 751 * signif_d_cnt == 0). 752 752 */ … … 779 779 780 780 /* Produce decimal digits from the scaled number. */ 781 int len = gen_fixed_dec_digits(w_scaled, scale, signif_d_cnt, frac_d_cnt, 781 int len = gen_fixed_dec_digits(w_scaled, scale, signif_d_cnt, frac_d_cnt, 782 782 buf, buf_size, dec_exponent); 783 783
Note:
See TracChangeset
for help on using the changeset viewer.