1 /* Copyright 2018 Ulf Adams
2 * Licensed to the Hipparchus project under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /*
19 * This is not the original file distributed by Ulf Adams in project
20 * https://github.com/ulfjack/ryu
21 * It has been modified by the Hipparchus project.
22 */
23 package org.hipparchus.util;
24
25 import java.math.BigInteger;
26
27 import org.hipparchus.exception.LocalizedCoreFormats;
28 import org.hipparchus.exception.MathIllegalArgumentException;
29
30 /**
31 * An implementation of Ryū for double.
32 * <p>
33 * Ryū generates the shortest decimal representation of a floating point number
34 * that maintains round-trip safety. That is, a correct parser can recover the
35 * exact original number. Ryū is very fast (about 10 time faster than {@code
36 * Double.toString()}).
37 * </p>
38 * @see <a href="https://dl.acm.org/citation.cfm?doid=3296979.3192369">Ryū: fast float-to-string conversion</a>
39 */
40 public final class RyuDouble {
41
42 /** Default low switch level to scientific notation. */
43 public static final int DEFAULT_LOW_EXP = -3;
44
45 /** Default high switch level to scientific notation. */
46 public static final int DEFAULT_HIGH_EXP = 7;
47
48 /** Number of bits in a double mantissa. */
49 private static final int DOUBLE_MANTISSA_BITS = 52;
50
51 /** Bit mask for retrieving mantissa. */
52 private static final long DOUBLE_MANTISSA_MASK = (1L << DOUBLE_MANTISSA_BITS) - 1;
53
54 /** Number of bits in a double exponant. */
55 private static final int DOUBLE_EXPONENT_BITS = 11;
56
57 /** Bit mask for retrieving exponent. */
58 private static final int DOUBLE_EXPONENT_MASK = (1 << DOUBLE_EXPONENT_BITS) - 1;
59
60 /** Bias of the exponent. */
61 private static final int DOUBLE_EXPONENT_BIAS = (1 << (DOUBLE_EXPONENT_BITS - 1)) - 1;
62
63 /** Size of the factors table for positive exponents. */
64 private static final int POS_TABLE_SIZE = 326;
65
66 /** Size of the factors table for negative exponents. */
67 private static final int NEG_TABLE_SIZE = 291;
68
69 /** Bit count for complete entries in the positive exponent tables. */
70 private static final int POW5_BITCOUNT = 121; // max 3*31 = 124
71
72 /** Bit count for split entries in the positive exponent tables. */
73 private static final int POW5_QUARTER_BITCOUNT = 31;
74
75 /** Split table for positive exponents. */
76 private static final int[][] POW5_SPLIT = new int[POS_TABLE_SIZE][4];
77
78 /** Bit count for complete entries in the negative exponent tables. */
79 private static final int POW5_INV_BITCOUNT = 122; // max 3*31 = 124
80
81 /** Bit count for split entries in the negative exponent tables. */
82 private static final int POW5_INV_QUARTER_BITCOUNT = 31;
83
84 /** Split table for negative exponents. */
85 private static final int[][] POW5_INV_SPLIT = new int[NEG_TABLE_SIZE][4];
86
87 /** Create the tables. */
88 static {
89 final BigInteger mask = BigInteger.valueOf(1).shiftLeft(POW5_QUARTER_BITCOUNT).subtract(BigInteger.ONE);
90 final BigInteger invMask = BigInteger.valueOf(1).shiftLeft(POW5_INV_QUARTER_BITCOUNT).subtract(BigInteger.ONE);
91 for (int i = 0; i < FastMath.max(POS_TABLE_SIZE, NEG_TABLE_SIZE); i++) {
92 final BigInteger pow = BigInteger.valueOf(5).pow(i);
93 final int pow5len = pow.bitLength();
94 if (i < POW5_SPLIT.length) {
95 for (int j = 0; j < 4; j++) {
96 POW5_SPLIT[i][j] = pow.
97 shiftRight(pow5len - POW5_BITCOUNT + (3 - j) * POW5_QUARTER_BITCOUNT).
98 and(mask).
99 intValueExact();
100 }
101 }
102
103 if (i < POW5_INV_SPLIT.length) {
104 // We want floor(log_2 5^q) here, which is pow5len - 1.
105 final int j = pow5len - 1 + POW5_INV_BITCOUNT;
106 final BigInteger inv = BigInteger.ONE.shiftLeft(j).divide(pow).add(BigInteger.ONE);
107 for (int k = 0; k < 4; k++) {
108 if (k == 0) {
109 POW5_INV_SPLIT[i][k] = inv.shiftRight((3 - k) * POW5_INV_QUARTER_BITCOUNT).intValueExact();
110 } else {
111 POW5_INV_SPLIT[i][k] = inv.shiftRight((3 - k) * POW5_INV_QUARTER_BITCOUNT).and(invMask).intValueExact();
112 }
113 }
114 }
115 }
116 }
117
118 /** Private constructor for a utility class.
119 */
120 private RyuDouble() {
121 // nothing to do
122 }
123
124 /** Convert a double to shortest string representation, preserving full accuracy.
125 * <p>
126 * This implementation uses the same specifications as {@code Double.toString()},
127 * i.e. it uses scientific notation if for numbers smaller than 10⁻³ or larger
128 * than 10⁺⁷, and decimal notion in between. That is it call {@link #doubleToString(double,
129 * int, int) doubleToString(value, -3, 7)}.
130 * </p>
131 * @param value double number to convert
132 * @return shortest string representation
133 * @see #doubleToString(double, int, int)
134 * @see #DEFAULT_LOW_EXP
135 * @see #DEFAULT_HIGH_EXP
136 */
137 public static String doubleToString(double value) {
138 return doubleToString(value, DEFAULT_LOW_EXP, DEFAULT_HIGH_EXP);
139 }
140
141 /** Convert a double to shortest string representation, preserving full accuracy.
142 * <p>
143 * Number inside of the interval [10<sup>lowExp</sup>, 10<sup>highExp</sup>]
144 * are represented using decimal notation, numbers outside of this
145 * range are represented using scientific notation.
146 * </p>
147 * @param value double number to convert
148 * @param lowExp lowest decimal exponent for which decimal notation can be used
149 * @param highExp highest decimal exponent for which decimal notation can be used
150 * @return shortest string representation
151 * @see #doubleToString(double)
152 * @see #DEFAULT_LOW_EXP
153 * @see #DEFAULT_HIGH_EXP
154 */
155 public static String doubleToString(double value, int lowExp, int highExp) {
156 // Step 1: Decode the floating point number, and unify normalized and subnormal cases.
157 // First, handle all the trivial cases.
158 if (Double.isNaN(value)) {
159 return "NaN";
160 }
161 if (value == Double.POSITIVE_INFINITY) {
162 return "Infinity";
163 }
164 if (value == Double.NEGATIVE_INFINITY) {
165 return "-Infinity";
166 }
167 long bits = Double.doubleToLongBits(value);
168 if (bits == 0) {
169 return "0.0";
170 }
171 if (bits == 0x8000000000000000L) {
172 return "-0.0";
173 }
174
175 // Otherwise extract the mantissa and exponent bits and run the full algorithm.
176 final int ieeeExponent = (int) ((bits >>> DOUBLE_MANTISSA_BITS) & DOUBLE_EXPONENT_MASK);
177 final long ieeeMantissa = bits & DOUBLE_MANTISSA_MASK;
178 int e2;
179 final long m2;
180 if (ieeeExponent == 0) {
181 // Denormal number - no implicit leading 1, and the exponent is 1, not 0.
182 e2 = 1 - DOUBLE_EXPONENT_BIAS - DOUBLE_MANTISSA_BITS;
183 m2 = ieeeMantissa;
184 } else {
185 // Add implicit leading 1.
186 e2 = ieeeExponent - DOUBLE_EXPONENT_BIAS - DOUBLE_MANTISSA_BITS;
187 m2 = ieeeMantissa | (1L << DOUBLE_MANTISSA_BITS);
188 }
189
190 final boolean sign = bits < 0;
191
192 // Step 2: Determine the interval of legal decimal representations.
193 final boolean even = (m2 & 1) == 0;
194 final long mv = 4 * m2;
195 final long mp = 4 * m2 + 2;
196 final int mmShift = ((m2 != (1L << DOUBLE_MANTISSA_BITS)) || (ieeeExponent <= 1)) ? 1 : 0;
197 final long mm = 4 * m2 - 1 - mmShift;
198 e2 -= 2;
199
200 // Step 3: Convert to a decimal power base using 128-bit arithmetic.
201 // -1077 = 1 - 1023 - 53 - 2 <= e_2 - 2 <= 2046 - 1023 - 53 - 2 = 968
202 long dv;
203 long dp;
204 long dm;
205 final int e10;
206 boolean dmIsTrailingZeros = false;
207 boolean dvIsTrailingZeros = false;
208 if (e2 >= 0) {
209 final int q = FastMath.max(0, ((e2 * 78913) >>> 18) - 1);
210 // k = constant + floor(log_2(5^q))
211 final int k = POW5_INV_BITCOUNT + pow5bits(q) - 1;
212 final int i = -e2 + q + k;
213 dv = mulPow5InvDivPow2(mv, q, i);
214 dp = mulPow5InvDivPow2(mp, q, i);
215 dm = mulPow5InvDivPow2(mm, q, i);
216 e10 = q;
217
218 if (q <= 21) {
219 if (mv % 5 == 0) {
220 dvIsTrailingZeros = multipleOfPowerOf5(mv, q);
221 } else if (even) {
222 dmIsTrailingZeros = multipleOfPowerOf5(mm, q);
223 } else if (multipleOfPowerOf5(mp, q)) {
224 dp--;
225 }
226 }
227 } else {
228 final int q = FastMath.max(0, ((-e2 * 732923) >>> 20) - 1);
229 final int i = -e2 - q;
230 final int k = pow5bits(i) - POW5_BITCOUNT;
231 final int j = q - k;
232 dv = mulPow5divPow2(mv, i, j);
233 dp = mulPow5divPow2(mp, i, j);
234 dm = mulPow5divPow2(mm, i, j);
235 e10 = q + e2;
236 if (q <= 1) {
237 dvIsTrailingZeros = true;
238 if (even) {
239 dmIsTrailingZeros = mmShift == 1;
240 } else {
241 dp--;
242 }
243 } else if (q < 63) {
244 dvIsTrailingZeros = (mv & ((1L << (q - 1)) - 1)) == 0;
245 }
246 }
247
248 // Step 4: Find the shortest decimal representation in the interval of legal representations.
249 //
250 // We do some extra work here in order to follow Float/Double.toString semantics. In particular,
251 // that requires printing in scientific format if and only if the exponent is between lowExp and highExp,
252 // and it requires printing at least two decimal digits.
253 //
254 // Above, we moved the decimal dot all the way to the right, so now we need to count digits to
255 // figure out the correct exponent for scientific notation.
256 final int vplength = decimalLength(dp);
257 int exp = e10 + vplength - 1;
258
259 // use scientific notation if and only if outside this range.
260 final boolean scientificNotation = !((exp >= lowExp) && (exp < highExp));
261
262 int removed = 0;
263
264 int lastRemovedDigit = 0;
265 long output;
266 if (dmIsTrailingZeros || dvIsTrailingZeros) {
267 while (dp / 10 > dm / 10) {
268 if ((dp < 100) && scientificNotation) {
269 // Double.toString semantics requires printing at least two digits.
270 break;
271 }
272 dmIsTrailingZeros &= dm % 10 == 0;
273 dvIsTrailingZeros &= lastRemovedDigit == 0;
274 lastRemovedDigit = (int) (dv % 10);
275 dp /= 10;
276 dv /= 10;
277 dm /= 10;
278 removed++;
279 }
280 if (dmIsTrailingZeros && even) {
281 while (dm % 10 == 0) {
282 if ((dp < 100) && scientificNotation) {
283 // Double.toString semantics requires printing at least two digits.
284 break;
285 }
286 dvIsTrailingZeros &= lastRemovedDigit == 0;
287 lastRemovedDigit = (int) (dv % 10);
288 dp /= 10;
289 dv /= 10;
290 dm /= 10;
291 removed++;
292 }
293 }
294 if (dvIsTrailingZeros && (lastRemovedDigit == 5) && (dv % 2 == 0)) {
295 // Round even if the exact numbers is .....50..0.
296 lastRemovedDigit = 4;
297 }
298 output = dv +
299 ((dv == dm && !(dmIsTrailingZeros && even)) || (lastRemovedDigit >= 5) ? 1 : 0);
300 } else {
301 while (dp / 10 > dm / 10) {
302 if ((dp < 100) && scientificNotation) {
303 // Double.toString semantics requires printing at least two digits.
304 break;
305 }
306 lastRemovedDigit = (int) (dv % 10);
307 dp /= 10;
308 dv /= 10;
309 dm /= 10;
310 removed++;
311 }
312 output = dv + ((dv == dm || (lastRemovedDigit >= 5)) ? 1 : 0);
313 }
314 int olength = vplength - removed;
315
316 // Step 5: Print the decimal representation.
317 // We follow Double.toString semantics here,
318 // but adjusting the boundaries at which we switch to scientific notation
319 char[] result = new char[14 - lowExp + highExp];
320 int index = 0;
321 if (sign) {
322 result[index++] = '-';
323 }
324
325 // Values in the interval [10^lowExp, 10^highExp) are special.
326 if (scientificNotation) {
327 // Print in the format x.xxxxxE-yy.
328 for (int i = 0; i < olength - 1; i++) {
329 int c = (int) (output % 10);
330 output /= 10;
331 result[index + olength - i] = (char) ('0' + c);
332 }
333 result[index] = (char) ('0' + output % 10);
334 result[index + 1] = '.';
335 index += olength + 1;
336 if (olength == 1) {
337 result[index++] = '0';
338 }
339
340 // Print 'E', the exponent sign, and the exponent, which has at most three digits.
341 result[index++] = 'E';
342 if (exp < 0) {
343 result[index++] = '-';
344 exp = -exp;
345 }
346 if (exp >= 100) {
347 result[index++] = (char) ('0' + exp / 100);
348 exp %= 100;
349 result[index++] = (char) ('0' + exp / 10);
350 } else if (exp >= 10) {
351 result[index++] = (char) ('0' + exp / 10);
352 }
353 result[index++] = (char) ('0' + exp % 10);
354 return String.valueOf(result, 0, index);
355 } else {
356 // Otherwise follow the Java spec for values in the interval [10^lowExp, 10^highExp).
357 if (exp < 0) {
358 // Decimal dot is before any of the digits.
359 result[index++] = '0';
360 result[index++] = '.';
361 for (int i = -1; i > exp; i--) {
362 result[index++] = '0';
363 }
364 int current = index;
365 for (int i = 0; i < olength; i++) {
366 result[current + olength - i - 1] = (char) ('0' + output % 10);
367 output /= 10;
368 index++;
369 }
370 } else if (exp + 1 >= olength) {
371 // Decimal dot is after any of the digits.
372 for (int i = 0; i < olength; i++) {
373 result[index + olength - i - 1] = (char) ('0' + output % 10);
374 output /= 10;
375 }
376 index += olength;
377 for (int i = olength; i < exp + 1; i++) {
378 result[index++] = '0';
379 }
380 result[index++] = '.';
381 result[index++] = '0';
382 } else {
383 // Decimal dot is somewhere between the digits.
384 int current = index + 1;
385 for (int i = 0; i < olength; i++) {
386 if (olength - i - 1 == exp) {
387 result[current + olength - i - 1] = '.';
388 current--;
389 }
390 result[current + olength - i - 1] = (char) ('0' + output % 10);
391 output /= 10;
392 }
393 index += olength + 1;
394 }
395 return String.valueOf(result, 0, index);
396 }
397 }
398
399 /** Get the number of bits of 5<sup>e</sup>.
400 * @param e exponent
401 * @return number of bits of 5<sup>e</sup>
402 */
403 private static int pow5bits(int e) {
404 return ((e * 1217359) >>> 19) + 1;
405 }
406
407 /** Compute decimal length of an integer.
408 * @param v integer to check
409 * @return decimal length of {@code v}
410 */
411 private static int decimalLength(long v) {
412 if (v >= 1000000000000000000L) {
413 return 19;
414 }
415 if (v >= 100000000000000000L) {
416 return 18;
417 }
418 if (v >= 10000000000000000L) {
419 return 17;
420 }
421 if (v >= 1000000000000000L) {
422 return 16;
423 }
424 if (v >= 100000000000000L) {
425 return 15;
426 }
427 if (v >= 10000000000000L) {
428 return 14;
429 }
430 if (v >= 1000000000000L) {
431 return 13;
432 }
433 if (v >= 100000000000L) {
434 return 12;
435 }
436 if (v >= 10000000000L) {
437 return 11;
438 }
439 if (v >= 1000000000L) {
440 return 10;
441 }
442 if (v >= 100000000L) {
443 return 9;
444 }
445 if (v >= 10000000L) {
446 return 8;
447 }
448 if (v >= 1000000L) {
449 return 7;
450 }
451 if (v >= 100000L) {
452 return 6;
453 }
454 if (v >= 10000L) {
455 return 5;
456 }
457 if (v >= 1000L) {
458 return 4;
459 }
460 if (v >= 100L) {
461 return 3;
462 }
463 if (v >= 10L) {
464 return 2;
465 }
466 return 1;
467 }
468
469 private static boolean multipleOfPowerOf5(long value, int q) {
470 return pow5Factor(value) >= q;
471 }
472
473 /** Compute largest power of 5 that divides the value.
474 * @param value value to check
475 * @return largest power of 5 that divides the value
476 */
477 private static int pow5Factor(long value) {
478 // We want to find the largest power of 5 that divides value.
479 if ((value % 5) != 0) {
480 return 0;
481 }
482 if ((value % 25) != 0) {
483 return 1;
484 }
485 if ((value % 125) != 0) {
486 return 2;
487 }
488 if ((value % 625) != 0) {
489 return 3;
490 }
491 int count = 4;
492 value /= 625;
493 while (value > 0) {
494 if (value % 5 != 0) {
495 return count;
496 }
497 value /= 5;
498 count++;
499 }
500 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL, value, 0);
501 }
502
503 /**
504 * Compute the high digits of m * 5^p / 10^q = m * 5^(p - q) / 2^q = m * 5^i / 2^j, with q chosen
505 * such that m * 5^i / 2^j has sufficiently many decimal digits to represent the original floating
506 * point number.
507 * @param m mantissa
508 * @param i power of 5
509 * @param j power of 2
510 * @return high digits of m * 5^i / 2^j
511 */
512 private static long mulPow5divPow2(final long m, final int i, final int j) {
513 // m has at most 55 bits.
514 long mHigh = m >>> 31;
515 long mLow = m & 0x7fffffff;
516 long bits13 = mHigh * POW5_SPLIT[i][0]; // 124
517 long bits03 = mLow * POW5_SPLIT[i][0]; // 93
518 long bits12 = mHigh * POW5_SPLIT[i][1]; // 93
519 long bits02 = mLow * POW5_SPLIT[i][1]; // 62
520 long bits11 = mHigh * POW5_SPLIT[i][2]; // 62
521 long bits01 = mLow * POW5_SPLIT[i][2]; // 31
522 long bits10 = mHigh * POW5_SPLIT[i][3]; // 31
523 long bits00 = mLow * POW5_SPLIT[i][3]; // 0
524 int actualShift = j - 3 * 31 - 21;
525 if (actualShift < 0) {
526 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL,
527 j, 3 * 31 + 21);
528 }
529 return ((((((((bits00 >>> 31) + bits01 + bits10) >>> 31) +
530 bits02 + bits11) >>> 31) +
531 bits03 + bits12) >>> 21) +
532 (bits13 << 10)) >>> actualShift;
533 }
534
535 /**
536 * Compute the high digits of m / 5^i / 2^j such that the result is accurate to at least 9
537 * decimal digits. i and j are already chosen appropriately.
538 * @param m mantissa
539 * @param i power of 5
540 * @param j power of 2
541 * @return high digits of m / 5^i / 2^j
542 */
543 private static long mulPow5InvDivPow2(final long m, final int i, final int j) {
544 // m has at most 55 bits.
545 final long mHigh = m >>> 31;
546 final long mLow = m & 0x7fffffff;
547 final long bits13 = mHigh * POW5_INV_SPLIT[i][0];
548 final long bits03 = mLow * POW5_INV_SPLIT[i][0];
549 final long bits12 = mHigh * POW5_INV_SPLIT[i][1];
550 final long bits02 = mLow * POW5_INV_SPLIT[i][1];
551 final long bits11 = mHigh * POW5_INV_SPLIT[i][2];
552 final long bits01 = mLow * POW5_INV_SPLIT[i][2];
553 final long bits10 = mHigh * POW5_INV_SPLIT[i][3];
554 final long bits00 = mLow * POW5_INV_SPLIT[i][3];
555
556 final int actualShift = j - 3 * 31 - 21;
557 if (actualShift < 0) {
558 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL,
559 j, 3 * 31 + 21);
560 }
561 return ((((((((bits00 >>> 31) + bits01 + bits10) >>> 31) +
562 bits02 + bits11) >>> 31) +
563 bits03 + bits12) >>> 21) +
564 (bits13 << 10)) >>> actualShift;
565 }
566
567 }