1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 // This file is available under and governed by the GNU General Public 27 // License version 2 only, as published by the Free Software Foundation. 28 // However, the following notice accompanied the original version of this 29 // file: 30 // 31 // Copyright 2010 the V8 project authors. All rights reserved. 32 // Redistribution and use in source and binary forms, with or without 33 // modification, are permitted provided that the following conditions are 34 // met: 35 // 36 // * Redistributions of source code must retain the above copyright 37 // notice, this list of conditions and the following disclaimer. 38 // * Redistributions in binary form must reproduce the above 39 // copyright notice, this list of conditions and the following 40 // disclaimer in the documentation and/or other materials provided 41 // with the distribution. 42 // * Neither the name of Google Inc. nor the names of its 43 // contributors may be used to endorse or promote products derived 44 // from this software without specific prior written permission. 45 // 46 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 47 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 48 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 49 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 50 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 51 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 52 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 56 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 58 package jdk.nashorn.internal.runtime.doubleconv; 59 60 // Dtoa implementation based on our own Bignum implementation, supporting 61 // all conversion modes but slightly slower than the specialized implementations. 62 class BignumDtoa { 63 64 private static int normalizedExponent(long significand, int exponent) { 65 assert (significand != 0); 66 while ((significand & IeeeDouble.kHiddenBit) == 0) { 67 significand = significand << 1; 68 exponent = exponent - 1; 69 } 70 return exponent; 71 } 72 73 // Converts the given double 'v' to ascii. 74 // The result should be interpreted as buffer * 10^(point-length). 75 // The buffer will be null-terminated. 76 // 77 // The input v must be > 0 and different from NaN, and Infinity. 78 // 79 // The output depends on the given mode: 80 // - SHORTEST: produce the least amount of digits for which the internal 81 // identity requirement is still satisfied. If the digits are printed 82 // (together with the correct exponent) then reading this number will give 83 // 'v' again. The buffer will choose the representation that is closest to 84 // 'v'. If there are two at the same distance, than the number is round up. 85 // In this mode the 'requested_digits' parameter is ignored. 86 // - FIXED: produces digits necessary to print a given number with 87 // 'requested_digits' digits after the decimal point. The produced digits 88 // might be too short in which case the caller has to fill the gaps with '0's. 89 // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. 90 // Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns 91 // buffer="2", point=0. 92 // Note: the length of the returned buffer has no meaning wrt the significance 93 // of its digits. That is, just because it contains '0's does not mean that 94 // any other digit would not satisfy the internal identity requirement. 95 // - PRECISION: produces 'requested_digits' where the first digit is not '0'. 96 // Even though the length of produced digits usually equals 97 // 'requested_digits', the function is allowed to return fewer digits, in 98 // which case the caller has to fill the missing digits with '0's. 99 // Halfway cases are again rounded up. 100 // 'BignumDtoa' expects the given buffer to be big enough to hold all digits 101 // and a terminating null-character. 102 static void bignumDtoa(final double v, final DtoaMode mode, final int requested_digits, 103 final DtoaBuffer buffer) { 104 assert (v > 0); 105 assert (!IeeeDouble.isSpecial(IeeeDouble.doubleToLong(v))); 106 final long significand; 107 final int exponent; 108 final boolean lower_boundary_is_closer; 109 110 final long l = IeeeDouble.doubleToLong(v); 111 significand = IeeeDouble.significand(l); 112 exponent = IeeeDouble.exponent(l); 113 lower_boundary_is_closer = IeeeDouble.lowerBoundaryIsCloser(l); 114 115 final boolean need_boundary_deltas = mode == DtoaMode.SHORTEST; 116 117 final boolean is_even = (significand & 1) == 0; 118 assert (significand != 0); 119 final int normalizedExponent = normalizedExponent(significand, exponent); 120 // estimated_power might be too low by 1. 121 final int estimated_power = estimatePower(normalizedExponent); 122 123 // Shortcut for Fixed. 124 // The requested digits correspond to the digits after the point. If the 125 // number is much too small, then there is no need in trying to get any 126 // digits. 127 if (mode == DtoaMode.FIXED && -estimated_power - 1 > requested_digits) { 128 buffer.reset(); 129 // Set decimal-point to -requested_digits. This is what Gay does. 130 // Note that it should not have any effect anyways since the string is 131 // empty. 132 buffer.decimalPoint = -requested_digits; 133 return; 134 } 135 136 final Bignum numerator = new Bignum(); 137 final Bignum denominator = new Bignum(); 138 final Bignum delta_minus = new Bignum(); 139 final Bignum delta_plus = new Bignum(); 140 // Make sure the bignum can grow large enough. The smallest double equals 141 // 4e-324. In this case the denominator needs fewer than 324*4 binary digits. 142 // The maximum double is 1.7976931348623157e308 which needs fewer than 143 // 308*4 binary digits. 144 assert (Bignum.kMaxSignificantBits >= 324*4); 145 initialScaledStartValues(significand, exponent, lower_boundary_is_closer, 146 estimated_power, need_boundary_deltas, 147 numerator, denominator, 148 delta_minus, delta_plus); 149 // We now have v = (numerator / denominator) * 10^estimated_power. 150 buffer.decimalPoint = fixupMultiply10(estimated_power, is_even, 151 numerator, denominator, 152 delta_minus, delta_plus); 153 // We now have v = (numerator / denominator) * 10^(decimal_point-1), and 154 // 1 <= (numerator + delta_plus) / denominator < 10 155 switch (mode) { 156 case SHORTEST: 157 generateShortestDigits(numerator, denominator, 158 delta_minus, delta_plus, 159 is_even, buffer); 160 break; 161 case FIXED: 162 bignumToFixed(requested_digits, 163 numerator, denominator, 164 buffer); 165 break; 166 case PRECISION: 167 generateCountedDigits(requested_digits, 168 numerator, denominator, 169 buffer); 170 break; 171 default: 172 throw new RuntimeException(); 173 } 174 } 175 176 177 // The procedure starts generating digits from the left to the right and stops 178 // when the generated digits yield the shortest decimal representation of v. A 179 // decimal representation of v is a number lying closer to v than to any other 180 // double, so it converts to v when read. 181 // 182 // This is true if d, the decimal representation, is between m- and m+, the 183 // upper and lower boundaries. d must be strictly between them if !is_even. 184 // m- := (numerator - delta_minus) / denominator 185 // m+ := (numerator + delta_plus) / denominator 186 // 187 // Precondition: 0 <= (numerator+delta_plus) / denominator < 10. 188 // If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit 189 // will be produced. This should be the standard precondition. 190 static void generateShortestDigits(final Bignum numerator, final Bignum denominator, 191 final Bignum delta_minus, Bignum delta_plus, 192 final boolean is_even, 193 final DtoaBuffer buffer) { 194 // Small optimization: if delta_minus and delta_plus are the same just reuse 195 // one of the two bignums. 196 if (Bignum.equal(delta_minus, delta_plus)) { 197 delta_plus = delta_minus; 198 } 199 for (;;) { 200 final char digit; 201 digit = numerator.divideModuloIntBignum(denominator); 202 assert (digit <= 9); // digit is a uint16_t and therefore always positive. 203 // digit = numerator / denominator (integer division). 204 // numerator = numerator % denominator. 205 buffer.append((char) (digit + '0')); 206 207 // Can we stop already? 208 // If the remainder of the division is less than the distance to the lower 209 // boundary we can stop. In this case we simply round down (discarding the 210 // remainder). 211 // Similarly we test if we can round up (using the upper boundary). 212 final boolean in_delta_room_minus; 213 final boolean in_delta_room_plus; 214 if (is_even) { 215 in_delta_room_minus = Bignum.lessEqual(numerator, delta_minus); 216 } else { 217 in_delta_room_minus = Bignum.less(numerator, delta_minus); 218 } 219 if (is_even) { 220 in_delta_room_plus = 221 Bignum.plusCompare(numerator, delta_plus, denominator) >= 0; 222 } else { 223 in_delta_room_plus = 224 Bignum.plusCompare(numerator, delta_plus, denominator) > 0; 225 } 226 if (!in_delta_room_minus && !in_delta_room_plus) { 227 // Prepare for next iteration. 228 numerator.times10(); 229 delta_minus.times10(); 230 // We optimized delta_plus to be equal to delta_minus (if they share the 231 // same value). So don't multiply delta_plus if they point to the same 232 // object. 233 if (delta_minus != delta_plus) { 234 delta_plus.times10(); 235 } 236 } else if (in_delta_room_minus && in_delta_room_plus) { 237 // Let's see if 2*numerator < denominator. 238 // If yes, then the next digit would be < 5 and we can round down. 239 final int compare = Bignum.plusCompare(numerator, numerator, denominator); 240 if (compare < 0) { 241 // Remaining digits are less than .5. -> Round down (== do nothing). 242 } else if (compare > 0) { 243 // Remaining digits are more than .5 of denominator. -> Round up. 244 // Note that the last digit could not be a '9' as otherwise the whole 245 // loop would have stopped earlier. 246 // We still have an assert here in case the preconditions were not 247 // satisfied. 248 assert (buffer.chars[buffer.length - 1] != '9'); 249 buffer.chars[buffer.length - 1]++; 250 } else { 251 // Halfway case. 252 // TODO(floitsch): need a way to solve half-way cases. 253 // For now let's round towards even (since this is what Gay seems to 254 // do). 255 256 if ((buffer.chars[buffer.length - 1] - '0') % 2 == 0) { 257 // Round down => Do nothing. 258 } else { 259 assert (buffer.chars[buffer.length - 1] != '9'); 260 buffer.chars[buffer.length - 1]++; 261 } 262 } 263 return; 264 } else if (in_delta_room_minus) { 265 // Round down (== do nothing). 266 return; 267 } else { // in_delta_room_plus 268 // Round up. 269 // Note again that the last digit could not be '9' since this would have 270 // stopped the loop earlier. 271 // We still have an ASSERT here, in case the preconditions were not 272 // satisfied. 273 assert (buffer.chars[buffer.length -1] != '9'); 274 buffer.chars[buffer.length - 1]++; 275 return; 276 } 277 } 278 } 279 280 281 // Let v = numerator / denominator < 10. 282 // Then we generate 'count' digits of d = x.xxxxx... (without the decimal point) 283 // from left to right. Once 'count' digits have been produced we decide wether 284 // to round up or down. Remainders of exactly .5 round upwards. Numbers such 285 // as 9.999999 propagate a carry all the way, and change the 286 // exponent (decimal_point), when rounding upwards. 287 static void generateCountedDigits(final int count, 288 final Bignum numerator, final Bignum denominator, 289 final DtoaBuffer buffer) { 290 assert (count >= 0); 291 for (int i = 0; i < count - 1; ++i) { 292 final char digit; 293 digit = numerator.divideModuloIntBignum(denominator); 294 assert (digit <= 9); // digit is a uint16_t and therefore always positive. 295 // digit = numerator / denominator (integer division). 296 // numerator = numerator % denominator. 297 buffer.chars[i] = (char)(digit + '0'); 298 // Prepare for next iteration. 299 numerator.times10(); 300 } 301 // Generate the last digit. 302 char digit; 303 digit = numerator.divideModuloIntBignum(denominator); 304 if (Bignum.plusCompare(numerator, numerator, denominator) >= 0) { 305 digit++; 306 } 307 assert (digit <= 10); 308 buffer.chars[count - 1] = (char) (digit + '0'); 309 // Correct bad digits (in case we had a sequence of '9's). Propagate the 310 // carry until we hat a non-'9' or til we reach the first digit. 311 for (int i = count - 1; i > 0; --i) { 312 if (buffer.chars[i] != '0' + 10) break; 313 buffer.chars[i] = '0'; 314 buffer.chars[i - 1]++; 315 } 316 if (buffer.chars[0] == '0' + 10) { 317 // Propagate a carry past the top place. 318 buffer.chars[0] = '1'; 319 buffer.decimalPoint++; 320 } 321 buffer.length = count; 322 } 323 324 325 // Generates 'requested_digits' after the decimal point. It might omit 326 // trailing '0's. If the input number is too small then no digits at all are 327 // generated (ex.: 2 fixed digits for 0.00001). 328 // 329 // Input verifies: 1 <= (numerator + delta) / denominator < 10. 330 static void bignumToFixed(final int requested_digits, 331 final Bignum numerator, final Bignum denominator, 332 final DtoaBuffer buffer) { 333 // Note that we have to look at more than just the requested_digits, since 334 // a number could be rounded up. Example: v=0.5 with requested_digits=0. 335 // Even though the power of v equals 0 we can't just stop here. 336 if (-buffer.decimalPoint > requested_digits) { 337 // The number is definitively too small. 338 // Ex: 0.001 with requested_digits == 1. 339 // Set decimal-decimalPoint to -requested_digits. This is what Gay does. 340 // Note that it should not have any effect anyways since the string is 341 // empty. 342 buffer.decimalPoint = -requested_digits; 343 buffer.length = 0; 344 // return; 345 } else if (-buffer.decimalPoint == requested_digits) { 346 // We only need to verify if the number rounds down or up. 347 // Ex: 0.04 and 0.06 with requested_digits == 1. 348 assert (buffer.decimalPoint == -requested_digits); 349 // Initially the fraction lies in range (1, 10]. Multiply the denominator 350 // by 10 so that we can compare more easily. 351 denominator.times10(); 352 if (Bignum.plusCompare(numerator, numerator, denominator) >= 0) { 353 // If the fraction is >= 0.5 then we have to include the rounded 354 // digit. 355 buffer.chars[0] = '1'; 356 buffer.length = 1; 357 buffer.decimalPoint++; 358 } else { 359 // Note that we caught most of similar cases earlier. 360 buffer.length = 0; 361 } 362 // return; 363 } else { 364 // The requested digits correspond to the digits after the point. 365 // The variable 'needed_digits' includes the digits before the point. 366 final int needed_digits = buffer.decimalPoint + requested_digits; 367 generateCountedDigits(needed_digits, 368 numerator, denominator, 369 buffer); 370 } 371 } 372 373 374 // Returns an estimation of k such that 10^(k-1) <= v < 10^k where 375 // v = f * 2^exponent and 2^52 <= f < 2^53. 376 // v is hence a normalized double with the given exponent. The output is an 377 // approximation for the exponent of the decimal approimation .digits * 10^k. 378 // 379 // The result might undershoot by 1 in which case 10^k <= v < 10^k+1. 380 // Note: this property holds for v's upper boundary m+ too. 381 // 10^k <= m+ < 10^k+1. 382 // (see explanation below). 383 // 384 // Examples: 385 // EstimatePower(0) => 16 386 // EstimatePower(-52) => 0 387 // 388 // Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0. 389 static int estimatePower(final int exponent) { 390 // This function estimates log10 of v where v = f*2^e (with e == exponent). 391 // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)). 392 // Note that f is bounded by its container size. Let p = 53 (the double's 393 // significand size). Then 2^(p-1) <= f < 2^p. 394 // 395 // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close 396 // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)). 397 // The computed number undershoots by less than 0.631 (when we compute log3 398 // and not log10). 399 // 400 // Optimization: since we only need an approximated result this computation 401 // can be performed on 64 bit integers. On x86/x64 architecture the speedup is 402 // not really measurable, though. 403 // 404 // Since we want to avoid overshooting we decrement by 1e10 so that 405 // floating-point imprecisions don't affect us. 406 // 407 // Explanation for v's boundary m+: the computation takes advantage of 408 // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement 409 // (even for denormals where the delta can be much more important). 410 411 final double k1Log10 = 0.30102999566398114; // 1/lg(10) 412 413 // For doubles len(f) == 53 (don't forget the hidden bit). 414 final int kSignificandSize = IeeeDouble.kSignificandSize; 415 final double estimate = Math.ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10); 416 return (int) estimate; 417 } 418 419 420 // See comments for InitialScaledStartValues. 421 static void initialScaledStartValuesPositiveExponent( 422 final long significand, final int exponent, 423 final int estimated_power, final boolean need_boundary_deltas, 424 final Bignum numerator, final Bignum denominator, 425 final Bignum delta_minus, final Bignum delta_plus) { 426 // A positive exponent implies a positive power. 427 assert (estimated_power >= 0); 428 // Since the estimated_power is positive we simply multiply the denominator 429 // by 10^estimated_power. 430 431 // numerator = v. 432 numerator.assignUInt64(significand); 433 numerator.shiftLeft(exponent); 434 // denominator = 10^estimated_power. 435 denominator.assignPowerUInt16(10, estimated_power); 436 437 if (need_boundary_deltas) { 438 // Introduce a common denominator so that the deltas to the boundaries are 439 // integers. 440 denominator.shiftLeft(1); 441 numerator.shiftLeft(1); 442 // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common 443 // denominator (of 2) delta_plus equals 2^e. 444 delta_plus.assignUInt16((char) 1); 445 delta_plus.shiftLeft(exponent); 446 // Same for delta_minus. The adjustments if f == 2^p-1 are done later. 447 delta_minus.assignUInt16((char) 1); 448 delta_minus.shiftLeft(exponent); 449 } 450 } 451 452 453 // See comments for InitialScaledStartValues 454 static void initialScaledStartValuesNegativeExponentPositivePower( 455 final long significand, final int exponent, 456 final int estimated_power, final boolean need_boundary_deltas, 457 final Bignum numerator, final Bignum denominator, 458 final Bignum delta_minus, final Bignum delta_plus) { 459 // v = f * 2^e with e < 0, and with estimated_power >= 0. 460 // This means that e is close to 0 (have a look at how estimated_power is 461 // computed). 462 463 // numerator = significand 464 // since v = significand * 2^exponent this is equivalent to 465 // numerator = v * / 2^-exponent 466 numerator.assignUInt64(significand); 467 // denominator = 10^estimated_power * 2^-exponent (with exponent < 0) 468 denominator.assignPowerUInt16(10, estimated_power); 469 denominator.shiftLeft(-exponent); 470 471 if (need_boundary_deltas) { 472 // Introduce a common denominator so that the deltas to the boundaries are 473 // integers. 474 denominator.shiftLeft(1); 475 numerator.shiftLeft(1); 476 // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common 477 // denominator (of 2) delta_plus equals 2^e. 478 // Given that the denominator already includes v's exponent the distance 479 // to the boundaries is simply 1. 480 delta_plus.assignUInt16((char) 1); 481 // Same for delta_minus. The adjustments if f == 2^p-1 are done later. 482 delta_minus.assignUInt16((char) 1); 483 } 484 } 485 486 487 // See comments for InitialScaledStartValues 488 static void initialScaledStartValuesNegativeExponentNegativePower( 489 final long significand, final int exponent, 490 final int estimated_power, final boolean need_boundary_deltas, 491 final Bignum numerator, final Bignum denominator, 492 final Bignum delta_minus, final Bignum delta_plus) { 493 // Instead of multiplying the denominator with 10^estimated_power we 494 // multiply all values (numerator and deltas) by 10^-estimated_power. 495 496 // Use numerator as temporary container for power_ten. 497 final Bignum power_ten = numerator; 498 power_ten.assignPowerUInt16(10, -estimated_power); 499 500 if (need_boundary_deltas) { 501 // Since power_ten == numerator we must make a copy of 10^estimated_power 502 // before we complete the computation of the numerator. 503 // delta_plus = delta_minus = 10^estimated_power 504 delta_plus.assignBignum(power_ten); 505 delta_minus.assignBignum(power_ten); 506 } 507 508 // numerator = significand * 2 * 10^-estimated_power 509 // since v = significand * 2^exponent this is equivalent to 510 // numerator = v * 10^-estimated_power * 2 * 2^-exponent. 511 // Remember: numerator has been abused as power_ten. So no need to assign it 512 // to itself. 513 assert (numerator == power_ten); 514 numerator.multiplyByUInt64(significand); 515 516 // denominator = 2 * 2^-exponent with exponent < 0. 517 denominator.assignUInt16((char) 1); 518 denominator.shiftLeft(-exponent); 519 520 if (need_boundary_deltas) { 521 // Introduce a common denominator so that the deltas to the boundaries are 522 // integers. 523 numerator.shiftLeft(1); 524 denominator.shiftLeft(1); 525 // With this shift the boundaries have their correct value, since 526 // delta_plus = 10^-estimated_power, and 527 // delta_minus = 10^-estimated_power. 528 // These assignments have been done earlier. 529 // The adjustments if f == 2^p-1 (lower boundary is closer) are done later. 530 } 531 } 532 533 534 // Let v = significand * 2^exponent. 535 // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator 536 // and denominator. The functions GenerateShortestDigits and 537 // GenerateCountedDigits will then convert this ratio to its decimal 538 // representation d, with the required accuracy. 539 // Then d * 10^estimated_power is the representation of v. 540 // (Note: the fraction and the estimated_power might get adjusted before 541 // generating the decimal representation.) 542 // 543 // The initial start values consist of: 544 // - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power. 545 // - a scaled (common) denominator. 546 // optionally (used by GenerateShortestDigits to decide if it has the shortest 547 // decimal converting back to v): 548 // - v - m-: the distance to the lower boundary. 549 // - m+ - v: the distance to the upper boundary. 550 // 551 // v, m+, m-, and therefore v - m- and m+ - v all share the same denominator. 552 // 553 // Let ep == estimated_power, then the returned values will satisfy: 554 // v / 10^ep = numerator / denominator. 555 // v's boundarys m- and m+: 556 // m- / 10^ep == v / 10^ep - delta_minus / denominator 557 // m+ / 10^ep == v / 10^ep + delta_plus / denominator 558 // Or in other words: 559 // m- == v - delta_minus * 10^ep / denominator; 560 // m+ == v + delta_plus * 10^ep / denominator; 561 // 562 // Since 10^(k-1) <= v < 10^k (with k == estimated_power) 563 // or 10^k <= v < 10^(k+1) 564 // we then have 0.1 <= numerator/denominator < 1 565 // or 1 <= numerator/denominator < 10 566 // 567 // It is then easy to kickstart the digit-generation routine. 568 // 569 // The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST 570 // or BIGNUM_DTOA_SHORTEST_SINGLE. 571 572 static void initialScaledStartValues(final long significand, 573 final int exponent, 574 final boolean lower_boundary_is_closer, 575 final int estimated_power, 576 final boolean need_boundary_deltas, 577 final Bignum numerator, 578 final Bignum denominator, 579 final Bignum delta_minus, 580 final Bignum delta_plus) { 581 if (exponent >= 0) { 582 initialScaledStartValuesPositiveExponent( 583 significand, exponent, estimated_power, need_boundary_deltas, 584 numerator, denominator, delta_minus, delta_plus); 585 } else if (estimated_power >= 0) { 586 initialScaledStartValuesNegativeExponentPositivePower( 587 significand, exponent, estimated_power, need_boundary_deltas, 588 numerator, denominator, delta_minus, delta_plus); 589 } else { 590 initialScaledStartValuesNegativeExponentNegativePower( 591 significand, exponent, estimated_power, need_boundary_deltas, 592 numerator, denominator, delta_minus, delta_plus); 593 } 594 595 if (need_boundary_deltas && lower_boundary_is_closer) { 596 // The lower boundary is closer at half the distance of "normal" numbers. 597 // Increase the common denominator and adapt all but the delta_minus. 598 denominator.shiftLeft(1); // *2 599 numerator.shiftLeft(1); // *2 600 delta_plus.shiftLeft(1); // *2 601 } 602 } 603 604 605 // This routine multiplies numerator/denominator so that its values lies in the 606 // range 1-10. That is after a call to this function we have: 607 // 1 <= (numerator + delta_plus) /denominator < 10. 608 // Let numerator the input before modification and numerator' the argument 609 // after modification, then the output-parameter decimal_point is such that 610 // numerator / denominator * 10^estimated_power == 611 // numerator' / denominator' * 10^(decimal_point - 1) 612 // In some cases estimated_power was too low, and this is already the case. We 613 // then simply adjust the power so that 10^(k-1) <= v < 10^k (with k == 614 // estimated_power) but do not touch the numerator or denominator. 615 // Otherwise the routine multiplies the numerator and the deltas by 10. 616 static int fixupMultiply10(final int estimated_power, final boolean is_even, 617 final Bignum numerator, final Bignum denominator, 618 final Bignum delta_minus, final Bignum delta_plus) { 619 final boolean in_range; 620 final int decimal_point; 621 if (is_even) { 622 // For IEEE doubles half-way cases (in decimal system numbers ending with 5) 623 // are rounded to the closest floating-point number with even significand. 624 in_range = Bignum.plusCompare(numerator, delta_plus, denominator) >= 0; 625 } else { 626 in_range = Bignum.plusCompare(numerator, delta_plus, denominator) > 0; 627 } 628 if (in_range) { 629 // Since numerator + delta_plus >= denominator we already have 630 // 1 <= numerator/denominator < 10. Simply update the estimated_power. 631 decimal_point = estimated_power + 1; 632 } else { 633 decimal_point = estimated_power; 634 numerator.times10(); 635 if (Bignum.equal(delta_minus, delta_plus)) { 636 delta_minus.times10(); 637 delta_plus.assignBignum(delta_minus); 638 } else { 639 delta_minus.times10(); 640 delta_plus.times10(); 641 } 642 } 643 return decimal_point; 644 } 645 646 647 }