core-libs-dev
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
March 2020
- 93 participants
- 96 discussions
19 Mar '20
Please review adding pre-generated RMI stub classes to the jdk repo
and the removal of make files supporting the specific APIs.
It removes a dependency on build time generation invoking RMIC.
RMIC was deprecated in JDK 13 [1].
The source files have been edited to remove or suppress compilation
warnings.
Webrev:
http://cr.openjdk.java.net/~rriggs/webrev-stubs-classes-8241073/
Issue:
https://bugs.openjdk.java.net/browse/JDK-8241073
Thanks, Roger
p.s. A future change will remove the interim build steps
[1] https://bugs.openjdk.java.net/browse/JDK-8217412
4
15
Sponsor Request: 8241097: java/math/BigInteger/largeMemory/SymmetricRangeTests.java requires -XX:+CompactStrings
by Andrew Leonard 19 Mar '20
by Andrew Leonard 19 Mar '20
19 Mar '20
Hi,
Please can I get a sponsor and reviews for the following "patch" to the
SymmetricRangeTests.java test, for bug
https://bugs.openjdk.java.net/browse/JDK-8241097
patch: http://cr.openjdk.java.net/~aleonard/8241097/webrev.00/
The current testcase makes the assumption that -XX:+CompactStrings is the
default, which it is for Hotspot, but that's not necessarily true for all
JVM providers.
Thank you
Andrew
Andrew Leonard
Java Runtimes Development
IBM Hursley
IBM United Kingdom Ltd
internet email: andrew_m_leonard(a)uk.ibm.com
Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU
3
9
[15] RFR: 8202117: com/sun/jndi/ldap/RemoveNamingListenerTest.java fails intermittently: Connection reset
by Chris Yin 19 Mar '20
by Chris Yin 19 Mar '20
19 Mar '20
Hello,
Please review following changes to try to fix intermittent failure of test com/sun/jndi/ldap/RemoveNamingListenerTest.java, thanks
Bug: https://bugs.openjdk.java.net/browse/JDK-8202117
Webrev: http://cr.openjdk.java.net/~xyin/8202117/webrev.00/
According to failure logs, test already run done and give a pass message, but test framework caught “java.lang.RuntimeException: java.net.SocketException: Connection reset” from other thread during test end, go through the test code, LDAPServerHandler thread may throw such exception in specific case. This change will replace test itself implemented TestLDAPServer/LDAPServerHandler with customized BaseLdapServer to fix the corner. I had run the changed test on 4 platforms for total 600 times, no failure observed.
Thanks,
Chris
3
6
[15] RFR: 8241082: Upgrade IANA Language Subtag Registry data to 03-16-2020 version
by naoto.sato@oracle.com 18 Mar '20
by naoto.sato@oracle.com 18 Mar '20
18 Mar '20
Hello,
Please review the fix to the following issue:
https://bugs.openjdk.java.net/browse/JDK-8241082
The proposed changeset is located at:
http://cr.openjdk.java.net/~naoto/8241082/webrev.00/
It is simply updating the data file. Since there is no change in
equivalency of language tags, no code change and test change was needed
except for the data release date. Instead, I modified the equiv-map
source code generator to explicitly specify the initial capacity for
hash maps.
Naoto
3
4
RFR 8214245 : Case insensitive matching doesn't work correctly for some character classes
by Ivan Gerasimov 18 Mar '20
by Ivan Gerasimov 18 Mar '20
18 Mar '20
Hello!
It turns out, that the case-insensitive j.u.regex.Pattern still pays
attention to the characters case when certain char classes are used.
For example \p{IsLowerCase}, \p{IsUpperCase} and \p{IsTitleCase}
continue to recognize only lower, upper and title case characters, even
in case-insensitive context.
For example, for POSIX char classes this behavior contradicts this
paragraph:
"""
9.2 Regular Expression General Requirements
...
When a standard utility or function that uses regular expressions
specifies that pattern matching shall be performed without regard to the
case (uppercase or lowercase) of either data or patterns, then when each
character in the string is matched against the pattern, not only the
character, but also its case counterpart (if any), shall be matched.
This definition of case-insensitive processing is intended to allow
matching of multi-character collating elements as well as characters, as
each character in the string is matched using both its cases.
...
"""
I also checked how Perl is dealing with in such situation, and yes, it
ignores the case with various \p{} classes when they are used in
case-insensitive context, so all these tests run fine:
'A' =~ /\p{Lower}/i or die;
'a' =~ /\p{Upper}/i or die;
'A' =~ /\p{gc=Lt}/i or die; # title case
'a' =~ /\p{IsTitlecase}/i or die;
'Lj' =~ /\p{Lower}/i or die; # title-cased digraph
'lj' =~ /\p{Upper}/i or die;
'LJ' =~ /\p{Lt}/i or die;
For reference, here's a lengthy document, describing precise rules used
by Perl to deal with \p{} char classes:
https://perldoc.perl.org/perluniprops.html#Properties-accessible-through-%5…
So, for any Lower, Upper or Title case chars in case-insensitive context
Perl uses set of "Cased Letters", with is just a combination of these
three categories (aka "LC" general category).
Would you please help review the patch?
BUGURL: https://bugs.openjdk.java.net/browse/JDK-8214245
WEBREV: http://cr.openjdk.java.net/~igerasim/8214245/00/webrev/
--
With kind regards,
Ivan Gerasimov
3
8
I was looking at GraalVM in order to try out FastR, a jre based R language implementation.
It seemed to me if it was actually a standalone JRE I should be able to use jpackage to turn it into an application. Or use my usual application for trying things out but just replace the runtime.
It seems to work for running the application. I seem to be able to use the included RScript command to run R files. I can’t use the R command due to limitations in my own code. Otherwise the normal application functionality appears to work.
However, If I try a simple test for programmatic R access the application crashes with…
Exception Type: EXC_BAD_ACCESS (Code Signature Invalid)
If I check…
codesign -dv outFastR/FastRGraalHP.app
Executable=/Users/mjh/HalfPipe/HalfPipe_jpkg/outFastR/FastRGraalHP.app/Contents/MacOS/FastRGraalHP
Identifier=jpackageapplauncher
…
It does appear that jpackage is doing some default code signing.
I guess my question would be if it could be possible to omit the signing. Where I assume the application would be subject to the usual Gatekeeper ‘use at your own risk’ messages. But could be runnable.
I see there are signing parameters in the help but I currently don’t have ADC certificates. That includes —mac-sign to indicate signing should be done. Could there be some way to get none?
Or supported is that you must get the signing certs?
It doesn’t make sense to me that you can fully use the included commands but can’t have programmatic access. How is that less secure? But it seems to be the case.
I realize jpackage is probably not intended to support GraalVM. But it is possible it’s use could be extended even if unsupported.
2
4
RFR CSR JDK-8202555: Double.toString(double) sometimes produces incorrect results
by Raffaello Giulietti 17 Mar '20
by Raffaello Giulietti 17 Mar '20
17 Mar '20
Hello,
there's a new version of the documentation [1] for the attached patch to
solve the long standing issues described in [2]. The CSR referred to in
the subject is in [3].
Besides many improvements in the proofs, a couple of simplifications and
a better overall organization (this is my hope), I could find an ideal
treatment of a special case that in the previous inception had a ugly,
yet pragmatic solution in form of rather ad-hoc switch constructs. The
new approach is mathematically clean and makes the code some lines shorter.
The new code reflects this improvement and also adds a couple of
additional tests.
Passes tier1 tests.
@BrianBurkalter
Brian, can you please upload the patch to webrev? As usual, there's an
email attachemnt for your benefit. Thanks.
Greetings
Raffaello
----
[1] https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
[2] https://bugs.openjdk.java.net/browse/JDK-4511638
[3] https://bugs.openjdk.java.net/browse/JDK-8202555
----
# HG changeset patch
# User lello <raffaello.giulietti(a)gmail.com>
# Date 1584472052 -3600
# Tue Mar 17 20:07:32 2020 +0100
# Node ID ec615c419ab236ae291651f5a810807f05fb4421
# Parent 42b62267498dbea03a82eeb073c6020b4b43d288
Patch to fix JDK-4511638
4511638: Double.toString(double) sometimes produces incorrect results
Reviewed-by: TBD
Contributed-by: Raffaello Giulietti <raffaello.giulietti(a)gmail.com>
diff --git
a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
@@ -25,8 +25,10 @@
package java.lang;
-import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.DoubleToDecimal;
+import jdk.internal.math.FloatToDecimal;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Spliterator;
import java.util.stream.IntStream;
@@ -880,7 +882,11 @@
* @return a reference to this object.
*/
public AbstractStringBuilder append(float f) {
- FloatingDecimal.appendTo(f,this);
+ try {
+ FloatToDecimal.appendTo(f, this);
+ } catch (IOException ignored) {
+ assert false;
+ }
return this;
}
@@ -897,7 +903,11 @@
* @return a reference to this object.
*/
public AbstractStringBuilder append(double d) {
- FloatingDecimal.appendTo(d,this);
+ try {
+ DoubleToDecimal.appendTo(d, this);
+ } catch (IOException ignored) {
+ assert false;
+ }
return this;
}
diff --git a/src/java.base/share/classes/java/lang/Double.java
b/src/java.base/share/classes/java/lang/Double.java
--- a/src/java.base/share/classes/java/lang/Double.java
+++ b/src/java.base/share/classes/java/lang/Double.java
@@ -32,6 +32,7 @@
import jdk.internal.math.FloatingDecimal;
import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.DoubleToDecimal;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
@@ -145,69 +146,120 @@
public static final Class<Double> TYPE = (Class<Double>)
Class.getPrimitiveClass("double");
/**
- * Returns a string representation of the {@code double}
- * argument. All characters mentioned below are ASCII characters.
- * <ul>
- * <li>If the argument is NaN, the result is the string
- * "{@code NaN}".
- * <li>Otherwise, the result is a string that represents the sign and
- * magnitude (absolute value) of the argument. If the sign is negative,
- * the first character of the result is '{@code -}'
- * ({@code '\u005Cu002D'}); if the sign is positive, no sign character
- * appears in the result. As for the magnitude <i>m</i>:
- * <ul>
- * <li>If <i>m</i> is infinity, it is represented by the characters
- * {@code "Infinity"}; thus, positive infinity produces the result
- * {@code "Infinity"} and negative infinity produces the result
- * {@code "-Infinity"}.
- *
- * <li>If <i>m</i> is zero, it is represented by the characters
- * {@code "0.0"}; thus, negative zero produces the result
- * {@code "-0.0"} and positive zero produces the result
- * {@code "0.0"}.
+ * Returns a string rendering of the {@code double} argument.
*
- * <li>If <i>m</i> is greater than or equal to 10<sup>-3</sup> but less
- * than 10<sup>7</sup>, then it is represented as the integer part of
- * <i>m</i>, in decimal form with no leading zeroes, followed by
- * '{@code .}' ({@code '\u005Cu002E'}), followed by one or
- * more decimal digits representing the fractional part of <i>m</i>.
- *
- * <li>If <i>m</i> is less than 10<sup>-3</sup> or greater than or
- * equal to 10<sup>7</sup>, then it is represented in so-called
- * "computerized scientific notation." Let <i>n</i> be the unique
- * integer such that 10<sup><i>n</i></sup> ≤ <i>m</i> {@literal <}
- * 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
- * mathematically exact quotient of <i>m</i> and
- * 10<sup><i>n</i></sup> so that 1 ≤ <i>a</i> {@literal <} 10. The
- * magnitude is then represented as the integer part of <i>a</i>,
- * as a single decimal digit, followed by '{@code .}'
- * ({@code '\u005Cu002E'}), followed by decimal digits
- * representing the fractional part of <i>a</i>, followed by the
- * letter '{@code E}' ({@code '\u005Cu0045'}), followed
- * by a representation of <i>n</i> as a decimal integer, as
- * produced by the method {@link Integer#toString(int)}.
+ * <p>The characters of the result are all drawn from the ASCII set.
+ * <ul>
+ * <li> Any NaN, whether quiet or signaling, is rendered as
+ * {@code "NaN"}, regardless of the sign bit.
+ * <li> The infinities +∞ and -∞ are rendered as
+ * {@code "Infinity"} and {@code "-Infinity"}, respectively.
+ * <li> The positive and negative zeroes are rendered as
+ * {@code "0.0"} and {@code "-0.0"}, respectively.
+ * <li> A finite negative {@code v} is rendered as the sign
+ * '{@code -}' followed by the rendering of the magnitude -{@code v}.
+ * <li> A finite positive {@code v} is rendered in two stages:
+ * <ul>
+ * <li> <em>Selection of a decimal</em>: A well-defined
+ * decimal <i>d</i><sub><code>v</code></sub> is selected
+ * to represent {@code v}.
+ * <li> <em>Formatting as a string</em>: The decimal
+ * <i>d</i><sub><code>v</code></sub> is formatted as a string,
+ * either in plain or in computerized scientific notation,
+ * depending on its value.
* </ul>
* </ul>
- * How many digits must be printed for the fractional part of
- * <i>m</i> or <i>a</i>? There must be at least one digit to represent
- * the fractional part, and beyond that as many, but only as many, more
- * digits as are needed to uniquely distinguish the argument value from
- * adjacent values of type {@code double}. That is, suppose that
- * <i>x</i> is the exact mathematical value represented by the decimal
- * representation produced by this method for a finite nonzero argument
- * <i>d</i>. Then <i>d</i> must be the {@code double} value nearest
- * to <i>x</i>; or if two {@code double} values are equally close
- * to <i>x</i>, then <i>d</i> must be one of them and the least
- * significant bit of the significand of <i>d</i> must be {@code 0}.
+ *
+ * <p>A <em>decimal</em> is a number of the form
+ * <i>d</i>×10<sup><i>i</i></sup>
+ * for some (unique) integers <i>d</i> > 0 and <i>i</i> such that
+ * <i>d</i> is not a multiple of 10.
+ * These integers are the <em>significand</em> and
+ * the <em>exponent</em>, respectively, of the decimal.
+ * The <em>length</em> of the decimal is the (unique)
+ * integer <i>n</i> meeting
+ * 10<sup><i>n</i>-1</sup> ≤ <i>d</i> < 10<sup><i>n</i></sup>.
+ *
+ * <p>The decimal <i>d</i><sub><code>v</code></sub>
+ * for a finite positive {@code v} is defined as follows:
+ * <ul>
+ * <li>Let <i>R</i> be the set of all decimals that round to {@code v}
+ * according to the usual round-to-closest rule of
+ * IEEE 754 floating-point arithmetic.
+ * <li>Let <i>m</i> be the minimal length over all decimals in
<i>R</i>.
+ * <li>When <i>m</i> ≥ 2, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length <i>m</i>.
+ * Otherwise, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length 1 or 2.
+ * <li>Define <i>d</i><sub><code>v</code></sub> as
+ * the decimal in <i>T</i> that is closest to {@code v}.
+ * Or if there are two such decimals in <i>T</i>,
+ * select the one with the even significand (there is exactly one).
+ * </ul>
+ *
+ * <p>The (uniquely) selected decimal <i>d</i><sub><code>v</code></sub>
+ * is then formatted.
*
- * <p>To create localized string representations of a floating-point
- * value, use subclasses of {@link java.text.NumberFormat}.
+ * <p>Let <i>d</i>, <i>i</i> and <i>n</i> be the significand,
exponent and
+ * length of <i>d</i><sub><code>v</code></sub>, respectively.
+ * Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>
+ * be the usual decimal expansion of the significand.
+ * Note that <i>d</i><sub>1</sub> ≠ 0 ≠
<i>d</i><sub><i>n</i></sub>.
+ * <ul>
+ * <li>Case -3 ≤ <i>e</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <code>0.0</code>…<code>0</code><!--
+ * --><i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>,
+ * where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
+ * the decimal point and <i>d</i><sub>1</sub>.
+ * For example, 123 × 10<sup>-4</sup> is formatted as
+ * {@code 0.0123}.
+ * <li>Case 0 ≤ <i>e</i> < 7:
+ * <ul>
+ * <li>Subcase <i>i</i> ≥ 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub><!--
+ * --><code>0</code>…<code>0.0</code>,
+ * where there are exactly <i>i</i> zeroes
+ * between <i>d</i><sub><i>n</i></sub> and the decimal point.
+ * For example, 123 × 10<sup>2</sup> is formatted as
+ * {@code 12300.0}.
+ * <li>Subcase <i>i</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i></sub>.<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i>+1</sub>…<!--
+ * --><i>d</i><sub><i>n</i></sub>.
+ * There are exactly -<i>i</i> digits to the right of
+ * the decimal point.
+ * For example, 123 × 10<sup>-1</sup> is formatted as
+ * {@code 12.3}.
+ * </ul>
+ * <li>Case <i>e</i> < -3 or <i>e</i> ≥ 7:
+ * computerized scientific notation is used to format
+ * <i>d</i><sub><code>v</code></sub>.
+ * Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
+ * <ul>
+ * <li>Subcase <i>n</i> = 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.0E</code><i>e</i>.
+ * For example, 1 × 10<sup>23</sup> is formatted as
+ * {@code 1.0E23}.
+ * <li>Subcase <i>n</i> > 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.</code><i>d</i><sub>2</sub><!--
+ * -->…<i>d</i><sub><i>n</i></sub><code>E</code><i>e</i>.
+ * For example, 123 × 10<sup>-21</sup> is formatted as
+ * {@code 1.23E-19}.
+ * </ul>
+ * </ul>
*
- * @param d the {@code double} to be converted.
- * @return a string representation of the argument.
+ * @param v the {@code double} to be rendered.
+ * @return a string rendering of the argument.
*/
- public static String toString(double d) {
- return FloatingDecimal.toJavaFormatString(d);
+ public static String toString(double v) {
+ return DoubleToDecimal.toString(v);
}
/**
diff --git a/src/java.base/share/classes/java/lang/Float.java
b/src/java.base/share/classes/java/lang/Float.java
--- a/src/java.base/share/classes/java/lang/Float.java
+++ b/src/java.base/share/classes/java/lang/Float.java
@@ -31,6 +31,7 @@
import java.util.Optional;
import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.FloatToDecimal;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
@@ -142,73 +143,120 @@
public static final Class<Float> TYPE = (Class<Float>)
Class.getPrimitiveClass("float");
/**
- * Returns a string representation of the {@code float}
- * argument. All characters mentioned below are ASCII characters.
- * <ul>
- * <li>If the argument is NaN, the result is the string
- * "{@code NaN}".
- * <li>Otherwise, the result is a string that represents the sign and
- * magnitude (absolute value) of the argument. If the sign is
- * negative, the first character of the result is
- * '{@code -}' ({@code '\u005Cu002D'}); if the sign is
- * positive, no sign character appears in the result. As for
- * the magnitude <i>m</i>:
+ * Returns a string rendering of the {@code float} argument.
+ *
+ * <p>The characters of the result are all drawn from the ASCII set.
* <ul>
- * <li>If <i>m</i> is infinity, it is represented by the characters
- * {@code "Infinity"}; thus, positive infinity produces
- * the result {@code "Infinity"} and negative infinity
- * produces the result {@code "-Infinity"}.
- * <li>If <i>m</i> is zero, it is represented by the characters
- * {@code "0.0"}; thus, negative zero produces the result
- * {@code "-0.0"} and positive zero produces the result
- * {@code "0.0"}.
- * <li> If <i>m</i> is greater than or equal to 10<sup>-3</sup> but
- * less than 10<sup>7</sup>, then it is represented as the
- * integer part of <i>m</i>, in decimal form with no leading
- * zeroes, followed by '{@code .}'
- * ({@code '\u005Cu002E'}), followed by one or more
- * decimal digits representing the fractional part of
- * <i>m</i>.
- * <li> If <i>m</i> is less than 10<sup>-3</sup> or greater than or
- * equal to 10<sup>7</sup>, then it is represented in
- * so-called "computerized scientific notation." Let <i>n</i>
- * be the unique integer such that 10<sup><i>n</i> </sup>≤
- * <i>m</i> {@literal <} 10<sup><i>n</i>+1</sup>; then let
<i>a</i>
- * be the mathematically exact quotient of <i>m</i> and
- * 10<sup><i>n</i></sup> so that 1 ≤ <i>a</i> {@literal <} 10.
- * The magnitude is then represented as the integer part of
- * <i>a</i>, as a single decimal digit, followed by
- * '{@code .}' ({@code '\u005Cu002E'}), followed by
- * decimal digits representing the fractional part of
- * <i>a</i>, followed by the letter '{@code E}'
- * ({@code '\u005Cu0045'}), followed by a representation
- * of <i>n</i> as a decimal integer, as produced by the
- * method {@link java.lang.Integer#toString(int)}.
- *
+ * <li> Any NaN, whether quiet or signaling, is rendered as
+ * {@code "NaN"}, regardless of the sign bit.
+ * <li> The infinities +∞ and -∞ are rendered as
+ * {@code "Infinity"} and {@code "-Infinity"}, respectively.
+ * <li> The positive and negative zeroes are rendered as
+ * {@code "0.0"} and {@code "-0.0"}, respectively.
+ * <li> A finite negative {@code v} is rendered as the sign
+ * '{@code -}' followed by the rendering of the magnitude -{@code v}.
+ * <li> A finite positive {@code v} is rendered in two stages:
+ * <ul>
+ * <li> <em>Selection of a decimal</em>: A well-defined
+ * decimal <i>d</i><sub><code>v</code></sub> is selected
+ * to represent {@code v}.
+ * <li> <em>Formatting as a string</em>: The decimal
+ * <i>d</i><sub><code>v</code></sub> is formatted as a string,
+ * either in plain or in computerized scientific notation,
+ * depending on its value.
* </ul>
* </ul>
- * How many digits must be printed for the fractional part of
- * <i>m</i> or <i>a</i>? There must be at least one digit
- * to represent the fractional part, and beyond that as many, but
- * only as many, more digits as are needed to uniquely distinguish
- * the argument value from adjacent values of type
- * {@code float}. That is, suppose that <i>x</i> is the
- * exact mathematical value represented by the decimal
- * representation produced by this method for a finite nonzero
- * argument <i>f</i>. Then <i>f</i> must be the {@code float}
- * value nearest to <i>x</i>; or, if two {@code float} values are
- * equally close to <i>x</i>, then <i>f</i> must be one of
- * them and the least significant bit of the significand of
- * <i>f</i> must be {@code 0}.
+ *
+ * <p>A <em>decimal</em> is a number of the form
+ * <i>d</i>×10<sup><i>i</i></sup>
+ * for some (unique) integers <i>d</i> > 0 and <i>i</i> such that
+ * <i>d</i> is not a multiple of 10.
+ * These integers are the <em>significand</em> and
+ * the <em>exponent</em>, respectively, of the decimal.
+ * The <em>length</em> of the decimal is the (unique)
+ * integer <i>n</i> meeting
+ * 10<sup><i>n</i>-1</sup> ≤ <i>d</i> < 10<sup><i>n</i></sup>.
+ *
+ * <p>The decimal <i>d</i><sub><code>v</code></sub>
+ * for a finite positive {@code v} is defined as follows:
+ * <ul>
+ * <li>Let <i>R</i> be the set of all decimals that round to {@code v}
+ * according to the usual round-to-closest rule of
+ * IEEE 754 floating-point arithmetic.
+ * <li>Let <i>m</i> be the minimal length over all decimals in
<i>R</i>.
+ * <li>When <i>m</i> ≥ 2, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length <i>m</i>.
+ * Otherwise, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length 1 or 2.
+ * <li>Define <i>d</i><sub><code>v</code></sub> as
+ * the decimal in <i>T</i> that is closest to {@code v}.
+ * Or if there are two such decimals in <i>T</i>,
+ * select the one with the even significand (there is exactly one).
+ * </ul>
+ *
+ * <p>The (uniquely) selected decimal <i>d</i><sub><code>v</code></sub>
+ * is then formatted.
*
- * <p>To create localized string representations of a floating-point
- * value, use subclasses of {@link java.text.NumberFormat}.
+ * <p>Let <i>d</i>, <i>i</i> and <i>n</i> be the significand,
exponent and
+ * length of <i>d</i><sub><code>v</code></sub>, respectively.
+ * Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>
+ * be the usual decimal expansion of the significand.
+ * Note that <i>d</i><sub>1</sub> ≠ 0 ≠
<i>d</i><sub><i>n</i></sub>.
+ * <ul>
+ * <li>Case -3 ≤ <i>e</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <code>0.0</code>…<code>0</code><!--
+ * --><i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>,
+ * where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
+ * the decimal point and <i>d</i><sub>1</sub>.
+ * For example, 123 × 10<sup>-4</sup> is formatted as
+ * {@code 0.0123}.
+ * <li>Case 0 ≤ <i>e</i> < 7:
+ * <ul>
+ * <li>Subcase <i>i</i> ≥ 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub><!--
+ * --><code>0</code>…<code>0.0</code>,
+ * where there are exactly <i>i</i> zeroes
+ * between <i>d</i><sub><i>n</i></sub> and the decimal point.
+ * For example, 123 × 10<sup>2</sup> is formatted as
+ * {@code 12300.0}.
+ * <li>Subcase <i>i</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i></sub>.<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i>+1</sub>…<!--
+ * --><i>d</i><sub><i>n</i></sub>.
+ * There are exactly -<i>i</i> digits to the right of
+ * the decimal point.
+ * For example, 123 × 10<sup>-1</sup> is formatted as
+ * {@code 12.3}.
+ * </ul>
+ * <li>Case <i>e</i> < -3 or <i>e</i> ≥ 7:
+ * computerized scientific notation is used to format
+ * <i>d</i><sub><code>v</code></sub>.
+ * Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
+ * <ul>
+ * <li>Subcase <i>n</i> = 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.0E</code><i>e</i>.
+ * For example, 1 × 10<sup>23</sup> is formatted as
+ * {@code 1.0E23}.
+ * <li>Subcase <i>n</i> > 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.</code><i>d</i><sub>2</sub><!--
+ * -->…<i>d</i><sub><i>n</i></sub><code>E</code><i>e</i>.
+ * For example, 123 × 10<sup>-21</sup> is formatted as
+ * {@code 1.23E-19}.
+ * </ul>
+ * </ul>
*
- * @param f the float to be converted.
- * @return a string representation of the argument.
+ * @param v the {@code float} to be rendered.
+ * @return a string rendering of the argument.
*/
- public static String toString(float f) {
- return FloatingDecimal.toJavaFormatString(f);
+ public static String toString(float v) {
+ return FloatToDecimal.toString(v);
}
/**
diff --git
a/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java
b/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java
@@ -0,0 +1,644 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+import java.io.IOException;
+
+import static java.lang.Double.*;
+import static java.lang.Long.*;
+import static java.lang.Math.multiplyHigh;
+import static jdk.internal.math.MathUtils.*;
+
+/**
+ * This class exposes a method to render a {@code double} as a string.
+ *
+ * @author Raffaello Giulietti
+ */
+final public class DoubleToDecimal {
+ /*
+ For full details about this code see the following references:
+
+ [1] Giulietti, "The Schubfach way to render doubles",
+ https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
+
+ [2] IEEE Computer Society, "IEEE Standard for Floating-Point
Arithmetic"
+
+ [3] Bouvier & Zimmermann, "Division-Free Binary-to-Decimal Conversion"
+
+ Divisions are avoided altogether for the benefit of those architectures
+ that do not provide specific machine instructions or where they are
slow.
+ This is discussed in section 10 of [1].
+ */
+
+ // The precision in bits.
+ static final int P = 53;
+
+ // Exponent width in bits.
+ private static final int W = (Double.SIZE - 1) - (P - 1);
+
+ // Minimum value of the exponent: -(2^(W-1)) - P + 3.
+ static final int Q_MIN = (-1 << W - 1) - P + 3;
+
+ // Maximum value of the exponent: 2^(W-1) - P.
+ static final int Q_MAX = (1 << W - 1) - P;
+
+ // 10^(E_MIN - 1) <= MIN_VALUE < 10^E_MIN
+ static final int E_MIN = -323;
+
+ // 10^(E_MAX - 1) <= MAX_VALUE < 10^E_MAX
+ static final int E_MAX = 309;
+
+ // Threshold to detect tiny values, as in section 8.1.1 of [1]
+ static final long C_TINY = 3;
+
+ // The minimum and maximum k, as in section 8 of [1]
+ static final int K_MIN = -324;
+ static final int K_MAX = 292;
+
+ // H is as in section 8 of [1].
+ static final int H = 17;
+
+ // Minimum value of the significand of a normal value: 2^(P-1).
+ private static final long C_MIN = 1L << P - 1;
+
+ // Mask to extract the biased exponent.
+ private static final int BQ_MASK = (1 << W) - 1;
+
+ // Mask to extract the fraction bits.
+ private static final long T_MASK = (1L << P - 1) - 1;
+
+ // Used in rop().
+ private static final long MASK_63 = (1L << 63) - 1;
+
+ // Used for left-to-tight digit extraction.
+ private static final int MASK_28 = (1 << 28) - 1;
+
+ private static final int NON_SPECIAL = 0;
+ private static final int PLUS_ZERO = 1;
+ private static final int MINUS_ZERO = 2;
+ private static final int PLUS_INF = 3;
+ private static final int MINUS_INF = 4;
+ private static final int NAN = 5;
+
+ // For thread-safety, each thread gets its own instance of this class.
+ private static final ThreadLocal<DoubleToDecimal> threadLocal =
+ ThreadLocal.withInitial(DoubleToDecimal::new);
+
+ /*
+ Room for the longer of the forms
+ -ddddd.dddddddddddd H + 2 characters
+ -0.00ddddddddddddddddd H + 5 characters
+ -d.ddddddddddddddddE-eee H + 7 characters
+ where there are H digits d
+ */
+ public final int MAX_CHARS = H + 7;
+
+ // Numerical results are created here...
+ private final byte[] bytes = new byte[MAX_CHARS];
+
+ // ... and copied here in appendTo()
+ private final char[] chars = new char[MAX_CHARS];
+
+ // Index into bytes of rightmost valid character.
+ private int index;
+
+ private DoubleToDecimal() {
+ }
+
+ /**
+ * Returns a string rendering of the {@code double} argument.
+ *
+ * <p>The characters of the result are all drawn from the ASCII set.
+ * <ul>
+ * <li> Any NaN, whether quiet or signaling, is rendered as
+ * {@code "NaN"}, regardless of the sign bit.
+ * <li> The infinities +∞ and -∞ are rendered as
+ * {@code "Infinity"} and {@code "-Infinity"}, respectively.
+ * <li> The positive and negative zeroes are rendered as
+ * {@code "0.0"} and {@code "-0.0"}, respectively.
+ * <li> A finite negative {@code v} is rendered as the sign
+ * '{@code -}' followed by the rendering of the magnitude -{@code v}.
+ * <li> A finite positive {@code v} is rendered in two stages:
+ * <ul>
+ * <li> <em>Selection of a decimal</em>: A well-defined
+ * decimal <i>d</i><sub><code>v</code></sub> is selected
+ * to represent {@code v}.
+ * <li> <em>Formatting as a string</em>: The decimal
+ * <i>d</i><sub><code>v</code></sub> is formatted as a string,
+ * either in plain or in computerized scientific notation,
+ * depending on its value.
+ * </ul>
+ * </ul>
+ *
+ * <p>A <em>decimal</em> is a number of the form
+ * <i>d</i>×10<sup><i>i</i></sup>
+ * for some (unique) integers <i>d</i> > 0 and <i>i</i> such that
+ * <i>d</i> is not a multiple of 10.
+ * These integers are the <em>significand</em> and
+ * the <em>exponent</em>, respectively, of the decimal.
+ * The <em>length</em> of the decimal is the (unique)
+ * integer <i>n</i> meeting
+ * 10<sup><i>n</i>-1</sup> ≤ <i>d</i> < 10<sup><i>n</i></sup>.
+ *
+ * <p>The decimal <i>d</i><sub><code>v</code></sub>
+ * for a finite positive {@code v} is defined as follows:
+ * <ul>
+ * <li>Let <i>R</i> be the set of all decimals that round to {@code v}
+ * according to the usual round-to-closest rule of
+ * IEEE 754 floating-point arithmetic.
+ * <li>Let <i>m</i> be the minimal length over all decimals in
<i>R</i>.
+ * <li>When <i>m</i> ≥ 2, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length <i>m</i>.
+ * Otherwise, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length 1 or 2.
+ * <li>Define <i>d</i><sub><code>v</code></sub> as
+ * the decimal in <i>T</i> that is closest to {@code v}.
+ * Or if there are two such decimals in <i>T</i>,
+ * select the one with the even significand (there is exactly one).
+ * </ul>
+ *
+ * <p>The (uniquely) selected decimal <i>d</i><sub><code>v</code></sub>
+ * is then formatted.
+ *
+ * <p>Let <i>d</i>, <i>i</i> and <i>n</i> be the significand,
exponent and
+ * length of <i>d</i><sub><code>v</code></sub>, respectively.
+ * Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>
+ * be the usual decimal expansion of the significand.
+ * Note that <i>d</i><sub>1</sub> ≠ 0 ≠
<i>d</i><sub><i>n</i></sub>.
+ * <ul>
+ * <li>Case -3 ≤ <i>e</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <code>0.0</code>…<code>0</code><!--
+ * --><i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>,
+ * where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
+ * the decimal point and <i>d</i><sub>1</sub>.
+ * For example, 123 × 10<sup>-4</sup> is formatted as
+ * {@code 0.0123}.
+ * <li>Case 0 ≤ <i>e</i> < 7:
+ * <ul>
+ * <li>Subcase <i>i</i> ≥ 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub><!--
+ * --><code>0</code>…<code>0.0</code>,
+ * where there are exactly <i>i</i> zeroes
+ * between <i>d</i><sub><i>n</i></sub> and the decimal point.
+ * For example, 123 × 10<sup>2</sup> is formatted as
+ * {@code 12300.0}.
+ * <li>Subcase <i>i</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i></sub>.<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i>+1</sub>…<!--
+ * --><i>d</i><sub><i>n</i></sub>.
+ * There are exactly -<i>i</i> digits to the right of
+ * the decimal point.
+ * For example, 123 × 10<sup>-1</sup> is formatted as
+ * {@code 12.3}.
+ * </ul>
+ * <li>Case <i>e</i> < -3 or <i>e</i> ≥ 7:
+ * computerized scientific notation is used to format
+ * <i>d</i><sub><code>v</code></sub>.
+ * Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
+ * <ul>
+ * <li>Subcase <i>n</i> = 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.0E</code><i>e</i>.
+ * For example, 1 × 10<sup>23</sup> is formatted as
+ * {@code 1.0E23}.
+ * <li>Subcase <i>n</i> > 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.</code><i>d</i><sub>2</sub><!--
+ * -->…<i>d</i><sub><i>n</i></sub><code>E</code><i>e</i>.
+ * For example, 123 × 10<sup>-21</sup> is formatted as
+ * {@code 1.23E-19}.
+ * </ul>
+ * </ul>
+ *
+ * @param v the {@code double} to be rendered.
+ * @return a string rendering of the argument.
+ */
+ public static String toString(double v) {
+ return threadLocalInstance().toDecimalString(v);
+ }
+
+ /**
+ * Appends the rendering of the {@code v} to {@code app}.
+ *
+ * <p>The outcome is the same as if {@code v} were first
+ * {@link #toString(double) rendered} and the resulting string were
then
+ * {@link Appendable#append(CharSequence) appended} to {@code app}.
+ *
+ * @param v the {@code double} whose rendering is appended.
+ * @param app the {@link Appendable} to append to.
+ * @throws IOException If an I/O error occurs
+ */
+ public static Appendable appendTo(double v, Appendable app)
+ throws IOException {
+ return threadLocalInstance().appendDecimalTo(v, app);
+ }
+
+ private static DoubleToDecimal threadLocalInstance() {
+ return threadLocal.get();
+ }
+
+ private String toDecimalString(double v) {
+ switch (toDecimal(v)) {
+ case NON_SPECIAL: return charsToString();
+ case PLUS_ZERO: return "0.0";
+ case MINUS_ZERO: return "-0.0";
+ case PLUS_INF: return "Infinity";
+ case MINUS_INF: return "-Infinity";
+ default: return "NaN";
+ }
+ }
+
+ private Appendable appendDecimalTo(double v, Appendable app)
+ throws IOException {
+ switch (toDecimal(v)) {
+ case NON_SPECIAL:
+ for (int i = 0; i <= index; ++i) {
+ chars[i] = (char) bytes[i];
+ }
+ if (app instanceof StringBuilder) {
+ return ((StringBuilder) app).append(chars, 0, index
+ 1);
+ }
+ if (app instanceof StringBuffer) {
+ return ((StringBuffer) app).append(chars, 0, index
+ 1);
+ }
+ for (int i = 0; i <= index; ++i) {
+ app.append(chars[i]);
+ }
+ return app;
+ case PLUS_ZERO: return app.append("0.0");
+ case MINUS_ZERO: return app.append("-0.0");
+ case PLUS_INF: return app.append("Infinity");
+ case MINUS_INF: return app.append("-Infinity");
+ default: return app.append("NaN");
+ }
+ }
+
+ /*
+ Returns
+ PLUS_ZERO iff v is 0.0
+ MINUS_ZERO iff v is -0.0
+ PLUS_INF iff v is POSITIVE_INFINITY
+ MINUS_INF iff v is NEGATIVE_INFINITY
+ NAN iff v is NaN
+ */
+ private int toDecimal(double v) {
+ /*
+ For full details see references [2] and [1].
+
+ For finite v != 0, determine integers c and q such that
+ |v| = c 2^q and
+ Q_MIN <= q <= Q_MAX and
+ either 2^(P-1) <= c < 2^P (normal)
+ or 0 < c < 2^(P-1) and q = Q_MIN (subnormal)
+ */
+ long bits = doubleToRawLongBits(v);
+ long t = bits & T_MASK;
+ int bq = (int) (bits >>> P - 1) & BQ_MASK;
+ if (bq < BQ_MASK) {
+ index = -1;
+ if (bits < 0) {
+ append('-');
+ }
+ if (bq != 0) {
+ // normal value. Here mq = -q
+ int mq = -Q_MIN + 1 - bq;
+ long c = C_MIN | t;
+ // The fast path discussed in section 8.2 of [1].
+ if (0 < mq & mq < P) {
+ long f = c >> mq;
+ if (f << mq == c) {
+ return toChars(f, 0);
+ }
+ }
+ return toDecimal(-mq, c, 0);
+ }
+ if (t != 0) {
+ // subnormal value
+ return t < C_TINY
+ ? toDecimal(Q_MIN, 10 * t, -1)
+ : toDecimal(Q_MIN, t, 0);
+ }
+ return bits == 0 ? PLUS_ZERO : MINUS_ZERO;
+ }
+ if (t != 0) {
+ return NAN;
+ }
+ return bits > 0 ? PLUS_INF : MINUS_INF;
+ }
+
+ private int toDecimal(int q, long c, int dk) {
+ /*
+ The skeleton corresponds to figure 4 of [1].
+ The efficient computations are those summarized in figure 7.
+
+ Here's a correspondence between Java names and names in [1],
+ expressed as approximate LaTeX source code and informally.
+ Other names are identical.
+ cb: \bar{c} "c-bar"
+ cbr: \bar{c}_r "c-bar-r"
+ cbl: \bar{c}_l "c-bar-l"
+
+ vb: \bar{v} "v-bar"
+ vbr: \bar{v}_r "v-bar-r"
+ vbl: \bar{v}_l "v-bar-l"
+
+ rop: r_o' "r-o-prime"
+ */
+ int out = (int) c & 0x1;
+ long cb = c << 2;
+ long cbr = cb + 2;
+ long cbl;
+ int k;
+ /*
+ flog10pow2(e) = floor(log_10(2^e))
+ flog10threeQuartersPow2(e) = floor(log_10(3/4 2^e))
+ flog2pow10(e) = floor(log_2(10^e))
+ */
+ if (c != C_MIN | q == Q_MIN) {
+ // regular spacing
+ cbl = cb - 2;
+ k = flog10pow2(q);
+ } else {
+ // irregular spacing
+ cbl = cb - 1;
+ k = flog10threeQuartersPow2(q);
+ }
+ int h = q + flog2pow10(-k) + 2;
+
+ // g1 and g0 are as in section 9.9.3 of [1], so g = g1 2^63 + g0
+ long g1 = g1(k);
+ long g0 = g0(k);
+
+ long vb = rop(g1, g0, cb << h);
+ long vbl = rop(g1, g0, cbl << h);
+ long vbr = rop(g1, g0, cbr << h);
+
+ long s = vb >> 2;
+ if (s >= 100) {
+ /*
+ For n = 17, m = 1 the table in section 10 of [1] shows
+ s' = floor(s / 10) = floor(s 115_292_150_460_684_698 /
2^60)
+ = floor(s 115_292_150_460_684_698 2^4 / 2^64)
+
+ sp10 = 10 s'
+ tp10 = 10 t'
+ upin iff u' = sp10 10^k in Rv
+ wpin iff w' = tp10 10^k in Rv
+ See section 9.4 of [1].
+ */
+ long sp10 = 10 * multiplyHigh(s, 115_292_150_460_684_698L
<< 4);
+ long tp10 = sp10 + 10;
+ boolean upin = vbl + out <= sp10 << 2;
+ boolean wpin = (tp10 << 2) + out <= vbr;
+ if (upin != wpin) {
+ return toChars(upin ? sp10 : tp10, k);
+ }
+ }
+
+ /*
+ 10 <= s < 100 or s >= 100 and u', w' not in Rv
+ uin iff u = s 10^k in Rv
+ win iff w = t 10^k in Rv
+ See section 9.4 of [1].
+ */
+ long t = s + 1;
+ boolean uin = vbl + out <= s << 2;
+ boolean win = (t << 2) + out <= vbr;
+ if (uin != win) {
+ // Exactly one of u or w lies in Rv.
+ return toChars(uin ? s : t, k + dk);
+ }
+ /*
+ Both u and w lie in Rv: determine the one closest to v.
+ See section 9.4 of [1].
+ */
+ long cmp = vb - (s + t << 1);
+ return toChars(cmp < 0 || cmp == 0 && (s & 0x1) == 0 ? s : t, k
+ dk);
+ }
+
+ /*
+ Computes rop(cp g 2^(-127)), where g = g1 2^63 + g0
+ See section 9.10 and figure 5 of [1].
+ */
+ private static long rop(long g1, long g0, long cp) {
+ long x1 = multiplyHigh(g0, cp);
+ long y0 = g1 * cp;
+ long y1 = multiplyHigh(g1, cp);
+ long z = (y0 >>> 1) + x1;
+ long vbp = y1 + (z >>> 63);
+ return vbp | (z & MASK_63) + MASK_63 >>> 63;
+ }
+
+ /*
+ Formats the decimal f 10^e.
+ */
+ private int toChars(long f, int e) {
+ /*
+ For details not discussed here see section 10 of [1].
+
+ Determine len such that
+ 10^(len-1) <= f < 10^len
+ */
+ int len = flog10pow2(Long.SIZE - numberOfLeadingZeros(f));
+ if (f >= pow10(len)) {
+ len += 1;
+ }
+
+ /*
+ Let fp and ep be the original f and e, respectively.
+ Transform f and e to ensure
+ 10^(H-1) <= f < 10^H
+ fp 10^ep = f 10^(e-H) = 0.f 10^e
+ */
+ f *= pow10(H - len);
+ e += len;
+
+ /*
+ The toChars?() methods perform left-to-right digits extraction
+ using ints, provided that the arguments are limited to 8 digits.
+ Therefore, split the H = 17 digits of f into:
+ h = the most significant digit of f
+ m = the next 8 most significant digits of f
+ l = the last 8, least significant digits of f
+
+ For n = 17, m = 8 the table in section 10 of [1] shows
+ floor(f / 10^8) = floor(193_428_131_138_340_668 f / 2^84) =
+ floor(floor(193_428_131_138_340_668 f / 2^64) / 2^20)
+ and for n = 9, m = 8
+ floor(hm / 10^8) = floor(1_441_151_881 hm / 2^57)
+ */
+ long hm = multiplyHigh(f, 193_428_131_138_340_668L) >>> 20;
+ int l = (int) (f - 100_000_000L * hm);
+ int h = (int) (hm * 1_441_151_881L >>> 57);
+ int m = (int) (hm - 100_000_000 * h);
+
+ if (0 < e && e <= 7) {
+ return toChars1(h, m, l, e);
+ }
+ if (-3 < e && e <= 0) {
+ return toChars2(h, m, l, e);
+ }
+ return toChars3(h, m, l, e);
+ }
+
+ private int toChars1(int h, int m, int l, int e) {
+ /*
+ 0 < e <= 7: plain format without leading zeroes.
+ Left-to-right digits extraction:
+ algorithm 1 in [3], with b = 10, k = 8, n = 28.
+ */
+ appendDigit(h);
+ int y = y(m);
+ int t;
+ int i = 1;
+ for (; i < e; ++i) {
+ t = 10 * y;
+ appendDigit(t >>> 28);
+ y = t & MASK_28;
+ }
+ append('.');
+ for (; i <= 8; ++i) {
+ t = 10 * y;
+ appendDigit(t >>> 28);
+ y = t & MASK_28;
+ }
+ lowDigits(l);
+ return NON_SPECIAL;
+ }
+
+ private int toChars2(int h, int m, int l, int e) {
+ // -3 < e <= 0: plain format with leading zeroes.
+ appendDigit(0);
+ append('.');
+ for (; e < 0; ++e) {
+ appendDigit(0);
+ }
+ appendDigit(h);
+ append8Digits(m);
+ lowDigits(l);
+ return NON_SPECIAL;
+ }
+
+ private int toChars3(int h, int m, int l, int e) {
+ // -3 >= e | e > 7: computerized scientific notation
+ appendDigit(h);
+ append('.');
+ append8Digits(m);
+ lowDigits(l);
+ exponent(e - 1);
+ return NON_SPECIAL;
+ }
+
+ private void lowDigits(int l) {
+ if (l != 0) {
+ append8Digits(l);
+ }
+ removeTrailingZeroes();
+ }
+
+ private void append8Digits(int m) {
+ /*
+ Left-to-right digits extraction:
+ algorithm 1 in [3], with b = 10, k = 8, n = 28.
+ */
+ int y = y(m);
+ for (int i = 0; i < 8; ++i) {
+ int t = 10 * y;
+ appendDigit(t >>> 28);
+ y = t & MASK_28;
+ }
+ }
+
+ private void removeTrailingZeroes() {
+ while (bytes[index] == '0') {
+ --index;
+ }
+ // ... but do not remove the one directly to the right of '.'
+ if (bytes[index] == '.') {
+ ++index;
+ }
+ }
+
+ private int y(int a) {
+ /*
+ Algorithm 1 in [3] needs computation of
+ floor((a + 1) 2^n / b^k) - 1
+ with a < 10^8, b = 10, k = 8, n = 28.
+ Noting that
+ (a + 1) 2^n <= 10^8 2^28 < 10^17
+ For n = 17, m = 8 the table in section 10 of [1] leads to:
+ */
+ return (int) (multiplyHigh(
+ (long) (a + 1) << 28,
+ 193_428_131_138_340_668L) >>> 20) - 1;
+ }
+
+ private void exponent(int e) {
+ append('E');
+ if (e < 0) {
+ append('-');
+ e = -e;
+ }
+ if (e < 10) {
+ appendDigit(e);
+ return;
+ }
+ int d;
+ if (e >= 100) {
+ /*
+ For n = 3, m = 2 the table in section 10 of [1] shows
+ floor(e / 100) = floor(1_311 e / 2^17)
+ */
+ d = e * 1_311 >>> 17;
+ appendDigit(d);
+ e -= 100 * d;
+ }
+ /*
+ For n = 2, m = 1 the table in section 10 of [1] shows
+ floor(e / 10) = floor(103 e / 2^10)
+ */
+ d = e * 103 >>> 10;
+ appendDigit(d);
+ appendDigit(e - 10 * d);
+ }
+
+ private void append(int c) {
+ bytes[++index] = (byte) c;
+ }
+
+ private void appendDigit(int d) {
+ bytes[++index] = (byte) ('0' + d);
+ }
+
+ // Using the deprecated constructor enhances performance.
+ @SuppressWarnings("deprecation")
+ private String charsToString() {
+ return new String(bytes, 0, 0, index + 1);
+ }
+
+}
diff --git
a/src/java.base/share/classes/jdk/internal/math/FloatToDecimal.java
b/src/java.base/share/classes/jdk/internal/math/FloatToDecimal.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/math/FloatToDecimal.java
@@ -0,0 +1,617 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+import java.io.IOException;
+
+import static java.lang.Float.*;
+import static java.lang.Integer.*;
+import static java.lang.Math.multiplyHigh;
+import static jdk.internal.math.MathUtils.*;
+
+/**
+ * This class exposes a method to render a {@code float} as a string.
+ *
+ * @author Raffaello Giulietti
+ */
+final public class FloatToDecimal {
+ /*
+ For full details about this code see the following references:
+
+ [1] Giulietti, "The Schubfach way to render doubles",
+ https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
+
+ [2] IEEE Computer Society, "IEEE Standard for Floating-Point
Arithmetic"
+
+ [3] Bouvier & Zimmermann, "Division-Free Binary-to-Decimal Conversion"
+
+ Divisions are avoided altogether for the benefit of those architectures
+ that do not provide specific machine instructions or where they are
slow.
+ This is discussed in section 10 of [1].
+ */
+
+ // The precision in bits.
+ static final int P = 24;
+
+ // Exponent width in bits.
+ private static final int W = (Float.SIZE - 1) - (P - 1);
+
+ // Minimum value of the exponent: -(2^(W-1)) - P + 3.
+ static final int Q_MIN = (-1 << W - 1) - P + 3;
+
+ // Maximum value of the exponent: 2^(W-1) - P.
+ static final int Q_MAX = (1 << W - 1) - P;
+
+ // 10^(E_MIN - 1) <= MIN_VALUE < 10^E_MIN
+ static final int E_MIN = -44;
+
+ // 10^(E_MAX - 1) <= MAX_VALUE < 10^E_MAX
+ static final int E_MAX = 39;
+
+ // Threshold to detect tiny values, as in section 8.1.1 of [1]
+ static final int C_TINY = 8;
+
+ // The minimum and maximum k, as in section 8 of [1]
+ static final int K_MIN = -45;
+ static final int K_MAX = 31;
+
+ // H is as in section 8 of [1].
+ static final int H = 9;
+
+ // Minimum value of the significand of a normal value: 2^(P-1).
+ private static final int C_MIN = 1 << P - 1;
+
+ // Mask to extract the biased exponent.
+ private static final int BQ_MASK = (1 << W) - 1;
+
+ // Mask to extract the fraction bits.
+ private static final int T_MASK = (1 << P - 1) - 1;
+
+ // Used in rop().
+ private static final long MASK_32 = (1L << 32) - 1;
+
+ // Used for left-to-tight digit extraction.
+ private static final int MASK_28 = (1 << 28) - 1;
+
+ private static final int NON_SPECIAL = 0;
+ private static final int PLUS_ZERO = 1;
+ private static final int MINUS_ZERO = 2;
+ private static final int PLUS_INF = 3;
+ private static final int MINUS_INF = 4;
+ private static final int NAN = 5;
+
+ // For thread-safety, each thread gets its own instance of this class.
+ private static final ThreadLocal<FloatToDecimal> threadLocal =
+ ThreadLocal.withInitial(FloatToDecimal::new);
+
+ /*
+ Room for the longer of the forms
+ -ddddd.dddd H + 2 characters
+ -0.00ddddddddd H + 5 characters
+ -d.ddddddddE-ee H + 6 characters
+ where there are H digits d
+ */
+ public final int MAX_CHARS = H + 6;
+
+ // Numerical results are created here...
+ private final byte[] bytes = new byte[MAX_CHARS];
+
+ // ... and copied here in appendTo()
+ private final char[] chars = new char[MAX_CHARS];
+
+ // Index into buf of rightmost valid character.
+ private int index;
+
+ private FloatToDecimal() {
+ }
+
+ /**
+ * Returns a string rendering of the {@code float} argument.
+ *
+ * <p>The characters of the result are all drawn from the ASCII set.
+ * <ul>
+ * <li> Any NaN, whether quiet or signaling, is rendered as
+ * {@code "NaN"}, regardless of the sign bit.
+ * <li> The infinities +∞ and -∞ are rendered as
+ * {@code "Infinity"} and {@code "-Infinity"}, respectively.
+ * <li> The positive and negative zeroes are rendered as
+ * {@code "0.0"} and {@code "-0.0"}, respectively.
+ * <li> A finite negative {@code v} is rendered as the sign
+ * '{@code -}' followed by the rendering of the magnitude -{@code v}.
+ * <li> A finite positive {@code v} is rendered in two stages:
+ * <ul>
+ * <li> <em>Selection of a decimal</em>: A well-defined
+ * decimal <i>d</i><sub><code>v</code></sub> is selected
+ * to represent {@code v}.
+ * <li> <em>Formatting as a string</em>: The decimal
+ * <i>d</i><sub><code>v</code></sub> is formatted as a string,
+ * either in plain or in computerized scientific notation,
+ * depending on its value.
+ * </ul>
+ * </ul>
+ *
+ * <p>A <em>decimal</em> is a number of the form
+ * <i>d</i>×10<sup><i>i</i></sup>
+ * for some (unique) integers <i>d</i> > 0 and <i>i</i> such that
+ * <i>d</i> is not a multiple of 10.
+ * These integers are the <em>significand</em> and
+ * the <em>exponent</em>, respectively, of the decimal.
+ * The <em>length</em> of the decimal is the (unique)
+ * integer <i>n</i> meeting
+ * 10<sup><i>n</i>-1</sup> ≤ <i>d</i> < 10<sup><i>n</i></sup>.
+ *
+ * <p>The decimal <i>d</i><sub><code>v</code></sub>
+ * for a finite positive {@code v} is defined as follows:
+ * <ul>
+ * <li>Let <i>R</i> be the set of all decimals that round to {@code v}
+ * according to the usual round-to-closest rule of
+ * IEEE 754 floating-point arithmetic.
+ * <li>Let <i>m</i> be the minimal length over all decimals in
<i>R</i>.
+ * <li>When <i>m</i> ≥ 2, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length <i>m</i>.
+ * Otherwise, let <i>T</i> be the set of all decimals
+ * in <i>R</i> with length 1 or 2.
+ * <li>Define <i>d</i><sub><code>v</code></sub> as
+ * the decimal in <i>T</i> that is closest to {@code v}.
+ * Or if there are two such decimals in <i>T</i>,
+ * select the one with the even significand (there is exactly one).
+ * </ul>
+ *
+ * <p>The (uniquely) selected decimal <i>d</i><sub><code>v</code></sub>
+ * is then formatted.
+ *
+ * <p>Let <i>d</i>, <i>i</i> and <i>n</i> be the significand,
exponent and
+ * length of <i>d</i><sub><code>v</code></sub>, respectively.
+ * Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>
+ * be the usual decimal expansion of the significand.
+ * Note that <i>d</i><sub>1</sub> ≠ 0 ≠
<i>d</i><sub><i>n</i></sub>.
+ * <ul>
+ * <li>Case -3 ≤ <i>e</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <code>0.0</code>…<code>0</code><!--
+ * --><i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub>,
+ * where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
+ * the decimal point and <i>d</i><sub>1</sub>.
+ * For example, 123 × 10<sup>-4</sup> is formatted as
+ * {@code 0.0123}.
+ * <li>Case 0 ≤ <i>e</i> < 7:
+ * <ul>
+ * <li>Subcase <i>i</i> ≥ 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<i>d</i><sub><i>n</i></sub><!--
+ * --><code>0</code>…<code>0.0</code>,
+ * where there are exactly <i>i</i> zeroes
+ * between <i>d</i><sub><i>n</i></sub> and the decimal point.
+ * For example, 123 × 10<sup>2</sup> is formatted as
+ * {@code 12300.0}.
+ * <li>Subcase <i>i</i> < 0:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub>…<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i></sub>.<!--
+ * --><i>d</i><sub><i>n</i>+<i>i</i>+1</sub>…<!--
+ * --><i>d</i><sub><i>n</i></sub>.
+ * There are exactly -<i>i</i> digits to the right of
+ * the decimal point.
+ * For example, 123 × 10<sup>-1</sup> is formatted as
+ * {@code 12.3}.
+ * </ul>
+ * <li>Case <i>e</i> < -3 or <i>e</i> ≥ 7:
+ * computerized scientific notation is used to format
+ * <i>d</i><sub><code>v</code></sub>.
+ * Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
+ * <ul>
+ * <li>Subcase <i>n</i> = 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.0E</code><i>e</i>.
+ * For example, 1 × 10<sup>23</sup> is formatted as
+ * {@code 1.0E23}.
+ * <li>Subcase <i>n</i> > 1:
+ * <i>d</i><sub><code>v</code></sub> is formatted as
+ * <i>d</i><sub>1</sub><code>.</code><i>d</i><sub>2</sub><!--
+ * -->…<i>d</i><sub><i>n</i></sub><code>E</code><i>e</i>.
+ * For example, 123 × 10<sup>-21</sup> is formatted as
+ * {@code 1.23E-19}.
+ * </ul>
+ * </ul>
+ *
+ * @param v the {@code float} to be rendered.
+ * @return a string rendering of the argument.
+ */
+ public static String toString(float v) {
+ return threadLocalInstance().toDecimalString(v);
+ }
+
+ /**
+ * Appends the rendering of the {@code v} to {@code app}.
+ *
+ * <p>The outcome is the same as if {@code v} were first
+ * {@link #toString(float) rendered} and the resulting string were then
+ * {@link Appendable#append(CharSequence) appended} to {@code app}.
+ *
+ * @param v the {@code float} whose rendering is appended.
+ * @param app the {@link Appendable} to append to.
+ * @throws IOException If an I/O error occurs
+ */
+ public static Appendable appendTo(float v, Appendable app)
+ throws IOException {
+ return threadLocalInstance().appendDecimalTo(v, app);
+ }
+
+ private static FloatToDecimal threadLocalInstance() {
+ return threadLocal.get();
+ }
+
+ private String toDecimalString(float v) {
+ switch (toDecimal(v)) {
+ case NON_SPECIAL: return charsToString();
+ case PLUS_ZERO: return "0.0";
+ case MINUS_ZERO: return "-0.0";
+ case PLUS_INF: return "Infinity";
+ case MINUS_INF: return "-Infinity";
+ default: return "NaN";
+ }
+ }
+
+ private Appendable appendDecimalTo(float v, Appendable app)
+ throws IOException {
+ switch (toDecimal(v)) {
+ case NON_SPECIAL:
+ for (int i = 0; i <= index; ++i) {
+ chars[i] = (char) bytes[i];
+ }
+ if (app instanceof StringBuilder) {
+ return ((StringBuilder) app).append(chars, 0, index
+ 1);
+ }
+ if (app instanceof StringBuffer) {
+ return ((StringBuffer) app).append(chars, 0, index
+ 1);
+ }
+ for (int i = 0; i <= index; ++i) {
+ app.append(chars[i]);
+ }
+ return app;
+ case PLUS_ZERO: return app.append("0.0");
+ case MINUS_ZERO: return app.append("-0.0");
+ case PLUS_INF: return app.append("Infinity");
+ case MINUS_INF: return app.append("-Infinity");
+ default: return app.append("NaN");
+ }
+ }
+
+ /*
+ Returns
+ PLUS_ZERO iff v is 0.0
+ MINUS_ZERO iff v is -0.0
+ PLUS_INF iff v is POSITIVE_INFINITY
+ MINUS_INF iff v is NEGATIVE_INFINITY
+ NAN iff v is NaN
+ */
+ private int toDecimal(float v) {
+ /*
+ For full details see references [2] and [1].
+
+ For finite v != 0, determine integers c and q such that
+ |v| = c 2^q and
+ Q_MIN <= q <= Q_MAX and
+ either 2^(P-1) <= c < 2^P (normal)
+ or 0 < c < 2^(P-1) and q = Q_MIN (subnormal)
+ */
+ int bits = floatToRawIntBits(v);
+ int t = bits & T_MASK;
+ int bq = (bits >>> P - 1) & BQ_MASK;
+ if (bq < BQ_MASK) {
+ index = -1;
+ if (bits < 0) {
+ append('-');
+ }
+ if (bq != 0) {
+ // normal value. Here mq = -q
+ int mq = -Q_MIN + 1 - bq;
+ int c = C_MIN | t;
+ // The fast path discussed in section 8.2 of [1].
+ if (0 < mq & mq < P) {
+ int f = c >> mq;
+ if (f << mq == c) {
+ return toChars(f, 0);
+ }
+ }
+ return toDecimal(-mq, c, 0);
+ }
+ if (t != 0) {
+ // subnormal value
+ return t < C_TINY
+ ? toDecimal(Q_MIN, 10 * t, -1)
+ : toDecimal(Q_MIN, t, 0);
+ }
+ return bits == 0 ? PLUS_ZERO : MINUS_ZERO;
+ }
+ if (t != 0) {
+ return NAN;
+ }
+ return bits > 0 ? PLUS_INF : MINUS_INF;
+ }
+
+ private int toDecimal(int q, int c, int dk) {
+ /*
+ The skeleton corresponds to figure 4 of [1].
+ The efficient computations are those summarized in figure 7.
+ Also check the appendix.
+
+ Here's a correspondence between Java names and names in [1],
+ expressed as approximate LaTeX source code and informally.
+ Other names are identical.
+ cb: \bar{c} "c-bar"
+ cbr: \bar{c}_r "c-bar-r"
+ cbl: \bar{c}_l "c-bar-l"
+
+ vb: \bar{v} "v-bar"
+ vbr: \bar{v}_r "v-bar-r"
+ vbl: \bar{v}_l "v-bar-l"
+
+ rop: r_o' "r-o-prime"
+ */
+ int out = c & 0x1;
+ long cb = c << 2;
+ long cbr = cb + 2;
+ long cbl;
+ int k;
+ /*
+ flog10pow2(e) = floor(log_10(2^e))
+ flog10threeQuartersPow2(e) = floor(log_10(3/4 2^e))
+ flog2pow10(e) = floor(log_2(10^e))
+ */
+ if (c != C_MIN | q == Q_MIN) {
+ // regular spacing
+ cbl = cb - 2;
+ k = flog10pow2(q);
+ } else {
+ // irregular spacing0
+ cbl = cb - 1;
+ k = flog10threeQuartersPow2(q);
+ }
+ int h = q + flog2pow10(-k) + 33;
+
+ // g is as in the appendix
+ long g = g1(k) + 1;
+
+ int vb = rop(g, cb << h);
+ int vbl = rop(g, cbl << h);
+ int vbr = rop(g, cbr << h);
+
+ int s = vb >> 2;
+ if (s >= 100) {
+ /*
+ For n = 9, m = 1 the table in section 10 of [1] shows
+ s' = floor(s / 10) = floor(s 1_717_986_919 / 2^34)
+
+ sp10 = 10 s'
+ tp10 = 10 t'
+ upin iff u' = sp10 10^k in Rv
+ wpin iff w' = tp10 10^k in Rv
+ See section 9.4 of [1].
+ */
+ int sp10 = 10 * (int) (s * 1_717_986_919L >>> 34);
+ int tp10 = sp10 + 10;
+ boolean upin = vbl + out <= sp10 << 2;
+ boolean wpin = (tp10 << 2) + out <= vbr;
+ if (upin != wpin) {
+ return toChars(upin ? sp10 : tp10, k);
+ }
+ }
+
+ /*
+ 10 <= s < 100 or s >= 100 and u', w' not in Rv
+ uin iff u = s 10^k in Rv
+ win iff w = t 10^k in Rv
+ See section 9.4 of [1].
+ */
+ int t = s + 1;
+ boolean uin = vbl + out <= s << 2;
+ boolean win = (t << 2) + out <= vbr;
+ if (uin != win) {
+ // Exactly one of u or w lies in Rv.
+ return toChars(uin ? s : t, k + dk);
+ }
+ /*
+ Both u and w lie in Rv: determine the one closest to v.
+ See section 9.4 of [1].
+ */
+ int cmp = vb - (s + t << 1);
+ return toChars(cmp < 0 || cmp == 0 && (s & 0x1) == 0 ? s : t, k
+ dk);
+ }
+
+ /*
+ Computes rop(cp g 2^(-95))
+ See appendix and figure 8 of [1].
+ */
+ private static int rop(long g, long cp) {
+ long x1 = multiplyHigh(g, cp);
+ long vbp = x1 >>> 31;
+ return (int) (vbp | (x1 & MASK_32) + MASK_32 >>> 32);
+ }
+
+ /*
+ Formats the decimal f 10^e.
+ */
+ private int toChars(int f, int e) {
+ /*
+ For details not discussed here see section 10 of [1].
+
+ Determine len such that
+ 10^(len-1) <= f < 10^len
+ */
+ int len = flog10pow2(Integer.SIZE - numberOfLeadingZeros(f));
+ if (f >= pow10(len)) {
+ len += 1;
+ }
+
+ /*
+ Let fp and ep be the original f and e, respectively.
+ Transform f and e to ensure
+ 10^(H-1) <= f < 10^H
+ fp 10^ep = f 10^(e-H) = 0.f 10^e
+ */
+ f *= pow10(H - len);
+ e += len;
+
+ /*
+ The toChars?() methods perform left-to-right digits extraction
+ using ints, provided that the arguments are limited to 8 digits.
+ Therefore, split the H = 9 digits of f into:
+ h = the most significant digit of f
+ l = the last 8, least significant digits of f
+
+ For n = 9, m = 8 the table in section 10 of [1] shows
+ floor(f / 10^8) = floor(1_441_151_881 f / 2^57)
+ */
+ int h = (int) (f * 1_441_151_881L >>> 57);
+ int l = f - 100_000_000 * h;
+
+ if (0 < e && e <= 7) {
+ return toChars1(h, l, e);
+ }
+ if (-3 < e && e <= 0) {
+ return toChars2(h, l, e);
+ }
+ return toChars3(h, l, e);
+ }
+
+ private int toChars1(int h, int l, int e) {
+ /*
+ 0 < e <= 7: plain format without leading zeroes.
+ Left-to-right digits extraction:
+ algorithm 1 in [3], with b = 10, k = 8, n = 28.
+ */
+ appendDigit(h);
+ int y = y(l);
+ int t;
+ int i = 1;
+ for (; i < e; ++i) {
+ t = 10 * y;
+ appendDigit(t >>> 28);
+ y = t & MASK_28;
+ }
+ append('.');
+ for (; i <= 8; ++i) {
+ t = 10 * y;
+ appendDigit(t >>> 28);
+ y = t & MASK_28;
+ }
+ removeTrailingZeroes();
+ return NON_SPECIAL;
+ }
+
+ private int toChars2(int h, int l, int e) {
+ // -3 < e <= 0: plain format with leading zeroes.
+ appendDigit(0);
+ append('.');
+ for (; e < 0; ++e) {
+ appendDigit(0);
+ }
+ appendDigit(h);
+ append8Digits(l);
+ removeTrailingZeroes();
+ return NON_SPECIAL;
+ }
+
+ private int toChars3(int h, int l, int e) {
+ // -3 >= e | e > 7: computerized scientific notation
+ appendDigit(h);
+ append('.');
+ append8Digits(l);
+ removeTrailingZeroes();
+ exponent(e - 1);
+ return NON_SPECIAL;
+ }
+
+ private void append8Digits(int m) {
+ /*
+ Left-to-right digits extraction:
+ algorithm 1 in [3], with b = 10, k = 8, n = 28.
+ */
+ int y = y(m);
+ for (int i = 0; i < 8; ++i) {
+ int t = 10 * y;
+ appendDigit(t >>> 28);
+ y = t & MASK_28;
+ }
+ }
+
+ private void removeTrailingZeroes() {
+ while (bytes[index] == '0') {
+ --index;
+ }
+ // ... but do not remove the one directly to the right of '.'
+ if (bytes[index] == '.') {
+ ++index;
+ }
+ }
+
+ private int y(int a) {
+ /*
+ Algorithm 1 in [3] needs computation of
+ floor((a + 1) 2^n / b^k) - 1
+ with a < 10^8, b = 10, k = 8, n = 28.
+ Noting that
+ (a + 1) 2^n <= 10^8 2^28 < 10^17
+ For n = 17, m = 8 the table in section 10 of [1] leads to:
+ */
+ return (int) (multiplyHigh(
+ (long) (a + 1) << 28,
+ 193_428_131_138_340_668L) >>> 20) - 1;
+ }
+
+ private void exponent(int e) {
+ append('E');
+ if (e < 0) {
+ append('-');
+ e = -e;
+ }
+ if (e < 10) {
+ appendDigit(e);
+ return;
+ }
+ /*
+ For n = 2, m = 1 the table in section 10 of [1] shows
+ floor(e / 10) = floor(103 e / 2^10)
+ */
+ int d = e * 103 >>> 10;
+ appendDigit(d);
+ appendDigit(e - 10 * d);
+ }
+
+ private void append(int c) {
+ bytes[++index] = (byte) c;
+ }
+
+ private void appendDigit(int d) {
+ bytes[++index] = (byte) ('0' + d);
+ }
+
+ // Using the deprecated constructor enhances performance.
+ @SuppressWarnings("deprecation")
+ private String charsToString() {
+ return new String(bytes, 0, 0, index + 1);
+ }
+
+}
diff --git
a/src/java.base/share/classes/jdk/internal/math/MathUtils.java
b/src/java.base/share/classes/jdk/internal/math/MathUtils.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/math/MathUtils.java
@@ -0,0 +1,811 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+/**
+ * This class exposes package private utilities for other classes.
+ * Thus, all methods are assumed to be invoked with correct arguments,
+ * so these are not checked at all.
+ *
+ * @author Raffaello Giulietti
+ */
+final class MathUtils {
+ /*
+ For full details about this code see the following reference:
+
+ Giulietti, "The Schubfach way to render doubles",
+ https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
+ */
+
+ /*
+ The boundaries for k in g0(int) and g1(int).
+ K_MIN must be DoubleToDecimal.K_MIN or less.
+ K_MAX must be DoubleToDecimal.K_MAX or more.
+ */
+ static final int K_MIN = -324;
+ static final int K_MAX = 292;
+
+ // Must be DoubleToDecimal.H or more
+ static final int H = 17;
+
+ // C_10 = floor(log10(2) * 2^Q_10), A_10 = floor(log10(3/4) * 2^Q_10)
+ private static final int Q_10 = 41;
+ private static final long C_10 = 661_971_961_083L;
+ private static final long A_10 = -274_743_187_321L;
+
+ // C_2 = floor(log2(10) * 2^Q_2)
+ private static final int Q_2 = 38;
+ private static final long C_2 = 913_124_641_741L;
+
+ private MathUtils() {
+ }
+
+ // The first powers of 10. The last entry must be 10^H.
+ private static final long[] pow10 = {
+ 1L,
+ 10L,
+ 100L,
+ 1_000L,
+ 10_000L,
+ 100_000L,
+ 1_000_000L,
+ 10_000_000L,
+ 100_000_000L,
+ 1_000_000_000L,
+ 10_000_000_000L,
+ 100_000_000_000L,
+ 1_000_000_000_000L,
+ 10_000_000_000_000L,
+ 100_000_000_000_000L,
+ 1_000_000_000_000_000L,
+ 10_000_000_000_000_000L,
+ 100_000_000_000_000_000L,
+ };
+
+ /**
+ * Returns 10<sup>{@code e}</sup>.
+ *
+ * @param e The exponent which must meet
+ * 0 ≤ {@code e} ≤ {@link #H}.
+ * @return 10<sup>{@code e}</sup>.
+ */
+ static long pow10(int e) {
+ return pow10[e];
+ }
+
+ /**
+ * Returns the unique integer <i>k</i> such that
+ * 10<sup><i>k</i></sup> ≤ 2<sup>{@code e}</sup>
+ * < 10<sup><i>k</i>+1</sup>.
+ * <p>
+ * The result is correct when |{@code e}| ≤ 5_456_721.
+ * Otherwise the result is undefined.
+ *
+ * @param e The exponent of 2, which should meet
+ * |{@code e}| ≤ 5_456_721 for safe results.
+ * @return ⌊log<sub>10</sub>2<sup>{@code e}</sup>⌋.
+ */
+ static int flog10pow2(int e) {
+ return (int) (e * C_10 >> Q_10);
+ }
+
+ /**
+ * Returns the unique integer <i>k</i> such that
+ * 10<sup><i>k</i></sup> ≤ 3/4 · 2<sup>{@code e}</sup>
+ * < 10<sup><i>k</i>+1</sup>.
+ * <p>
+ * The result is correct when
+ * -2_956_395 ≤ {@code e} ≤ 2_500_325.
+ * Otherwise the result is undefined.
+ *
+ * @param e The exponent of 2, which should meet
+ * -2_956_395 ≤ {@code e} ≤ 2_500_325 for safe results.
+ * @return ⌊log<sub>10</sub>(3/4 ·
+ * 2<sup>{@code e}</sup>)⌋.
+ */
+ static int flog10threeQuartersPow2(int e) {
+ return (int) (e * C_10 + A_10 >> Q_10);
+ }
+
+ /**
+ * Returns the unique integer <i>k</i> such that
+ * 2<sup><i>k</i></sup> ≤ 10<sup>{@code e}</sup>
+ * < 2<sup><i>k</i>+1</sup>.
+ * <p>
+ * The result is correct when |{@code e}| ≤ 1_838_394.
+ * Otherwise the result is undefined.
+ *
+ * @param e The exponent of 10, which should meet
+ * |{@code e}| ≤ 1_838_394 for safe results.
+ * @return ⌊log<sub>2</sub>10<sup>{@code e}</sup>⌋.
+ */
+ static int flog2pow10(int e) {
+ return (int) (e * C_2 >> Q_2);
+ }
+
+ /**
+ * Let 10<sup>-{@code k}</sup> = <i>β</i> 2<sup><i>r</i></sup>,
+ * for the unique pair of integer <i>r</i> and real <i>β</i>
meeting
+ * 2<sup>125</sup> ≤ <i>β</i> < 2<sup>126</sup>.
+ * Further, let <i>g</i> = ⌊<i>β</i>⌋ + 1.
+ * Split <i>g</i> into the higher 63 bits <i>g</i><sub>1</sub> and
+ * the lower 63 bits <i>g</i><sub>0</sub>. Thus,
+ * <i>g</i><sub>1</sub> =
+ * ⌊<i>g</i> 2<sup>-63</sup>⌋
+ * and
+ * <i>g</i><sub>0</sub> =
+ * <i>g</i> - <i>g</i><sub>1</sub> 2<sup>63</sup>.
+ * <p>
+ * This method returns <i>g</i><sub>1</sub> while
+ * {@link #g0(int)} returns <i>g</i><sub>0</sub>.
+ * <p>
+ * If needed, the exponent <i>r</i> can be computed as
+ * <i>r</i> = {@code flog2pow10(-k)} - 125 (see {@link
#flog2pow10(int)}).
+ *
+ * @param k The exponent of 10, which must meet
+ * {@link #K_MIN} ≤ {@code e} ≤ {@link #K_MAX}.
+ * @return <i>g</i><sub>1</sub> as described above.
+ */
+ static long g1(int k) {
+ return g[k - K_MIN << 1];
+ }
+
+ /**
+ * Returns <i>g</i><sub>0</sub> as described in
+ * {@link #g1(int)}.
+ *
+ * @param k The exponent of 10, which must meet
+ * {@link #K_MIN} ≤ {@code e} ≤ {@link #K_MAX}.
+ * @return <i>g</i><sub>0</sub> as described in
+ * {@link #g1(int)}.
+ */
+ static long g0(int k) {
+ return g[k - K_MIN << 1 | 1];
+ }
+
+ /*
+ The precomputed values for g1(int) and g0(int).
+ The first entry must be for an exponent of K_MIN or less.
+ The last entry must be for an exponent of K_MAX or more.
+ */
+ private static final long[] g = {
+ /* -324 */ 0x4F0C_EDC9_5A71_8DD4L, 0x5B01_E8B0_9AA0_D1B5L,
+ /* -323 */ 0x7E7B_160E_F71C_1621L, 0x119C_A780_F767_B5EEL,
+ /* -322 */ 0x652F_44D8_C5B0_11B4L, 0x0E16_EC67_2C52_F7F2L,
+ /* -321 */ 0x50F2_9D7A_37C0_0E29L, 0x5812_56B8_F042_5FF5L,
+ /* -320 */ 0x40C2_1794_F966_71BAL, 0x79A8_4560_C035_1991L,
+ /* -319 */ 0x679C_F287_F570_B5F7L, 0x75DA_089A_CD21_C281L,
+ /* -318 */ 0x52E3_F539_9126_F7F9L, 0x44AE_6D48_A41B_0201L,
+ /* -317 */ 0x424F_F761_40EB_F994L, 0x36F1_F106_E9AF_34CDL,
+ /* -316 */ 0x6A19_8BCE_CE46_5C20L, 0x57E9_81A4_A918_547BL,
+ /* -315 */ 0x54E1_3CA5_71D1_E34DL, 0x2CBA_CE1D_5413_76C9L,
+ /* -314 */ 0x43E7_63B7_8E41_82A4L, 0x23C8_A4E4_4342_C56EL,
+ /* -313 */ 0x6CA5_6C58_E39C_043AL, 0x060D_D4A0_6B9E_08B0L,
+ /* -312 */ 0x56EA_BD13_E949_9CFBL, 0x1E71_76E6_BC7E_6D59L,
+ /* -311 */ 0x4588_9743_2107_B0C8L, 0x7EC1_2BEB_C9FE_BDE1L,
+ /* -310 */ 0x6F40_F205_01A5_E7A7L, 0x7E01_DFDF_A997_9635L,
+ /* -309 */ 0x5900_C19D_9AEB_1FB9L, 0x4B34_B319_5479_44F7L,
+ /* -308 */ 0x4733_CE17_AF22_7FC7L, 0x55C3_C27A_A9FA_9D93L,
+ /* -307 */ 0x71EC_7CF2_B1D0_CC72L, 0x5606_03F7_765D_C8EAL,
+ /* -306 */ 0x5B23_9728_8E40_A38EL, 0x7804_CFF9_2B7E_3A55L,
+ /* -305 */ 0x48E9_45BA_0B66_E93FL, 0x1337_0CC7_55FE_9511L,
+ /* -304 */ 0x74A8_6F90_123E_41FEL, 0x51F1_AE0B_BCCA_881BL,
+ /* -303 */ 0x5D53_8C73_41CB_67FEL, 0x74C1_5809_63D5_39AFL,
+ /* -302 */ 0x4AA9_3D29_016F_8665L, 0x43CD_E007_8310_FAF3L,
+ /* -301 */ 0x7775_2EA8_024C_0A3CL, 0x0616_333F_381B_2B1EL,
+ /* -300 */ 0x5F90_F220_01D6_6E96L, 0x3811_C298_F9AF_55B1L,
+ /* -299 */ 0x4C73_F4E6_67DE_BEDEL, 0x600E_3547_2E25_DE28L,
+ /* -298 */ 0x7A53_2170_A631_3164L, 0x3349_EED8_49D6_303FL,
+ /* -297 */ 0x61DC_1AC0_84F4_2783L, 0x42A1_8BE0_3B11_C033L,
+ /* -296 */ 0x4E49_AF00_6A5C_EC69L, 0x1BB4_6FE6_95A7_CCF5L,
+ /* -295 */ 0x7D42_B19A_43C7_E0A8L, 0x2C53_E63D_BC3F_AE55L,
+ /* -294 */ 0x6435_5AE1_CFD3_1A20L, 0x2376_51CA_FCFF_BEAAL,
+ /* -293 */ 0x502A_AF1B_0CA8_E1B3L, 0x35F8_416F_30CC_9888L,
+ /* -292 */ 0x4022_25AF_3D53_E7C2L, 0x5E60_3458_F3D6_E06DL,
+ /* -291 */ 0x669D_0918_621F_D937L, 0x4A33_86F4_B957_CD7BL,
+ /* -290 */ 0x5217_3A79_E819_7A92L, 0x6E8F_9F2A_2DDF_D796L,
+ /* -289 */ 0x41AC_2EC7_ECE1_2EDBL, 0x720C_7F54_F17F_DFABL,
+ /* -288 */ 0x6913_7E0C_AE35_17C6L, 0x1CE0_CBBB_1BFF_CC45L,
+ /* -287 */ 0x540F_980A_24F7_4638L, 0x171A_3C95_AFFF_D69EL,
+ /* -286 */ 0x433F_ACD4_EA5F_6B60L, 0x127B_63AA_F333_1218L,
+ /* -285 */ 0x6B99_1487_DD65_7899L, 0x6A5F_05DE_51EB_5026L,
+ /* -284 */ 0x5614_106C_B11D_FA14L, 0x5518_D17E_A7EF_7352L,
+ /* -283 */ 0x44DC_D9F0_8DB1_94DDL, 0x2A7A_4132_1FF2_C2A8L,
+ /* -282 */ 0x6E2E_2980_E2B5_BAFBL, 0x5D90_6850_331E_043FL,
+ /* -281 */ 0x5824_EE00_B55E_2F2FL, 0x6473_86A6_8F4B_3699L,
+ /* -280 */ 0x4683_F19A_2AB1_BF59L, 0x36C2_D21E_D908_F87BL,
+ /* -279 */ 0x70D3_1C29_DDE9_3228L, 0x579E_1CFE_280E_5A5DL,
+ /* -278 */ 0x5A42_7CEE_4B20_F4EDL, 0x2C7E_7D98_200B_7B7EL,
+ /* -277 */ 0x4835_30BE_A280_C3F1L, 0x09FE_CAE0_19A2_C932L,
+ /* -276 */ 0x7388_4DFD_D0CE_064EL, 0x4331_4499_C29E_0EB6L,
+ /* -275 */ 0x5C6D_0B31_73D8_050BL, 0x4F5A_9D47_CEE4_D891L,
+ /* -274 */ 0x49F0_D5C1_2979_9DA2L, 0x72AE_E439_7250_AD41L,
+ /* -273 */ 0x764E_22CE_A8C2_95D1L, 0x377E_39F5_83B4_4868L,
+ /* -272 */ 0x5EA4_E8A5_53CE_DE41L, 0x12CB_6191_3629_D387L,
+ /* -271 */ 0x4BB7_2084_430B_E500L, 0x756F_8140_F821_7605L,
+ /* -270 */ 0x7925_00D3_9E79_6E67L, 0x6F18_CECE_59CF_233CL,
+ /* -269 */ 0x60EA_670F_B1FA_BEB9L, 0x3F47_0BD8_47D8_E8FDL,
+ /* -268 */ 0x4D88_5272_F4C8_9894L, 0x329F_3CAD_0647_20CAL,
+ /* -267 */ 0x7C0D_50B7_EE0D_C0EDL, 0x3765_2DE1_A3A5_0143L,
+ /* -266 */ 0x633D_DA2C_BE71_6724L, 0x2C50_F181_4FB7_3436L,
+ /* -265 */ 0x4F64_AE8A_31F4_5283L, 0x3D0D_8E01_0C92_902BL,
+ /* -264 */ 0x7F07_7DA9_E986_EA6BL, 0x7B48_E334_E0EA_8045L,
+ /* -263 */ 0x659F_97BB_2138_BB89L, 0x4907_1C2A_4D88_669DL,
+ /* -262 */ 0x514C_7962_80FA_2FA1L, 0x20D2_7CEE_A46D_1EE4L,
+ /* -261 */ 0x4109_FAB5_33FB_594DL, 0x670E_CA58_838A_7F1DL,
+ /* -260 */ 0x680F_F788_532B_C216L, 0x0B4A_DD5A_6C10_CB62L,
+ /* -259 */ 0x533F_F939_DC23_01ABL, 0x22A2_4AAE_BCDA_3C4EL,
+ /* -258 */ 0x4299_942E_49B5_9AEFL, 0x354E_A225_63E1_C9D8L,
+ /* -257 */ 0x6A8F_537D_42BC_2B18L, 0x554A_9D08_9FCF_A95AL,
+ /* -256 */ 0x553F_75FD_CEFC_EF46L, 0x776E_E406_E63F_BAAEL,
+ /* -255 */ 0x4432_C4CB_0BFD_8C38L, 0x5F8B_E99F_1E99_6225L,
+ /* -254 */ 0x6D1E_07AB_4662_79F4L, 0x3279_75CB_6428_9D08L,
+ /* -253 */ 0x574B_3955_D1E8_6190L, 0x2861_2B09_1CED_4A6DL,
+ /* -252 */ 0x45D5_C777_DB20_4E0DL, 0x06B4_226D_B0BD_D524L,
+ /* -251 */ 0x6FBC_7259_5E9A_167BL, 0x2453_6A49_1AC9_5506L,
+ /* -250 */ 0x5963_8EAD_E548_11FCL, 0x1D0F_883A_7BD4_4405L,
+ /* -249 */ 0x4782_D88B_1DD3_4196L, 0x4A72_D361_FCA9_D004L,
+ /* -248 */ 0x726A_F411_C952_028AL, 0x43EA_EBCF_FAA9_4CD3L,
+ /* -247 */ 0x5B88_C341_6DDB_353BL, 0x4FEF_230C_C887_70A9L,
+ /* -246 */ 0x493A_35CD_F17C_2A96L, 0x0CBF_4F3D_6D39_26EEL,
+ /* -245 */ 0x7529_EFAF_E8C6_AA89L, 0x6132_1862_485B_717CL,
+ /* -244 */ 0x5DBB_2626_53D2_2207L, 0x675B_46B5_06AF_8DFDL,
+ /* -243 */ 0x4AFC_1E85_0FDB_4E6CL, 0x52AF_6BC4_0559_3E64L,
+ /* -242 */ 0x77F9_CA6E_7FC5_4A47L, 0x377F_12D3_3BC1_FD6DL,
+ /* -241 */ 0x5FFB_0858_6637_6E9FL, 0x45FF_4242_9634_CABDL,
+ /* -240 */ 0x4CC8_D379_EB5F_8BB2L, 0x6B32_9B68_782A_3BCBL,
+ /* -239 */ 0x7ADA_EBF6_4565_AC51L, 0x2B84_2BDA_59DD_2C77L,
+ /* -238 */ 0x6248_BCC5_0451_56A7L, 0x3C69_BCAE_AE4A_89F9L,
+ /* -237 */ 0x4EA0_9704_0374_4552L, 0x6387_CA25_583B_A194L,
+ /* -236 */ 0x7DCD_BE6C_D253_A21EL, 0x05A6_103B_C05F_68EDL,
+ /* -235 */ 0x64A4_9857_0EA9_4E7EL, 0x37B8_0CFC_99E5_ED8AL,
+ /* -234 */ 0x5083_AD12_7221_0B98L, 0x2C93_3D96_E184_BE08L,
+ /* -233 */ 0x4069_5741_F4E7_3C79L, 0x7075_CADF_1AD0_9807L,
+ /* -232 */ 0x670E_F203_2171_FA5CL, 0x4D89_4498_2AE7_59A4L,
+ /* -231 */ 0x5272_5B35_B45B_2EB0L, 0x3E07_6A13_5585_E150L,
+ /* -230 */ 0x41F5_15C4_9048_F226L, 0x64D2_BB42_AAD1_810DL,
+ /* -229 */ 0x6988_22D4_1A0E_503EL, 0x07B7_9204_4482_6815L,
+ /* -228 */ 0x546C_E8A9_AE71_D9CBL, 0x1FC6_0E69_D068_5344L,
+ /* -227 */ 0x438A_53BA_F1F4_AE3CL, 0x196B_3EBB_0D20_429DL,
+ /* -226 */ 0x6C10_85F7_E987_7D2DL, 0x0F11_FDF8_1500_6A94L,
+ /* -225 */ 0x5673_9E5F_EE05_FDBDL, 0x58DB_3193_4400_5543L,
+ /* -224 */ 0x4529_4B7F_F19E_6497L, 0x60AF_5ADC_3666_AA9CL,
+ /* -223 */ 0x6EA8_78CC_B5CA_3A8CL, 0x344B_C493_8A3D_DDC7L,
+ /* -222 */ 0x5886_C70A_2B08_2ED6L, 0x5D09_6A0F_A1CB_17D2L,
+ /* -221 */ 0x46D2_38D4_EF39_BF12L, 0x173A_BB3F_B4A2_7975L,
+ /* -220 */ 0x7150_5AEE_4B8F_981DL, 0x0B91_2B99_2103_F588L,
+ /* -219 */ 0x5AA6_AF25_093F_ACE4L, 0x0940_EFAD_B403_2AD3L,
+ /* -218 */ 0x4885_58EA_6DCC_8A50L, 0x0767_2624_9002_88A9L,
+ /* -217 */ 0x7408_8E43_E2E0_DD4CL, 0x723E_A36D_B337_410EL,
+ /* -216 */ 0x5CD3_A503_1BE7_1770L, 0x5B65_4F8A_F5C5_CDA5L,
+ /* -215 */ 0x4A42_EA68_E31F_45F3L, 0x62B7_72D5_916B_0AEBL,
+ /* -214 */ 0x76D1_770E_3832_0986L, 0x0458_B7BC_1BDE_77DDL,
+ /* -213 */ 0x5F0D_F8D8_2CF4_D46BL, 0x1D13_C630_164B_9318L,
+ /* -212 */ 0x4C0B_2D79_BD90_A9EFL, 0x30DC_9E8C_DEA2_DC13L,
+ /* -211 */ 0x79AB_7BF5_FC1A_A97FL, 0x0160_FDAE_3104_9351L,
+ /* -210 */ 0x6155_FCC4_C9AE_EDFFL, 0x1AB3_FE24_F403_A90EL,
+ /* -209 */ 0x4DDE_63D0_A158_BE65L, 0x6229_981D_9002_EDA5L,
+ /* -208 */ 0x7C97_061A_9BC1_30A2L, 0x69DC_2695_B337_E2A1L,
+ /* -207 */ 0x63AC_04E2_1634_26E8L, 0x54B0_1EDE_28F9_821BL,
+ /* -206 */ 0x4FBC_D0B4_DE90_1F20L, 0x43C0_18B1_BA61_34E2L,
+ /* -205 */ 0x7F94_8121_6419_CB67L, 0x1F99_C11C_5D68_549DL,
+ /* -204 */ 0x6610_674D_E9AE_3C52L, 0x4C7B_00E3_7DED_107EL,
+ /* -203 */ 0x51A6_B90B_2158_3042L, 0x09FC_00B5_FE57_4065L,
+ /* -202 */ 0x4152_2DA2_8113_59CEL, 0x3B30_0091_9845_CD1DL,
+ /* -201 */ 0x6883_7C37_34EB_C2E3L, 0x784C_CDB5_C06F_AE95L,
+ /* -200 */ 0x539C_635F_5D89_68B6L, 0x2D0A_3E2B_0059_5877L,
+ /* -199 */ 0x42E3_82B2_B13A_BA2BL, 0x3DA1_CB55_99E1_1393L,
+ /* -198 */ 0x6B05_9DEA_B52A_C378L, 0x629C_7888_F634_EC1EL,
+ /* -197 */ 0x559E_17EE_F755_692DL, 0x3549_FA07_2B5D_89B1L,
+ /* -196 */ 0x447E_798B_F911_20F1L, 0x1107_FB38_EF7E_07C1L,
+ /* -195 */ 0x6D97_28DF_F4E8_34B5L, 0x01A6_5EC1_7F30_0C68L,
+ /* -194 */ 0x57AC_20B3_2A53_5D5DL, 0x4E1E_B234_65C0_09EDL,
+ /* -193 */ 0x4623_4D5C_21DC_4AB1L, 0x24E5_5B5D_1E33_3B24L,
+ /* -192 */ 0x7038_7BC6_9C93_AAB5L, 0x216E_F894_FD1E_C506L,
+ /* -191 */ 0x59C6_C96B_B076_222AL, 0x4DF2_6077_30E5_6A6CL,
+ /* -190 */ 0x47D2_3ABC_8D2B_4E88L, 0x3E5B_805F_5A51_21F0L,
+ /* -189 */ 0x72E9_F794_1512_1740L, 0x63C5_9A32_2A1B_697FL,
+ /* -188 */ 0x5BEE_5FA9_AA74_DF67L, 0x0304_7B5B_54E2_BACCL,
+ /* -187 */ 0x498B_7FBA_EEC3_E5ECL, 0x0269_FC49_10B5_623DL,
+ /* -186 */ 0x75AB_FF91_7E06_3CACL, 0x6A43_2D41_B455_69FBL,
+ /* -185 */ 0x5E23_32DA_CB38_308AL, 0x21CF_5767_C377_87FCL,
+ /* -184 */ 0x4B4F_5BE2_3C2C_F3A1L, 0x67D9_12B9_692C_6CCAL,
+ /* -183 */ 0x787E_F969_F9E1_85CFL, 0x595B_5128_A847_1476L,
+ /* -182 */ 0x6065_9454_C7E7_9E3FL, 0x6115_DA86_ED05_A9F8L,
+ /* -181 */ 0x4D1E_1043_D31F_B1CCL, 0x4DAB_1538_BD9E_2193L,
+ /* -180 */ 0x7B63_4D39_51CC_4FADL, 0x62AB_5527_95C9_CF52L,
+ /* -179 */ 0x62B5_D761_0E3D_0C8BL, 0x0222_AA86_116E_3F75L,
+ /* -178 */ 0x4EF7_DF80_D830_D6D5L, 0x4E82_2204_DABE_992AL,
+ /* -177 */ 0x7E59_659A_F381_57BCL, 0x1736_9CD4_9130_F510L,
+ /* -176 */ 0x6514_5148_C2CD_DFC9L, 0x5F5E_E3DD_40F3_F740L,
+ /* -175 */ 0x50DD_0DD3_CF0B_196EL, 0x1918_B64A_9A5C_C5CDL,
+ /* -174 */ 0x40B0_D7DC_A5A2_7ABEL, 0x4746_F83B_AEB0_9E3EL,
+ /* -173 */ 0x6781_5961_0903_F797L, 0x253E_59F9_1780_FD2FL,
+ /* -172 */ 0x52CD_E11A_6D9C_C612L, 0x50FE_AE60_DF9A_6426L,
+ /* -171 */ 0x423E_4DAE_BE17_04DBL, 0x5A65_584D_7FAE_B685L,
+ /* -170 */ 0x69FD_4917_968B_3AF9L, 0x10A2_26E2_65E4_573BL,
+ /* -169 */ 0x54CA_A0DF_ABA2_9594L, 0x0D4E_8581_EB1D_1295L,
+ /* -168 */ 0x43D5_4D7F_BC82_1143L, 0x243E_D134_BC17_4211L,
+ /* -167 */ 0x6C88_7BFF_9403_4ED2L, 0x06CA_E854_6025_3682L,
+ /* -166 */ 0x56D3_9666_1002_A574L, 0x6BD5_86A9_E684_2B9BL,
+ /* -165 */ 0x4576_11EB_4002_1DF7L, 0x0977_9EEE_5203_5616L,
+ /* -164 */ 0x6F23_4FDE_CCD0_2FF1L, 0x5BF2_97E3_B66B_BCEFL,
+ /* -163 */ 0x58E9_0CB2_3D73_598EL, 0x165B_ACB6_2B89_63F3L,
+ /* -162 */ 0x4720_D6F4_FDF5_E13EL, 0x4516_23C4_EFA1_1CC2L,
+ /* -161 */ 0x71CE_24BB_2FEF_CECAL, 0x3B56_9FA1_7F68_2E03L,
+ /* -160 */ 0x5B0B_5095_BFF3_0BD5L, 0x15DE_E61A_CC53_5803L,
+ /* -159 */ 0x48D5_DA11_665C_0977L, 0x2B18_B815_7042_ACCFL,
+ /* -158 */ 0x7489_5CE8_A3C6_758BL, 0x5E8D_F355_806A_AE18L,
+ /* -157 */ 0x5D3A_B0BA_1C9E_C46FL, 0x653E_5C44_66BB_BE7AL,
+ /* -156 */ 0x4A95_5A2E_7D4B_D059L, 0x3765_169D_1EFC_9861L,
+ /* -155 */ 0x7755_5D17_2EDF_B3C2L, 0x256E_8A94_FE60_F3CFL,
+ /* -154 */ 0x5F77_7DAC_257F_C301L, 0x6ABE_D543_FEB3_F63FL,
+ /* -153 */ 0x4C5F_97BC_EACC_9C01L, 0x3BCB_DDCF_FEF6_5E99L,
+ /* -152 */ 0x7A32_8C61_77AD_C668L, 0x5FAC_9619_97F0_975BL,
+ /* -151 */ 0x61C2_09E7_92F1_6B86L, 0x7FBD_44E1_465A_12AFL,
+ /* -150 */ 0x4E34_D4B9_425A_BC6BL, 0x7FCA_9D81_0514_DBBFL,
+ /* -149 */ 0x7D21_545B_9D5D_FA46L, 0x32DD_C8CE_6E87_C5FFL,
+ /* -148 */ 0x641A_A9E2_E44B_2E9EL, 0x5BE4_A0A5_2539_6B32L,
+ /* -147 */ 0x5015_54B5_836F_587EL, 0x7CB6_E6EA_842D_EF5CL,
+ /* -146 */ 0x4011_1091_35F2_AD32L, 0x3092_5255_368B_25E3L,
+ /* -145 */ 0x6681_B41B_8984_4850L, 0x4DB6_EA21_F0DE_A304L,
+ /* -144 */ 0x5201_5CE2_D469_D373L, 0x57C5_881B_2718_826AL,
+ /* -143 */ 0x419A_B0B5_76BB_0F8FL, 0x5FD1_39AF_527A_01EFL,
+ /* -142 */ 0x68F7_8122_5791_B27FL, 0x4C81_F5E5_50C3_364AL,
+ /* -141 */ 0x53F9_341B_7941_5B99L, 0x239B_2B1D_DA35_C508L,
+ /* -140 */ 0x432D_C349_2DCD_E2E1L, 0x02E2_88E4_AE91_6A6DL,
+ /* -139 */ 0x6B7C_6BA8_4949_6B01L, 0x516A_74A1_174F_10AEL,
+ /* -138 */ 0x55FD_22ED_076D_EF34L, 0x4121_F6E7_45D8_DA25L,
+ /* -137 */ 0x44CA_8257_3924_BF5DL, 0x1A81_9252_9E47_14EBL,
+ /* -136 */ 0x6E10_D08B_8EA1_322EL, 0x5D9C_1D50_FD3E_87DDL,
+ /* -135 */ 0x580D_73A2_D880_F4F2L, 0x17B0_1773_FDCB_9FE4L,
+ /* -134 */ 0x4671_294F_139A_5D8EL, 0x4626_7929_97D6_1984L,
+ /* -133 */ 0x70B5_0EE4_EC2A_2F4AL, 0x3D0A_5B75_BFBC_F59FL,
+ /* -132 */ 0x5A2A_7250_BCEE_8C3BL, 0x4A6E_AF91_6630_C47FL,
+ /* -131 */ 0x4821_F50D_63F2_09C9L, 0x21F2_260D_EB5A_36CCL,
+ /* -130 */ 0x7369_8815_6CB6_760EL, 0x6983_7016_455D_247AL,
+ /* -129 */ 0x5C54_6CDD_F091_F80BL, 0x6E02_C011_D117_5062L,
+ /* -128 */ 0x49DD_23E4_C074_C66FL, 0x719B_CCDB_0DAC_404EL,
+ /* -127 */ 0x762E_9FD4_6721_3D7FL, 0x68F9_47C4_E2AD_33B0L,
+ /* -126 */ 0x5E8B_B310_5280_FDFFL, 0x6D94_396A_4EF0_F627L,
+ /* -125 */ 0x4BA2_F5A6_A867_3199L, 0x3E10_2DEE_A58D_91B9L,
+ /* -124 */ 0x7904_BC3D_DA3E_B5C2L, 0x3019_E317_6F48_E927L,
+ /* -123 */ 0x60D0_9697_E1CB_C49BL, 0x4014_B5AC_5907_20ECL,
+ /* -122 */ 0x4D73_ABAC_B4A3_03AFL, 0x4CDD_5E23_7A6C_1A57L,
+ /* -121 */ 0x7BEC_45E1_2104_D2B2L, 0x47C8_969F_2A46_908AL,
+ /* -120 */ 0x6323_6B1A_80D0_A88EL, 0x6CA0_787F_5505_406FL,
+ /* -119 */ 0x4F4F_88E2_00A6_ED3FL, 0x0A19_F9FF_7737_66BFL,
+ /* -118 */ 0x7EE5_A7D0_010B_1531L, 0x5CF6_5CCB_F1F2_3DFEL,
+ /* -117 */ 0x6584_8640_00D5_AA8EL, 0x172B_7D6F_F4C1_CB32L,
+ /* -116 */ 0x5136_D1CC_CD77_BBA4L, 0x78EF_978C_C3CE_3C28L,
+ /* -115 */ 0x40F8_A7D7_0AC6_2FB7L, 0x13F2_DFA3_CFD8_3020L,
+ /* -114 */ 0x67F4_3FBE_77A3_7F8BL, 0x3984_9906_1959_E699L,
+ /* -113 */ 0x5329_CC98_5FB5_FFA2L, 0x6136_E0D1_ADE1_8548L,
+ /* -112 */ 0x4287_D6E0_4C91_994FL, 0x00F8_B3DA_F181_376DL,
+ /* -111 */ 0x6A72_F166_E0E8_F54BL, 0x1B27_862B_1C01_F247L,
+ /* -110 */ 0x5528_C11F_1A53_F76FL, 0x2F52_D1BC_1667_F506L,
+ /* -109 */ 0x4420_9A7F_4843_2C59L, 0x0C42_4163_451F_F738L,
+ /* -108 */ 0x6D00_F732_0D38_46F4L, 0x7A03_9BD2_0833_2526L,
+ /* -107 */ 0x5733_F8F4_D760_38C3L, 0x7B36_1641_A028_EA85L,
+ /* -106 */ 0x45C3_2D90_AC4C_FA36L, 0x2F5E_7834_8020_BB9EL,
+ /* -105 */ 0x6F9E_AF4D_E07B_29F0L, 0x4BCA_59ED_99CD_F8FCL,
+ /* -104 */ 0x594B_BF71_8062_87F3L, 0x563B_7B24_7B0B_2D96L,
+ /* -103 */ 0x476F_CC5A_CD1B_9FF6L, 0x11C9_2F50_626F_57ACL,
+ /* -102 */ 0x724C_7A2A_E1C5_CCBDL, 0x02DB_7EE7_03E5_5912L,
+ /* -101 */ 0x5B70_61BB_E7D1_7097L, 0x1BE2_CBEC_031D_E0DCL,
+ /* -100 */ 0x4926_B496_530D_F3ACL, 0x164F_0989_9C17_E716L,
+ /* -99 */ 0x750A_BA8A_1E7C_B913L, 0x3D4B_4275_C68C_A4F0L,
+ /* -98 */ 0x5DA2_2ED4_E530_940FL, 0x4AA2_9B91_6BA3_B726L,
+ /* -97 */ 0x4AE8_2577_1DC0_7672L, 0x6EE8_7C74_561C_9285L,
+ /* -96 */ 0x77D9_D58B_62CD_8A51L, 0x3173_FA53_BCFA_8408L,
+ /* -95 */ 0x5FE1_77A2_B571_3B74L, 0x278F_FB76_30C8_69A0L,
+ /* -94 */ 0x4CB4_5FB5_5DF4_2F90L, 0x1FA6_62C4_F3D3_87B3L,
+ /* -93 */ 0x7ABA_32BB_C986_B280L, 0x32A3_D13B_1FB8_D91FL,
+ /* -92 */ 0x622E_8EFC_A138_8ECDL, 0x0EE9_742F_4C93_E0E6L,
+ /* -91 */ 0x4E8B_A596_E760_723DL, 0x58BA_C359_0A0F_E71EL,
+ /* -90 */ 0x7DAC_3C24_A567_1D2FL, 0x412A_D228_1019_71C9L,
+ /* -89 */ 0x6489_C9B6_EAB8_E426L, 0x00EF_0E86_7347_8E3BL,
+ /* -88 */ 0x506E_3AF8_BBC7_1CEBL, 0x1A58_D86B_8F6C_71C9L,
+ /* -87 */ 0x4058_2F2D_6305_B0BCL, 0x1513_E056_0C56_C16EL,
+ /* -86 */ 0x66F3_7EAF_04D5_E793L, 0x3B53_0089_AD57_9BE2L,
+ /* -85 */ 0x525C_6558_D0AB_1FA9L, 0x15DC_006E_2446_164FL,
+ /* -84 */ 0x41E3_8447_0D55_B2EDL, 0x5E49_99F1_B69E_783FL,
+ /* -83 */ 0x696C_06D8_1555_EB15L, 0x7D42_8FE9_2430_C065L,
+ /* -82 */ 0x5456_6BE0_1111_88DEL, 0x3102_0CBA_835A_3384L,
+ /* -81 */ 0x4378_564C_DA74_6D7EL, 0x5A68_0A2E_CF7B_5C69L,
+ /* -80 */ 0x6BF3_BD47_C3ED_7BFDL, 0x770C_DD17_B25E_FA42L,
+ /* -79 */ 0x565C_976C_9CBD_FCCBL, 0x1270_B0DF_C1E5_9502L,
+ /* -78 */ 0x4516_DF8A_16FE_63D5L, 0x5B8D_5A4C_9B1E_10CEL,
+ /* -77 */ 0x6E8A_FF43_57FD_6C89L, 0x127B_C3AD_C4FC_E7B0L,
+ /* -76 */ 0x586F_329C_4664_56D4L, 0x0EC9_6957_D0CA_52F3L,
+ /* -75 */ 0x46BF_5BB0_3850_4576L, 0x3F07_8779_73D5_0F29L,
+ /* -74 */ 0x7132_2C4D_26E6_D58AL, 0x31A5_A58F_1FBB_4B75L,
+ /* -73 */ 0x5A8E_89D7_5252_446EL, 0x5AEA_EAD8_E62F_6F91L,
+ /* -72 */ 0x4872_07DF_750E_9D25L, 0x2F22_557A_51BF_8C74L,
+ /* -71 */ 0x73E9_A632_54E4_2EA2L, 0x1836_EF2A_1C65_AD86L,
+ /* -70 */ 0x5CBA_EB5B_771C_F21BL, 0x2CF8_BF54_E384_8AD2L,
+ /* -69 */ 0x4A2F_22AF_927D_8E7CL, 0x23FA_32AA_4F9D_3BDBL,
+ /* -68 */ 0x76B1_D118_EA62_7D93L, 0x5329_EAAA_18FB_92F8L,
+ /* -67 */ 0x5EF4_A747_21E8_6476L, 0x0F54_BBBB_472F_A8C6L,
+ /* -66 */ 0x4BF6_EC38_E7ED_1D2BL, 0x25DD_62FC_38F2_ED6CL,
+ /* -65 */ 0x798B_138E_3FE1_C845L, 0x22FB_D193_8E51_7BDFL,
+ /* -64 */ 0x613C_0FA4_FFE7_D36AL, 0x4F2F_DADC_71DA_C97FL,
+ /* -63 */ 0x4DC9_A61D_9986_42BBL, 0x58F3_157D_27E2_3ACCL,
+ /* -62 */ 0x7C75_D695_C270_6AC5L, 0x74B8_2261_D969_F7ADL,
+ /* -61 */ 0x6391_7877_CEC0_556BL, 0x1093_4EB4_ADEE_5FBEL,
+ /* -60 */ 0x4FA7_9393_0BCD_1122L, 0x4075_D890_8B25_1965L,
+ /* -59 */ 0x7F72_85B8_12E1_B504L, 0x00BC_8DB4_11D4_F56EL,
+ /* -58 */ 0x65F5_37C6_7581_5D9CL, 0x66FD_3E29_A7DD_9125L,
+ /* -57 */ 0x5190_F96B_9134_4AE3L, 0x6BFD_CB54_864A_DA84L,
+ /* -56 */ 0x4140_C789_40F6_A24FL, 0x6FFE_3C43_9EA2_486AL,
+ /* -55 */ 0x6867_A5A8_67F1_03B2L, 0x7FFD_2D38_FDD0_73DCL,
+ /* -54 */ 0x5386_1E20_5327_3628L, 0x6664_242D_97D9_F64AL,
+ /* -53 */ 0x42D1_B1B3_75B8_F820L, 0x51E9_B68A_DFE1_91D5L,
+ /* -52 */ 0x6AE9_1C52_55F4_C034L, 0x1CA9_2411_6635_B621L,
+ /* -51 */ 0x5587_49DB_77F7_0029L, 0x63BA_8341_1E91_5E81L,
+ /* -50 */ 0x446C_3B15_F992_6687L, 0x6962_029A_7EDA_B201L,
+ /* -49 */ 0x6D79_F823_28EA_3DA6L, 0x0F03_375D_97C4_5001L,
+ /* -48 */ 0x5794_C682_8721_CAEBL, 0x259C_2C4A_DFD0_4001L,
+ /* -47 */ 0x4610_9ECE_D281_6F22L, 0x5149_BD08_B30D_0001L,
+ /* -46 */ 0x701A_97B1_50CF_1837L, 0x3542_C80D_EB48_0001L,
+ /* -45 */ 0x59AE_DFC1_0D72_79C5L, 0x7768_A00B_22A0_0001L,
+ /* -44 */ 0x47BF_1967_3DF5_2E37L, 0x7920_8008_E880_0001L,
+ /* -43 */ 0x72CB_5BD8_6321_E38CL, 0x5B67_3341_7400_0001L,
+ /* -42 */ 0x5BD5_E313_8281_82D6L, 0x7C52_8F67_9000_0001L,
+ /* -41 */ 0x4977_E8DC_6867_9BDFL, 0x16A8_72B9_4000_0001L,
+ /* -40 */ 0x758C_A7C7_0D72_92FEL, 0x5773_EAC2_0000_0001L,
+ /* -39 */ 0x5E0A_1FD2_7128_7598L, 0x45F6_5568_0000_0001L,
+ /* -38 */ 0x4B3B_4CA8_5A86_C47AL, 0x04C5_1120_0000_0001L,
+ /* -37 */ 0x785E_E10D_5DA4_6D90L, 0x07A1_B500_0000_0001L,
+ /* -36 */ 0x604B_E73D_E483_8AD9L, 0x52E7_C400_0000_0001L,
+ /* -35 */ 0x4D09_85CB_1D36_08AEL, 0x0F1F_D000_0000_0001L,
+ /* -34 */ 0x7B42_6FAB_61F0_0DE3L, 0x31CC_8000_0000_0001L,
+ /* -33 */ 0x629B_8C89_1B26_7182L, 0x5B0A_0000_0000_0001L,
+ /* -32 */ 0x4EE2_D6D4_15B8_5ACEL, 0x7C08_0000_0000_0001L,
+ /* -31 */ 0x7E37_BE20_22C0_914BL, 0x1340_0000_0000_0001L,
+ /* -30 */ 0x64F9_64E6_8233_A76FL, 0x2900_0000_0000_0001L,
+ /* -29 */ 0x50C7_83EB_9B5C_85F2L, 0x5400_0000_0000_0001L,
+ /* -28 */ 0x409F_9CBC_7C4A_04C2L, 0x1000_0000_0000_0001L,
+ /* -27 */ 0x6765_C793_FA10_079DL, 0x0000_0000_0000_0001L,
+ /* -26 */ 0x52B7_D2DC_C80C_D2E4L, 0x0000_0000_0000_0001L,
+ /* -25 */ 0x422C_A8B0_A00A_4250L, 0x0000_0000_0000_0001L,
+ /* -24 */ 0x69E1_0DE7_6676_D080L, 0x0000_0000_0000_0001L,
+ /* -23 */ 0x54B4_0B1F_852B_DA00L, 0x0000_0000_0000_0001L,
+ /* -22 */ 0x43C3_3C19_3756_4800L, 0x0000_0000_0000_0001L,
+ /* -21 */ 0x6C6B_935B_8BBD_4000L, 0x0000_0000_0000_0001L,
+ /* -20 */ 0x56BC_75E2_D631_0000L, 0x0000_0000_0000_0001L,
+ /* -19 */ 0x4563_9182_44F4_0000L, 0x0000_0000_0000_0001L,
+ /* -18 */ 0x6F05_B59D_3B20_0000L, 0x0000_0000_0000_0001L,
+ /* -17 */ 0x58D1_5E17_6280_0000L, 0x0000_0000_0000_0001L,
+ /* -16 */ 0x470D_E4DF_8200_0000L, 0x0000_0000_0000_0001L,
+ /* -15 */ 0x71AF_D498_D000_0000L, 0x0000_0000_0000_0001L,
+ /* -14 */ 0x5AF3_107A_4000_0000L, 0x0000_0000_0000_0001L,
+ /* -13 */ 0x48C2_7395_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -12 */ 0x746A_5288_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -11 */ 0x5D21_DBA0_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -10 */ 0x4A81_7C80_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -9 */ 0x7735_9400_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -8 */ 0x5F5E_1000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -7 */ 0x4C4B_4000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -6 */ 0x7A12_0000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -5 */ 0x61A8_0000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -4 */ 0x4E20_0000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -3 */ 0x7D00_0000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -2 */ 0x6400_0000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* -1 */ 0x5000_0000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* 0 */ 0x4000_0000_0000_0000L, 0x0000_0000_0000_0001L,
+ /* 1 */ 0x6666_6666_6666_6666L, 0x3333_3333_3333_3334L,
+ /* 2 */ 0x51EB_851E_B851_EB85L, 0x0F5C_28F5_C28F_5C29L,
+ /* 3 */ 0x4189_374B_C6A7_EF9DL, 0x5916_872B_020C_49BBL,
+ /* 4 */ 0x68DB_8BAC_710C_B295L, 0x74F0_D844_D013_A92BL,
+ /* 5 */ 0x53E2_D623_8DA3_C211L, 0x43F3_E037_0CDC_8755L,
+ /* 6 */ 0x431B_DE82_D7B6_34DAL, 0x698F_E692_70B0_6C44L,
+ /* 7 */ 0x6B5F_CA6A_F2BD_215EL, 0x0F4C_A41D_811A_46D4L,
+ /* 8 */ 0x55E6_3B88_C230_E77EL, 0x3F70_834A_CDAE_9F10L,
+ /* 9 */ 0x44B8_2FA0_9B5A_52CBL, 0x4C5A_02A2_3E25_4C0DL,
+ /* 10 */ 0x6DF3_7F67_5EF6_EADFL, 0x2D5C_D103_96A2_1347L,
+ /* 11 */ 0x57F5_FF85_E592_557FL, 0x3DE3_DA69_454E_75D3L,
+ /* 12 */ 0x465E_6604_B7A8_4465L, 0x7E4F_E1ED_D10B_9175L,
+ /* 13 */ 0x7097_09A1_25DA_0709L, 0x4A19_697C_81AC_1BEFL,
+ /* 14 */ 0x5A12_6E1A_84AE_6C07L, 0x54E1_2130_67BC_E326L,
+ /* 15 */ 0x480E_BE7B_9D58_566CL, 0x43E7_4DC0_52FD_8285L,
+ /* 16 */ 0x734A_CA5F_6226_F0ADL, 0x530B_AF9A_1E62_6A6DL,
+ /* 17 */ 0x5C3B_D519_1B52_5A24L, 0x426F_BFAE_7EB5_21F1L,
+ /* 18 */ 0x49C9_7747_490E_AE83L, 0x4EBF_CC8B_9890_E7F4L,
+ /* 19 */ 0x760F_253E_DB4A_B0D2L, 0x4ACC_7A78_F41B_0CBAL,
+ /* 20 */ 0x5E72_8432_4908_8D75L, 0x223D_2EC7_29AF_3D62L,
+ /* 21 */ 0x4B8E_D028_3A6D_3DF7L, 0x34FD_BF05_BAF2_9781L,
+ /* 22 */ 0x78E4_8040_5D7B_9658L, 0x54C9_31A2_C4B7_58CFL,
+ /* 23 */ 0x60B6_CD00_4AC9_4513L, 0x5D6D_C14F_03C5_E0A5L,
+ /* 24 */ 0x4D5F_0A66_A23A_9DA9L, 0x3124_9AA5_9C9E_4D51L,
+ /* 25 */ 0x7BCB_43D7_69F7_62A8L, 0x4EA0_F76F_60FD_4882L,
+ /* 26 */ 0x6309_0312_BB2C_4EEDL, 0x254D_92BF_80CA_A068L,
+ /* 27 */ 0x4F3A_68DB_C8F0_3F24L, 0x1DD7_A899_33D5_4D20L,
+ /* 28 */ 0x7EC3_DAF9_4180_6506L, 0x62F2_A75B_8622_1500L,
+ /* 29 */ 0x6569_7BFA_9ACD_1D9FL, 0x025B_B916_04E8_10CDL,
+ /* 30 */ 0x5121_2FFB_AF0A_7E18L, 0x6849_60DE_6A53_40A4L,
+ /* 31 */ 0x40E7_5996_25A1_FE7AL, 0x203A_B3E5_21DC_33B6L,
+ /* 32 */ 0x67D8_8F56_A29C_CA5DL, 0x19F7_863B_6960_52BDL,
+ /* 33 */ 0x5313_A5DE_E87D_6EB0L, 0x7B2C_6B62_BAB3_7564L,
+ /* 34 */ 0x4276_1E4B_ED31_255AL, 0x2F56_BC4E_FBC2_C450L,
+ /* 35 */ 0x6A56_96DF_E1E8_3BC3L, 0x6557_93B1_92D1_3A1AL,
+ /* 36 */ 0x5512_124C_B4B9_C969L, 0x3779_42F4_7574_2E7BL,
+ /* 37 */ 0x440E_750A_2A2E_3ABAL, 0x5F94_3590_5DF6_8B96L,
+ /* 38 */ 0x6CE3_EE76_A9E3_912AL, 0x65B9_EF4D_6324_1289L,
+ /* 39 */ 0x571C_BEC5_54B6_0DBBL, 0x6AFB_25D7_8283_4207L,
+ /* 40 */ 0x45B0_989D_DD5E_7163L, 0x08C8_EB12_CECF_6806L,
+ /* 41 */ 0x6F80_F42F_C897_1BD1L, 0x5ADB_11B7_B14B_D9A3L,
+ /* 42 */ 0x5933_F68C_A078_E30EL, 0x157C_0E2C_8DD6_47B5L,
+ /* 43 */ 0x475C_C53D_4D2D_8271L, 0x5DFC_D823_A4AB_6C91L,
+ /* 44 */ 0x722E_0862_1515_9D82L, 0x632E_269F_6DDF_141BL,
+ /* 45 */ 0x5B58_06B4_DDAA_E468L, 0x4F58_1EE5_F17F_4349L,
+ /* 46 */ 0x4913_3890_B155_8386L, 0x72AC_E584_C132_9C3BL,
+ /* 47 */ 0x74EB_8DB4_4EEF_38D7L, 0x6AAE_3C07_9B84_2D2AL,
+ /* 48 */ 0x5D89_3E29_D8BF_60ACL, 0x5558_3006_1603_5755L,
+ /* 49 */ 0x4AD4_31BB_13CC_4D56L, 0x7779_C004_DE69_12ABL,
+ /* 50 */ 0x77B9_E92B_52E0_7BBEL, 0x258F_99A1_63DB_5111L,
+ /* 51 */ 0x5FC7_EDBC_424D_2FCBL, 0x37A6_1481_1CAF_740DL,
+ /* 52 */ 0x4C9F_F163_683D_BFD5L, 0x7951_AA00_E3BF_900BL,
+ /* 53 */ 0x7A99_8238_A6C9_32EFL, 0x754F_7667_D2CC_19ABL,
+ /* 54 */ 0x6214_682D_523A_8F26L, 0x2AA5_F853_0F09_AE22L,
+ /* 55 */ 0x4E76_B9BD_DB62_0C1EL, 0x5551_9375_A5A1_581BL,
+ /* 56 */ 0x7D8A_C2C9_5F03_4697L, 0x3BB5_B8BC_3C35_59C5L,
+ /* 57 */ 0x646F_023A_B269_0545L, 0x7C91_6096_9691_149EL,
+ /* 58 */ 0x5058_CE95_5B87_376BL, 0x16DA_B3AB_ABA7_43B2L,
+ /* 59 */ 0x4047_0BAA_AF9F_5F88L, 0x78AE_F622_EFB9_02F5L,
+ /* 60 */ 0x66D8_12AA_B298_98DBL, 0x0DE4_BD04_B2C1_9E54L,
+ /* 61 */ 0x5246_7555_5BAD_4715L, 0x57EA_30D0_8F01_4B76L,
+ /* 62 */ 0x41D1_F777_7C8A_9F44L, 0x4654_F3DA_0C01_092CL,
+ /* 63 */ 0x694F_F258_C744_3207L, 0x23BB_1FC3_4668_0EACL,
+ /* 64 */ 0x543F_F513_D29C_F4D2L, 0x4FC8_E635_D1EC_D88AL,
+ /* 65 */ 0x4366_5DA9_754A_5D75L, 0x263A_51C4_A7F0_AD3BL,
+ /* 66 */ 0x6BD6_FC42_5543_C8BBL, 0x56C3_B607_731A_AEC4L,
+ /* 67 */ 0x5645_969B_7769_6D62L, 0x789C_919F_8F48_8BD0L,
+ /* 68 */ 0x4504_787C_5F87_8AB5L, 0x46E3_A7B2_D906_D640L,
+ /* 69 */ 0x6E6D_8D93_CC0C_1122L, 0x3E39_0C51_5B3E_239AL,
+ /* 70 */ 0x5857_A476_3CD6_741BL, 0x4B60_D6A7_7C31_B615L,
+ /* 71 */ 0x46AC_8391_CA45_29AFL, 0x55E7_121F_968E_2B44L,
+ /* 72 */ 0x7114_05B6_106E_A919L, 0x0971_B698_F0E3_786DL,
+ /* 73 */ 0x5A76_6AF8_0D25_5414L, 0x078E_2BAD_8D82_C6BDL,
+ /* 74 */ 0x485E_BBF9_A41D_DCDCL, 0x6C71_BC8A_D79B_D231L,
+ /* 75 */ 0x73CA_C65C_39C9_6161L, 0x2D82_C744_8C2C_8382L,
+ /* 76 */ 0x5CA2_3849_C7D4_4DE7L, 0x3E02_3903_A356_CF9BL,
+ /* 77 */ 0x4A1B_603B_0643_7185L, 0x7E68_2D9C_82AB_D949L,
+ /* 78 */ 0x7692_3391_A39F_1C09L, 0x4A40_48FA_6AAC_8EDBL,
+ /* 79 */ 0x5EDB_5C74_82E5_B007L, 0x5500_3A61_EEF0_7249L,
+ /* 80 */ 0x4BE2_B05D_3584_8CD2L, 0x7733_61E7_F259_F507L,
+ /* 81 */ 0x796A_B3C8_55A0_E151L, 0x3EB8_9CA6_508F_EE71L,
+ /* 82 */ 0x6122_296D_114D_810DL, 0x7EFA_16EB_73A6_585BL,
+ /* 83 */ 0x4DB4_EDF0_DAA4_673EL, 0x3261_ABEF_8FB8_46AFL,
+ /* 84 */ 0x7C54_AFE7_C43A_3ECAL, 0x1D69_1318_E5F3_A44BL,
+ /* 85 */ 0x6376_F31F_D02E_98A1L, 0x6454_0F47_1E5C_836FL,
+ /* 86 */ 0x4F92_5C19_7358_7A1BL, 0x0376_729F_4B7D_35F3L,
+ /* 87 */ 0x7F50_935B_EBC0_C35EL, 0x38BD_8432_1261_EFEBL,
+ /* 88 */ 0x65DA_0F7C_BC9A_35E5L, 0x13CA_D028_0EB4_BFEFL,
+ /* 89 */ 0x517B_3F96_FD48_2B1DL, 0x5CA2_4020_0BC3_CCBFL,
+ /* 90 */ 0x412F_6612_6439_BC17L, 0x63B5_0019_A303_0A33L,
+ /* 91 */ 0x684B_D683_D38F_9359L, 0x1F88_0029_04D1_A9EAL,
+ /* 92 */ 0x536F_DECF_DC72_DC47L, 0x32D3_3354_03DA_EE55L,
+ /* 93 */ 0x42BF_E573_16C2_49D2L, 0x5BDC_2910_0315_8B77L,
+ /* 94 */ 0x6ACC_A251_BE03_A951L, 0x12F9_DB4C_D1BC_1258L,
+ /* 95 */ 0x5570_81DA_FE69_5440L, 0x7594_AF70_A7C9_A847L,
+ /* 96 */ 0x445A_017B_FEBA_A9CDL, 0x4476_F2C0_863A_ED06L,
+ /* 97 */ 0x6D5C_CF2C_CAC4_42E2L, 0x3A57_EACD_A391_7B3CL,
+ /* 98 */ 0x577D_728A_3BD0_3581L, 0x7B79_88A4_82DA_C8FDL,
+ /* 99 */ 0x45FD_F53B_630C_F79BL, 0x15FA_D3B6_CF15_6D97L,
+ /* 100 */ 0x6FFC_BB92_3814_BF5EL, 0x565E_1F8A_E4EF_15BEL,
+ /* 101 */ 0x5996_FC74_F9AA_32B2L, 0x11E4_E608_B725_AAFFL,
+ /* 102 */ 0x47AB_FD2A_6154_F55BL, 0x27EA_51A0_9284_88CCL,
+ /* 103 */ 0x72AC_C843_CEEE_555EL, 0x7310_829A_8407_4146L,
+ /* 104 */ 0x5BBD_6D03_0BF1_DDE5L, 0x4273_9BAE_D005_CDD2L,
+ /* 105 */ 0x4964_5735_A327_E4B7L, 0x4EC2_E2F2_4004_A4A8L,
+ /* 106 */ 0x756D_5855_D1D9_6DF2L, 0x4AD1_6B1D_333A_A10CL,
+ /* 107 */ 0x5DF1_1377_DB14_57F5L, 0x2241_227D_C295_4DA3L,
+ /* 108 */ 0x4B27_42C6_48DD_132AL, 0x4E9A_81FE_3544_3E1CL,
+ /* 109 */ 0x783E_D13D_4161_B844L, 0x175D_9CC9_EED3_9694L,
+ /* 110 */ 0x6032_40FD_CDE7_C69CL, 0x7917_B0A1_8BDC_7876L,
+ /* 111 */ 0x4CF5_00CB_0B1F_D217L, 0x1412_F3B4_6FE3_9392L,
+ /* 112 */ 0x7B21_9ADE_7832_E9BEL, 0x5351_85ED_7FD2_85B6L,
+ /* 113 */ 0x6281_48B1_F9C2_5498L, 0x42A7_9E57_9975_37C5L,
+ /* 114 */ 0x4ECD_D3C1_949B_76E0L, 0x3552_E512_E12A_9304L,
+ /* 115 */ 0x7E16_1F9C_20F8_BE33L, 0x6EEB_081E_3510_EB39L,
+ /* 116 */ 0x64DE_7FB0_1A60_9829L, 0x3F22_6CE4_F740_BC2EL,
+ /* 117 */ 0x50B1_FFC0_151A_1354L, 0x3281_F0B7_2C33_C9BEL,
+ /* 118 */ 0x408E_6633_4414_DC43L, 0x4201_8D5F_568F_D498L,
+ /* 119 */ 0x674A_3D1E_D354_939FL, 0x1CCF_4898_8A7F_BA8DL,
+ /* 120 */ 0x52A1_CA7F_0F76_DC7FL, 0x30A5_D3AD_3B99_620BL,
+ /* 121 */ 0x421B_0865_A5F8_B065L, 0x73B7_DC8A_9614_4E6FL,
+ /* 122 */ 0x69C4_DA3C_3CC1_1A3CL, 0x52BF_C744_2353_B0B1L,
+ /* 123 */ 0x549D_7B63_63CD_AE96L, 0x7566_3903_4F76_26F4L,
+ /* 124 */ 0x43B1_2F82_B63E_2545L, 0x4451_C735_D92B_525DL,
+ /* 125 */ 0x6C4E_B26A_BD30_3BA2L, 0x3A1C_71EF_C1DE_EA2EL,
+ /* 126 */ 0x56A5_5B88_9759_C94EL, 0x61B0_5B26_34B2_54F2L,
+ /* 127 */ 0x4551_1606_DF7B_0772L, 0x1AF3_7C1E_908E_AA5BL,
+ /* 128 */ 0x6EE8_233E_325E_7250L, 0x2B1F_2CFD_B417_76F8L,
+ /* 129 */ 0x58B9_B5CB_5B7E_C1D9L, 0x6F4C_23FE_29AC_5F2DL,
+ /* 130 */ 0x46FA_F7D5_E2CB_CE47L, 0x72A3_4FFE_87BD_18F1L,
+ /* 131 */ 0x7191_8C89_6ADF_B073L, 0x0438_7FFD_A5FB_5B1BL,
+ /* 132 */ 0x5ADA_D6D4_557F_C05CL, 0x0360_6664_84C9_15AFL,
+ /* 133 */ 0x48AF_1243_7799_66B0L, 0x02B3_851D_3707_448CL,
+ /* 134 */ 0x744B_506B_F28F_0AB3L, 0x1DEC_082E_BE72_0746L,
+ /* 135 */ 0x5D09_0D23_2872_6EF5L, 0x64BC_D358_985B_3905L,
+ /* 136 */ 0x4A6D_A41C_205B_8BF7L, 0x6A30_A913_AD15_C738L,
+ /* 137 */ 0x7715_D360_33C5_ACBFL, 0x5D1A_A81F_7B56_0B8CL,
+ /* 138 */ 0x5F44_A919_C304_8A32L, 0x7DAE_ECE5_FC44_D609L,
+ /* 139 */ 0x4C36_EDAE_359D_3B5BL, 0x7E25_8A51_969D_7808L,
+ /* 140 */ 0x79F1_7C49_EF61_F893L, 0x16A2_76E8_F0FB_F33FL,
+ /* 141 */ 0x618D_FD07_F2B4_C6DCL, 0x121B_9253_F3FC_C299L,
+ /* 142 */ 0x4E0B_30D3_2890_9F16L, 0x41AF_A843_2997_0214L,
+ /* 143 */ 0x7CDE_B485_0DB4_31BDL, 0x4F7F_739E_A8F1_9CEDL,
+ /* 144 */ 0x63E5_5D37_3E29_C164L, 0x3F99_294B_BA5A_E3F1L,
+ /* 145 */ 0x4FEA_B0F8_FE87_CDE9L, 0x7FAD_BAA2_FB7B_E98DL,
+ /* 146 */ 0x7FDD_E7F4_CA72_E30FL, 0x7F7C_5DD1_925F_DC15L,
+ /* 147 */ 0x664B_1FF7_085B_E8D9L, 0x4C63_7E41_41E6_49ABL,
+ /* 148 */ 0x51D5_B32C_06AF_ED7AL, 0x704F_9834_34B8_3AEFL,
+ /* 149 */ 0x4177_C289_9EF3_2462L, 0x26A6_135C_F6F9_C8BFL,
+ /* 150 */ 0x68BF_9DA8_FE51_D3D0L, 0x3DD6_8561_8B29_4132L,
+ /* 151 */ 0x53CC_7E20_CB74_A973L, 0x4B12_044E_08ED_CDC2L,
+ /* 152 */ 0x4309_FE80_A2C3_BAC2L, 0x6F41_9D0B_3A57_D7CEL,
+ /* 153 */ 0x6B43_30CD_D139_2AD1L, 0x3202_94DE_C3BF_BFB0L,
+ /* 154 */ 0x55CF_5A3E_40FA_88A7L, 0x419B_AA4B_CFCC_995AL,
+ /* 155 */ 0x44A5_E1CB_672E_D3B9L, 0x1AE2_EEA3_0CA3_ADE1L,
+ /* 156 */ 0x6DD6_3612_3EB1_52C1L, 0x77D1_7DD1_ADD2_AFCFL,
+ /* 157 */ 0x57DE_91A8_3227_7567L, 0x7974_64A7_BE42_263FL,
+ /* 158 */ 0x464B_A7B9_C1B9_2AB9L, 0x4790_5086_31CE_84FFL,
+ /* 159 */ 0x7079_0C5C_6928_445CL, 0x0C1A_1A70_4FB0_D4CCL,
+ /* 160 */ 0x59FA_7049_EDB9_D049L, 0x567B_4859_D95A_43D6L,
+ /* 161 */ 0x47FB_8D07_F161_736EL, 0x11FC_39E1_7AAE_9CABL,
+ /* 162 */ 0x732C_14D9_8235_857DL, 0x032D_2968_C44A_9445L,
+ /* 163 */ 0x5C23_43E1_34F7_9DFDL, 0x4F57_5453_D03B_A9D1L,
+ /* 164 */ 0x49B5_CFE7_5D92_E4CAL, 0x72AC_4376_402F_BB0EL,
+ /* 165 */ 0x75EF_B30B_C8EB_07ABL, 0x0446_D256_CD19_2B49L,
+ /* 166 */ 0x5E59_5C09_6D88_D2EFL, 0x1D05_7512_3DAD_BC3AL,
+ /* 167 */ 0x4B7A_B007_8AD3_DBF2L, 0x4A6A_C40E_97BE_302FL,
+ /* 168 */ 0x78C4_4CD8_DE1F_C650L, 0x7711_39B0_F2C9_E6B1L,
+ /* 169 */ 0x609D_0A47_1819_6B73L, 0x78DA_948D_8F07_EBC1L,
+ /* 170 */ 0x4D4A_6E9F_467A_BC5CL, 0x60AE_DD3E_0C06_5634L,
+ /* 171 */ 0x7BAA_4A98_70C4_6094L, 0x344A_FB96_79A3_BD20L,
+ /* 172 */ 0x62EE_A213_8D69_E6DDL, 0x103B_FC78_614F_CA80L,
+ /* 173 */ 0x4F25_4E76_0ABB_1F17L, 0x2696_6393_810C_A200L,
+ /* 174 */ 0x7EA2_1723_445E_9825L, 0x2423_D285_9B47_6999L,
+ /* 175 */ 0x654E_78E9_037E_E01DL, 0x69B6_4204_7C39_2148L,
+ /* 176 */ 0x510B_93ED_9C65_8017L, 0x6E2B_6803_9694_1AA0L,
+ /* 177 */ 0x40D6_0FF1_49EA_CCDFL, 0x71BC_5336_1210_154DL,
+ /* 178 */ 0x67BC_E64E_DCAA_E166L, 0x1C60_8523_5019_BBAEL,
+ /* 179 */ 0x52FD_850B_E3BB_E784L, 0x7D1A_041C_4014_9625L,
+ /* 180 */ 0x4264_6A6F_E963_1F9DL, 0x4A7B_367D_0010_781DL,
+ /* 181 */ 0x6A3A_43E6_4238_3295L, 0x5D91_F0C8_001A_59C8L,
+ /* 182 */ 0x54FB_6985_01C6_8EDEL, 0x17A7_F3D3_3348_47D4L,
+ /* 183 */ 0x43FC_546A_67D2_0BE4L, 0x7953_2975_C2A0_3976L,
+ /* 184 */ 0x6CC6_ED77_0C83_463BL, 0x0EEB_7589_3766_C256L,
+ /* 185 */ 0x5705_8AC5_A39C_382FL, 0x2589_2AD4_2C52_3512L,
+ /* 186 */ 0x459E_089E_1C7C_F9BFL, 0x37A0_EF10_2374_F742L,
+ /* 187 */ 0x6F63_40FC_FA61_8F98L, 0x5901_7E80_38BB_2536L,
+ /* 188 */ 0x591C_33FD_951A_D946L, 0x7A67_9866_93C8_EA91L,
+ /* 189 */ 0x4749_C331_4415_7A9FL, 0x151F_AD1E_DCA0_BBA8L,
+ /* 190 */ 0x720F_9EB5_39BB_F765L, 0x0832_AE97_C767_92A5L,
+ /* 191 */ 0x5B3F_B22A_9496_5F84L, 0x068E_F213_05EC_7551L,
+ /* 192 */ 0x48FF_C1BB_AA11_E603L, 0x1ED8_C1A8_D189_F774L,
+ /* 193 */ 0x74CC_692C_434F_D66BL, 0x4AF4_690E_1C0F_F253L,
+ /* 194 */ 0x5D70_5423_690C_AB89L, 0x225D_20D8_1673_2843L,
+ /* 195 */ 0x4AC0_434F_873D_5607L, 0x3517_4D79_AB8F_5369L,
+ /* 196 */ 0x779A_054C_0B95_5672L, 0x21BE_E25C_45B2_1F0EL,
+ /* 197 */ 0x5FAE_6AA3_3C77_785BL, 0x3498_B516_9E28_18D8L,
+ /* 198 */ 0x4C8B_8882_96C5_F9E2L, 0x5D46_F745_4B53_4713L,
+ /* 199 */ 0x7A78_DA6A_8AD6_5C9DL, 0x7BA4_BED5_4552_0B52L,
+ /* 200 */ 0x61FA_4855_3BDE_B07EL, 0x2FB6_FF11_0441_A2A8L,
+ /* 201 */ 0x4E61_D377_6318_8D31L, 0x72F8_CC0D_9D01_4EEDL,
+ /* 202 */ 0x7D69_5258_9E8D_AEB6L, 0x1E5A_E015_C802_17E1L,
+ /* 203 */ 0x6454_41E0_7ED7_BEF8L, 0x1848_B344_A001_ACB4L,
+ /* 204 */ 0x5043_67E6_CBDF_CBF9L, 0x603A_2903_B334_8A2AL,
+ /* 205 */ 0x4035_ECB8_A319_6FFBL, 0x002E_8736_28F6_D4EEL,
+ /* 206 */ 0x66BC_ADF4_3828_B32BL, 0x19E4_0B89_DB24_87E3L,
+ /* 207 */ 0x5230_8B29_C686_F5BCL, 0x14B6_6FA1_7C1D_3983L,
+ /* 208 */ 0x41C0_6F54_9ED2_5E30L, 0x1091_F2E7_967D_C79CL,
+ /* 209 */ 0x6933_E554_3150_96B3L, 0x341C_B7D8_F0C9_3F5FL,
+ /* 210 */ 0x5429_8443_5AA6_DEF5L, 0x767D_5FE0_C0A0_FF80L,
+ /* 211 */ 0x4354_69CF_7BB8_B25EL, 0x2B97_7FE7_0080_CC66L,
+ /* 212 */ 0x6BBA_42E5_92C1_1D63L, 0x5F58_CCA4_CD9A_E0A3L,
+ /* 213 */ 0x562E_9BEA_DBCD_B11CL, 0x4C47_0A1D_7148_B3B6L,
+ /* 214 */ 0x44F2_1655_7CA4_8DB0L, 0x3D05_A1B1_276D_5C92L,
+ /* 215 */ 0x6E50_23BB_FAA0_E2B3L, 0x7B3C_35E8_3F15_60E9L,
+ /* 216 */ 0x5840_1C96_621A_4EF6L, 0x2F63_5E53_65AA_B3EDL,
+ /* 217 */ 0x4699_B078_4E7B_725EL, 0x591C_4B75_EAEE_F658L,
+ /* 218 */ 0x70F5_E726_E3F8_B6FDL, 0x74FA_1256_44B1_8A26L,
+ /* 219 */ 0x5A5E_5285_832D_5F31L, 0x43FB_41DE_9D5A_D4EBL,
+ /* 220 */ 0x484B_7537_9C24_4C27L, 0x4FFC_34B2_177B_DD89L,
+ /* 221 */ 0x73AB_EEBF_603A_1372L, 0x4CC6_BAB6_8BF9_6274L,
+ /* 222 */ 0x5C89_8BCC_4CFB_42C2L, 0x0A38_955E_D661_1B90L,
+ /* 223 */ 0x4A07_A309_D72F_689BL, 0x21C6_DDE5_784D_AFA7L,
+ /* 224 */ 0x7672_9E76_2518_A75EL, 0x693E_2FD5_8D49_190BL,
+ /* 225 */ 0x5EC2_185E_8413_B918L, 0x5431_BFDE_0AA0_E0D5L,
+ /* 226 */ 0x4BCE_79E5_3676_2DADL, 0x29C1_664B_3BB3_E711L,
+ /* 227 */ 0x794A_5CA1_F0BD_15E2L, 0x0F9B_D6DE_C5EC_A4E8L,
+ /* 228 */ 0x6108_4A1B_26FD_AB1BL, 0x2616_457F_04BD_50BAL,
+ /* 229 */ 0x4DA0_3B48_EBFE_227CL, 0x1E78_3798_D097_73C8L,
+ /* 230 */ 0x7C33_920E_4663_6A60L, 0x30C0_58F4_80F2_52D9L,
+ /* 231 */ 0x635C_74D8_384F_884DL, 0x0D66_AD90_6728_4247L,
+ /* 232 */ 0x4F7D_2A46_9372_D370L, 0x711E_F140_5286_9B6CL,
+ /* 233 */ 0x7F2E_AA0A_8584_8581L, 0x34FE_4ECD_50D7_5F14L,
+ /* 234 */ 0x65BE_EE6E_D136_D134L, 0x2A65_0BD7_73DF_7F43L,
+ /* 235 */ 0x5165_8B8B_DA92_40F6L, 0x551D_A312_C319_329CL,
+ /* 236 */ 0x411E_093C_AEDB_672BL, 0x5DB1_4F42_35AD_C217L,
+ /* 237 */ 0x6830_0EC7_7E2B_D845L, 0x7C4E_E536_BC49_368AL,
+ /* 238 */ 0x5359_A56C_64EF_E037L, 0x7D0B_EA92_303A_9208L,
+ /* 239 */ 0x42AE_1DF0_50BF_E693L, 0x173C_BBA8_2695_41A0L,
+ /* 240 */ 0x6AB0_2FE6_E799_70EBL, 0x3EC7_92A6_A422_029AL,
+ /* 241 */ 0x5559_BFEB_EC7A_C0BCL, 0x3239_421E_E9B4_CEE1L,
+ /* 242 */ 0x4447_CCBC_BD2F_0096L, 0x5B61_01B2_5490_A581L,
+ /* 243 */ 0x6D3F_ADFA_C84B_3424L, 0x2BCE_691D_541A_A268L,
+ /* 244 */ 0x5766_24C8_A03C_29B6L, 0x563E_BA7D_DCE2_1B87L,
+ /* 245 */ 0x45EB_50A0_8030_215EL, 0x7832_2ECB_171B_4939L,
+ /* 246 */ 0x6FDE_E767_3380_3564L, 0x59E9_E478_24F8_7527L,
+ /* 247 */ 0x597F_1F85_C2CC_F783L, 0x6187_E9F9_B72D_2A86L,
+ /* 248 */ 0x4798_E604_9BD7_2C69L, 0x346C_BB2E_2C24_2205L,
+ /* 249 */ 0x728E_3CD4_2C8B_7A42L, 0x20AD_F849_E039_D007L,
+ /* 250 */ 0x5BA4_FD76_8A09_2E9BL, 0x33BE_603B_19C7_D99FL,
+ /* 251 */ 0x4950_CAC5_3B3A_8BAFL, 0x42FE_B362_7B06_47B3L,
+ /* 252 */ 0x754E_113B_91F7_45E5L, 0x5197_856A_5E70_72B8L,
+ /* 253 */ 0x5DD8_0DC9_4192_9E51L, 0x27AC_6ABB_7EC0_5BC6L,
+ /* 254 */ 0x4B13_3E3A_9ADB_B1DAL, 0x52F0_5562_CBCD_1638L,
+ /* 255 */ 0x781E_C9F7_5E2C_4FC4L, 0x1E4D_556A_DFAE_89F3L,
+ /* 256 */ 0x6018_A192_B1BD_0C9CL, 0x7EA4_4455_7FBE_D4C3L,
+ /* 257 */ 0x4CE0_8142_27CA_707DL, 0x4BB6_9D11_32FF_109CL,
+ /* 258 */ 0x7B00_CED0_3FAA_4D95L, 0x5F8A_94E8_5198_1A93L,
+ /* 259 */ 0x6267_0BD9_CC88_3E11L, 0x32D5_43ED_0E13_4875L,
+ /* 260 */ 0x4EB8_D647_D6D3_64DAL, 0x5BDD_CFF0_D80F_6D2BL,
+ /* 261 */ 0x7DF4_8A0C_8AEB_D491L, 0x12FC_7FE7_C018_AEABL,
+ /* 262 */ 0x64C3_A1A3_A256_43A7L, 0x28C9_FFEC_99AD_5889L,
+ /* 263 */ 0x509C_814F_B511_CFB9L, 0x0707_FFF0_7AF1_13A1L,
+ /* 264 */ 0x407D_343F_C40E_3FC7L, 0x1F39_998D_2F27_42E7L,
+ /* 265 */ 0x672E_B9FF_A016_CC71L, 0x7EC2_8F48_4B72_04A4L,
+ /* 266 */ 0x528B_C7FF_B345_705BL, 0x189B_A5D3_6F8E_6A1DL,
+ /* 267 */ 0x4209_6CCC_8F6A_C048L, 0x7A16_1E42_BFA5_21B1L,
+ /* 268 */ 0x69A8_AE14_18AA_CD41L, 0x4356_96D1_32A1_CF81L,
+ /* 269 */ 0x5486_F1A9_AD55_7101L, 0x1C45_4574_2881_72CEL,
+ /* 270 */ 0x439F_27BA_F111_2734L, 0x169D_D129_BA01_28A5L,
+ /* 271 */ 0x6C31_D92B_1B4E_A520L, 0x242F_B50F_9001_DAA1L,
+ /* 272 */ 0x568E_4755_AF72_1DB3L, 0x368C_90D9_4001_7BB4L,
+ /* 273 */ 0x453E_9F77_BF8E_7E29L, 0x120A_0D7A_999A_C95DL,
+ /* 274 */ 0x6ECA_98BF_98E3_FD0EL, 0x5010_1590_F5C4_7561L,
+ /* 275 */ 0x58A2_13CC_7A4F_FDA5L, 0x2673_4473_F7D0_5DE8L,
+ /* 276 */ 0x46E8_0FD6_C83F_FE1DL, 0x6B8F_69F6_5FD9_E4B9L,
+ /* 277 */ 0x7173_4C8A_D9FF_FCFCL, 0x45B2_4323_CC8F_D45CL,
+ /* 278 */ 0x5AC2_A3A2_47FF_FD96L, 0x6AF5_0283_0A0C_A9E3L,
+ /* 279 */ 0x489B_B61B_6CCC_CADFL, 0x08C4_0202_6E70_87E9L,
+ /* 280 */ 0x742C_5692_47AE_1164L, 0x746C_D003_E3E7_3FDBL,
+ /* 281 */ 0x5CF0_4541_D2F1_A783L, 0x76BD_7336_4FEC_3315L,
+ /* 282 */ 0x4A59_D101_758E_1F9CL, 0x5EFD_F5C5_0CBC_F5ABL,
+ /* 283 */ 0x76F6_1B35_88E3_65C7L, 0x4B2F_EFA1_ADFB_22ABL,
+ /* 284 */ 0x5F2B_48F7_A0B5_EB06L, 0x08F3_261A_F195_B555L,
+ /* 285 */ 0x4C22_A0C6_1A2B_226BL, 0x20C2_84E2_5ADE_2AABL,
+ /* 286 */ 0x79D1_013C_F6AB_6A45L, 0x1AD0_D49D_5E30_4444L,
+ /* 287 */ 0x6174_00FD_9222_BB6AL, 0x48A7_107D_E4F3_69D0L,
+ /* 288 */ 0x4DF6_6731_41B5_62BBL, 0x53B8_D9FE_50C2_BB0DL,
+ /* 289 */ 0x7CBD_71E8_6922_3792L, 0x52C1_5CCA_1AD1_2B48L,
+ /* 290 */ 0x63CA_C186_BA81_C60EL, 0x7567_7D6E_7BDA_8906L,
+ /* 291 */ 0x4FD5_679E_FB9B_04D8L, 0x5DEC_6458_6315_3A6CL,
+ /* 292 */ 0x7FBB_D8FE_5F5E_6E27L, 0x497A_3A27_04EE_C3DFL,
+ };
+
+}
diff --git
a/test/jdk/java/lang/String/concat/ImplicitStringConcatBoundaries.java
b/test/jdk/java/lang/String/concat/ImplicitStringConcatBoundaries.java
--- a/test/jdk/java/lang/String/concat/ImplicitStringConcatBoundaries.java
+++ b/test/jdk/java/lang/String/concat/ImplicitStringConcatBoundaries.java
@@ -169,8 +169,8 @@
test("foo-2147483648", "foo" + INT_MIN_1);
test("foo-2147483648", "foo" + INT_MIN_2);
- test("foo1.17549435E-38", "foo" + FLOAT_MIN_NORM_1);
- test("foo1.17549435E-38", "foo" + FLOAT_MIN_NORM_2);
+ test("foo1.1754944E-38", "foo" + FLOAT_MIN_NORM_1);
+ test("foo1.1754944E-38", "foo" + FLOAT_MIN_NORM_2);
test("foo-126.0", "foo" + FLOAT_MIN_EXP_1);
test("foo-126.0", "foo" + FLOAT_MIN_EXP_2);
test("foo1.4E-45", "foo" + FLOAT_MIN_1);
diff --git
a/test/jdk/jdk/internal/math/ToDecimal/DoubleToDecimalTest.java
b/test/jdk/jdk/internal/math/ToDecimal/DoubleToDecimalTest.java
new file mode 100644
--- /dev/null
+++ b/test/jdk/jdk/internal/math/ToDecimal/DoubleToDecimalTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2019 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import jdk.internal.math.DoubleToDecimalChecker;
+import jdk.test.lib.RandomFactory;
+
+/*
+ * @test
+ * @bug 8202555
+ * @author Raffaello Giulietti
+ * @key randomness
+ *
+ * @modules java.base/jdk.internal.math
+ * @library /test/lib
+ * @library java.base
+ * @build jdk.test.lib.RandomFactory
+ * @build java.base/jdk.internal.math.*
+ * @run main DoubleToDecimalTest 1_000_000
+ */
+public class DoubleToDecimalTest {
+
+ private static final int RANDOM_COUNT = 100_000;
+
+ public static void main(String[] args) {
+ int count = RANDOM_COUNT;
+ if (args.length == 0) {
+ DoubleToDecimalChecker.test(count, RandomFactory.getRandom());
+ return;
+ }
+ try {
+ count = Integer.parseInt(args[0].replace("_", ""));
+ } catch (NumberFormatException ignored) {
+ }
+ DoubleToDecimalChecker.test(count, RandomFactory.getRandom());
+ }
+
+}
diff --git
a/test/jdk/jdk/internal/math/ToDecimal/FloatToDecimalTest.java
b/test/jdk/jdk/internal/math/ToDecimal/FloatToDecimalTest.java
new file mode 100644
--- /dev/null
+++ b/test/jdk/jdk/internal/math/ToDecimal/FloatToDecimalTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import jdk.internal.math.FloatToDecimalChecker;
+import jdk.test.lib.RandomFactory;
+
+/*
+ * @test
+ * @author Raffaello Giulietti
+ * @key randomness
+ *
+ * @modules java.base/jdk.internal.math
+ * @library /test/lib
+ * @library java.base
+ * @build jdk.test.lib.RandomFactory
+ * @build java.base/jdk.internal.math.*
+ * @run main FloatToDecimalTest 1_000_000
+ */
+public class FloatToDecimalTest {
+
+ private static final int RANDOM_COUNT = 100_000;
+
+ public static void main(String[] args) {
+ int count = RANDOM_COUNT;
+ if (args.length == 0) {
+ FloatToDecimalChecker.test(count, RandomFactory.getRandom());
+ return;
+ }
+ if (args[0].equals("all")) {
+ FloatToDecimalChecker.testAll();
+ return;
+ }
+ if (args[0].equals("positive")) {
+ FloatToDecimalChecker.testPositive();
+ return;
+ }
+ try {
+ count = Integer.parseInt(args[0].replace("_", ""));
+ } catch (NumberFormatException ignored) {
+ }
+ FloatToDecimalChecker.test(count, RandomFactory.getRandom());
+ }
+
+}
diff --git a/test/jdk/jdk/internal/math/ToDecimal/MathUtilsTest.java
b/test/jdk/jdk/internal/math/ToDecimal/MathUtilsTest.java
new file mode 100644
--- /dev/null
+++ b/test/jdk/jdk/internal/math/ToDecimal/MathUtilsTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import jdk.internal.math.MathUtilsChecker;
+
+/*
+ * @test
+ * @author Raffaello Giulietti
+ *
+ * @modules java.base/jdk.internal.math
+ * @library java.base
+ * @build java.base/jdk.internal.math.*
+ * @run main MathUtilsTest
+ */
+public class MathUtilsTest {
+
+ public static void main(String[] args) {
+ MathUtilsChecker.test();
+ }
+
+}
diff --git
a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/BasicChecker.java
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/BasicChecker.java
new file mode 100644
--- /dev/null
+++
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/BasicChecker.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+class BasicChecker {
+
+ static final boolean FAILURE_THROWS_EXCEPTION = true;
+
+ static void assertTrue(boolean ok, String valueName) {
+ if (ok) {
+ return;
+ }
+ String msg = valueName + " is not correct";
+ if (FAILURE_THROWS_EXCEPTION) {
+ throw new RuntimeException(msg);
+ }
+ System.err.println(msg);
+ }
+
+}
diff --git
a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/DoubleToDecimalChecker.java
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/DoubleToDecimalChecker.java
new file mode 100644
--- /dev/null
+++
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/DoubleToDecimalChecker.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+import java.math.BigDecimal;
+import java.util.Random;
+
+import static java.lang.Double.*;
+import static java.lang.Long.numberOfTrailingZeros;
+import static java.lang.StrictMath.scalb;
+import static jdk.internal.math.MathUtils.flog10pow2;
+
+public class DoubleToDecimalChecker extends ToDecimalChecker {
+
+ private static final int P =
+ numberOfTrailingZeros(doubleToRawLongBits(3)) + 2;
+ private static final int W = (SIZE - 1) - (P - 1);
+ private static final int Q_MIN = (-1 << W - 1) - P + 3;
+ private static final int Q_MAX = (1 << W - 1) - P;
+ private static final long C_MIN = 1L << P - 1;
+ private static final long C_MAX = (1L << P) - 1;
+
+ private static final int K_MIN = flog10pow2(Q_MIN);
+ private static final int K_MAX = flog10pow2(Q_MAX);
+ private static final int H = flog10pow2(P) + 2;
+
+ private static final double MIN_VALUE = scalb(1.0, Q_MIN);
+ private static final double MIN_NORMAL = scalb((double) C_MIN, Q_MIN);
+ private static final double MAX_VALUE = scalb((double) C_MAX, Q_MAX);
+
+ private static final int E_MIN = e(MIN_VALUE);
+ private static final int E_MAX = e(MAX_VALUE);
+
+ private static final long C_TINY = cTiny(Q_MIN, K_MIN);
+
+ private double v;
+ private final long originalBits;
+
+ private DoubleToDecimalChecker(double v, String s) {
+ super(s);
+ this.v = v;
+ originalBits = doubleToRawLongBits(v);
+ }
+
+ @Override
+ BigDecimal toBigDecimal() {
+ return new BigDecimal(v);
+ }
+
+ @Override
+ boolean recovers(BigDecimal b) {
+ return b.doubleValue() == v;
+ }
+
+ @Override
+ boolean recovers(String s) {
+ return parseDouble(s) == v;
+ }
+
+ @Override
+ String hexBits() {
+ return String.format("0x%01X__%03X__%01X_%04X_%04X_%04X",
+ (int) (originalBits >>> 63) & 0x1,
+ (int) (originalBits >>> 52) & 0x7FF,
+ (int) (originalBits >>> 48) & 0xF,
+ (int) (originalBits >>> 32) & 0xFFFF,
+ (int) (originalBits >>> 16) & 0xFFFF,
+ (int) originalBits & 0xFFFF);
+ }
+
+ @Override
+ int minExp() {
+ return E_MIN;
+ }
+
+ @Override
+ int maxExp() {
+ return E_MAX;
+ }
+
+ @Override
+ int maxLen10() {
+ return H;
+ }
+
+ @Override
+ boolean isZero() {
+ return v == 0;
+ }
+
+ @Override
+ boolean isInfinity() {
+ return v == POSITIVE_INFINITY;
+ }
+
+ @Override
+ void negate() {
+ v = -v;
+ }
+
+ @Override
+ boolean isNegative() {
+ return originalBits < 0;
+ }
+
+ @Override
+ boolean isNaN() {
+ return Double.isNaN(v);
+ }
+
+ private static void toDec(double v) {
+// String s = Double.toString(v);
+ String s = DoubleToDecimal.toString(v);
+ new DoubleToDecimalChecker(v, s).assertTrue();
+ }
+
+ private static void testExtremeValues() {
+ toDec(NEGATIVE_INFINITY);
+ toDec(-MAX_VALUE);
+ toDec(-MIN_NORMAL);
+ toDec(-MIN_VALUE);
+ toDec(-0.0);
+ toDec(0.0);
+ toDec(MIN_VALUE);
+ toDec(MIN_NORMAL);
+ toDec(MAX_VALUE);
+ toDec(POSITIVE_INFINITY);
+ toDec(NaN);
+
+ /*
+ Quiet NaNs have the most significant bit of the mantissa as 1,
+ while signaling NaNs have it as 0.
+ Exercise 4 combinations of quiet/signaling NaNs and
+ "positive/negative" NaNs
+ */
+ toDec(longBitsToDouble(0x7FF8_0000_0000_0001L));
+ toDec(longBitsToDouble(0x7FF0_0000_0000_0001L));
+ toDec(longBitsToDouble(0xFFF8_0000_0000_0001L));
+ toDec(longBitsToDouble(0xFFF0_0000_0000_0001L));
+
+ /*
+ All values treated specially by Schubfach
+ */
+ for (int c = 1; c < C_TINY; ++c) {
+ toDec(c * MIN_VALUE);
+ }
+ }
+
+ /*
+ A few "powers of 10" are incorrectly rendered by the JDK.
+ The rendering is either too long or it is not the closest decimal.
+ */
+ private static void testPowersOf10() {
+ for (int e = E_MIN; e <= E_MAX; ++e) {
+ toDec(parseDouble("1e" + e));
+ }
+ }
+
+ /*
+ Many powers of 2 are incorrectly rendered by the JDK.
+ The rendering is either too long or it is not the closest decimal.
+ */
+ private static void testPowersOf2() {
+ for (double v = MIN_VALUE; v <= MAX_VALUE; v *= 2) {
+ toDec(v);
+ }
+ }
+
+ /*
+ There are tons of doubles that are rendered incorrectly by the JDK.
+ While the renderings correctly round back to the original value,
+ they are longer than needed or are not the closest decimal to the
double.
+ Here are just a very few examples.
+ */
+ private static final String[] Anomalies = {
+ // JDK renders these, and others, with 18 digits!
+ "2.82879384806159E17", "1.387364135037754E18",
+ "1.45800632428665E17",
+
+ // JDK renders these longer than needed.
+ "1.6E-322", "6.3E-322",
+ "7.3879E20", "2.0E23", "7.0E22", "9.2E22",
+ "9.5E21", "3.1E22", "5.63E21", "8.41E21",
+
+ // JDK does not render these, and many others, as the closest.
+ "9.9E-324", "9.9E-323",
+ "1.9400994884341945E25", "3.6131332396758635E25",
+ "2.5138990223946153E25",
+ };
+
+ private static void testSomeAnomalies() {
+ for (String dec : Anomalies) {
+ toDec(parseDouble(dec));
+ }
+ }
+
+ /*
+ Values are from
+ Paxson V, "A Program for Testing IEEE Decimal-Binary Conversion"
+ tables 3 and 4
+ */
+ private static final double[] PaxsonSignificands = {
+ 8_511_030_020_275_656L,
+ 5_201_988_407_066_741L,
+ 6_406_892_948_269_899L,
+ 8_431_154_198_732_492L,
+ 6_475_049_196_144_587L,
+ 8_274_307_542_972_842L,
+ 5_381_065_484_265_332L,
+ 6_761_728_585_499_734L,
+ 7_976_538_478_610_756L,
+ 5_982_403_858_958_067L,
+ 5_536_995_190_630_837L,
+ 7_225_450_889_282_194L,
+ 7_225_450_889_282_194L,
+ 8_703_372_741_147_379L,
+ 8_944_262_675_275_217L,
+ 7_459_803_696_087_692L,
+ 6_080_469_016_670_379L,
+ 8_385_515_147_034_757L,
+ 7_514_216_811_389_786L,
+ 8_397_297_803_260_511L,
+ 6_733_459_239_310_543L,
+ 8_091_450_587_292_794L,
+
+ 6_567_258_882_077_402L,
+ 6_712_731_423_444_934L,
+ 6_712_731_423_444_934L,
+ 5_298_405_411_573_037L,
+ 5_137_311_167_659_507L,
+ 6_722_280_709_661_868L,
+ 5_344_436_398_034_927L,
+ 8_369_123_604_277_281L,
+ 8_995_822_108_487_663L,
+ 8_942_832_835_564_782L,
+ 8_942_832_835_564_782L,
+ 8_942_832_835_564_782L,
+ 6_965_949_469_487_146L,
+ 6_965_949_469_487_146L,
+ 6_965_949_469_487_146L,
+ 7_487_252_720_986_826L,
+ 5_592_117_679_628_511L,
+ 8_887_055_249_355_788L,
+ 6_994_187_472_632_449L,
+ 8_797_576_579_012_143L,
+ 7_363_326_733_505_337L,
+ 8_549_497_411_294_502L,
+ };
+
+ private static final int[] PaxsonExponents = {
+ -342,
+ -824,
+ 237,
+ 72,
+ 99,
+ 726,
+ -456,
+ -57,
+ 376,
+ 377,
+ 93,
+ 710,
+ 709,
+ 117,
+ -1,
+ -707,
+ -381,
+ 721,
+ -828,
+ -345,
+ 202,
+ -473,
+
+ 952,
+ 535,
+ 534,
+ -957,
+ -144,
+ 363,
+ -169,
+ -853,
+ -780,
+ -383,
+ -384,
+ -385,
+ -249,
+ -250,
+ -251,
+ 548,
+ 164,
+ 665,
+ 690,
+ 588,
+ 272,
+ -448,
+ };
+
+ private static void testPaxson() {
+ for (int i = 0; i < PaxsonSignificands.length; ++i) {
+ toDec(scalb(PaxsonSignificands[i], PaxsonExponents[i]));
+ }
+ }
+
+ /*
+ Tests all integers of the form yx_xxx_000_000_000_000_000, y != 0.
+ These are all exact doubles.
+ */
+ private static void testLongs() {
+ for (int i = 10_000; i < 100_000; ++i) {
+ toDec(i * 1e15);
+ }
+ }
+
+ /*
+ Tests all integers up to 1_000_000.
+ These are all exact doubles and exercise a fast path.
+ */
+ private static void testInts() {
+ for (int i = 0; i <= 1_000_000; ++i) {
+ toDec(i);
+ }
+ }
+
+ /*
+ Random doubles over the whole range
+ */
+ private static void testRandom(int randomCount, Random r) {
+ for (int i = 0; i < randomCount; ++i) {
+ toDec(longBitsToDouble(r.nextLong()));
+ }
+ }
+
+ /*
+ Random doubles over the integer range [0, 2^52).
+ These are all exact doubles and exercise the fast path (except 0).
+ */
+ private static void testRandomUnit(int randomCount, Random r) {
+ for (int i = 0; i < randomCount; ++i) {
+ toDec(r.nextLong() & (1L << P - 1));
+ }
+ }
+
+ /*
+ Random doubles over the range [0, 10^15) as "multiples" of 1e-3
+ */
+ private static void testRandomMilli(int randomCount, Random r) {
+ for (int i = 0; i < randomCount; ++i) {
+ toDec(r.nextLong() % 1_000_000_000_000_000_000L / 1e3);
+ }
+ }
+
+ /*
+ Random doubles over the range [0, 10^15) as "multiples" of 1e-6
+ */
+ private static void testRandomMicro(int randomCount, Random r) {
+ for (int i = 0; i < randomCount; ++i) {
+ toDec((r.nextLong() & 0x7FFF_FFFF_FFFF_FFFFL) / 1e6);
+ }
+ }
+
+ private static void testConstants() {
+ assertTrue(P == DoubleToDecimal.P, "P");
+ assertTrue((long) (double) C_MIN == C_MIN, "C_MIN");
+ assertTrue((long) (double) C_MAX == C_MAX, "C_MAX");
+ assertTrue(MIN_VALUE == Double.MIN_VALUE, "MIN_VALUE");
+ assertTrue(MIN_NORMAL == Double.MIN_NORMAL, "MIN_NORMAL");
+ assertTrue(MAX_VALUE == Double.MAX_VALUE, "MAX_VALUE");
+
+ assertTrue(Q_MIN == DoubleToDecimal.Q_MIN, "Q_MIN");
+ assertTrue(Q_MAX == DoubleToDecimal.Q_MAX, "Q_MAX");
+
+ assertTrue(K_MIN == DoubleToDecimal.K_MIN, "K_MIN");
+ assertTrue(K_MAX == DoubleToDecimal.K_MAX, "K_MAX");
+ assertTrue(H == DoubleToDecimal.H, "H");
+
+ assertTrue(E_MIN == DoubleToDecimal.E_MIN, "E_MIN");
+ assertTrue(E_MAX == DoubleToDecimal.E_MAX, "E_MAX");
+ assertTrue(C_TINY == DoubleToDecimal.C_TINY, "C_TINY");
+ }
+
+ public static void test(int randomCount, Random r) {
+ testConstants();
+ testExtremeValues();
+ testSomeAnomalies();
+ testPowersOf2();
+ testPowersOf10();
+ testPaxson();
+ testInts();
+ testLongs();
+ testRandom(randomCount, r);
+ testRandomUnit(randomCount, r);
+ testRandomMilli(randomCount, r);
+ testRandomMicro(randomCount, r);
+ }
+
+ public static void main(String[] args) {
+ test(1_000_000, new Random());
+ }
+}
diff --git
a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/FloatToDecimalChecker.java
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/FloatToDecimalChecker.java
new file mode 100644
--- /dev/null
+++
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/FloatToDecimalChecker.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+import java.math.BigDecimal;
+import java.util.Random;
+
+import static java.lang.Float.*;
+import static java.lang.Integer.numberOfTrailingZeros;
+import static java.lang.StrictMath.scalb;
+import static jdk.internal.math.MathUtils.flog10pow2;
+
+public class FloatToDecimalChecker extends ToDecimalChecker {
+
+ private static final int P =
+ numberOfTrailingZeros(floatToRawIntBits(3)) + 2;
+ private static final int W = (SIZE - 1) - (P - 1);
+ private static final int Q_MIN = (-1 << W - 1) - P + 3;
+ private static final int Q_MAX = (1 << W - 1) - P;
+ private static final int C_MIN = 1 << P - 1;
+ private static final int C_MAX = (1 << P) - 1;
+
+ private static final int K_MIN = flog10pow2(Q_MIN);
+ private static final int K_MAX = flog10pow2(Q_MAX);
+ private static final int H = flog10pow2(P) + 2;
+
+ private static final float MIN_VALUE = scalb(1.0f, Q_MIN);
+ private static final float MIN_NORMAL = scalb((float) C_MIN, Q_MIN);
+ private static final float MAX_VALUE = scalb((float) C_MAX, Q_MAX);
+
+ private static final int E_MIN = e(MIN_VALUE);
+ private static final int E_MAX = e(MAX_VALUE);
+
+ private static final long C_TINY = cTiny(Q_MIN, K_MIN);
+
+ private float v;
+ private final int originalBits;
+
+ private FloatToDecimalChecker(float v, String s) {
+ super(s);
+ this.v = v;
+ originalBits = floatToRawIntBits(v);
+ }
+
+ @Override
+ BigDecimal toBigDecimal() {
+ return new BigDecimal(v);
+ }
+
+ @Override
+ boolean recovers(BigDecimal b) {
+ return b.floatValue() == v;
+ }
+
+ @Override
+ String hexBits() {
+ return String.format("0x%01X__%02X__%02X_%04X",
+ (originalBits >>> 31) & 0x1,
+ (originalBits >>> 23) & 0xFF,
+ (originalBits >>> 16) & 0x7F,
+ originalBits & 0xFFFF);
+ }
+
+ @Override
+ boolean recovers(String s) {
+ return parseFloat(s) == v;
+ }
+
+ @Override
+ int minExp() {
+ return E_MIN;
+ }
+
+ @Override
+ int maxExp() {
+ return E_MAX;
+ }
+
+ @Override
+ int maxLen10() {
+ return H;
+ }
+
+ @Override
+ boolean isZero() {
+ return v == 0;
+ }
+
+ @Override
+ boolean isInfinity() {
+ return v == POSITIVE_INFINITY;
+ }
+
+ @Override
+ void negate() {
+ v = -v;
+ }
+
+ @Override
+ boolean isNegative() {
+ return originalBits < 0;
+ }
+
+ @Override
+ boolean isNaN() {
+ return Float.isNaN(v);
+ }
+
+ private static void toDec(float v) {
+// String s = Float.toString(v);
+ String s = FloatToDecimal.toString(v);
+ new FloatToDecimalChecker(v, s).assertTrue();
+ }
+
+ /*
+ MIN_NORMAL is incorrectly rendered by the JDK.
+ */
+ private static void testExtremeValues() {
+ toDec(NEGATIVE_INFINITY);
+ toDec(-MAX_VALUE);
+ toDec(-MIN_NORMAL);
+ toDec(-MIN_VALUE);
+ toDec(-0.0f);
+ toDec(0.0f);
+ toDec(MIN_VALUE);
+ toDec(MIN_NORMAL);
+ toDec(MAX_VALUE);
+ toDec(POSITIVE_INFINITY);
+ toDec(NaN);
+
+ /*
+ Quiet NaNs have the most significant bit of the mantissa as 1,
+ while signaling NaNs have it as 0.
+ Exercise 4 combinations of quiet/signaling NaNs and
+ "positive/negative" NaNs.
+ */
+ toDec(intBitsToFloat(0x7FC0_0001));
+ toDec(intBitsToFloat(0x7F80_0001));
+ toDec(intBitsToFloat(0xFFC0_0001));
+ toDec(intBitsToFloat(0xFF80_0001));
+
+ /*
+ All values treated specially by Schubfach
+ */
+ for (int c = 1; c < C_TINY; ++c) {
+ toDec(c * MIN_VALUE);
+ }
+ }
+
+ /*
+ Some "powers of 10" are incorrectly rendered by the JDK.
+ The rendering is either too long or it is not the closest decimal.
+ */
+ private static void testPowersOf10() {
+ for (int e = E_MIN; e <= E_MAX; ++e) {
+ toDec(parseFloat("1e" + e));
+ }
+ }
+
+ /*
+ Many powers of 2 are incorrectly rendered by the JDK.
+ The rendering is either too long or it is not the closest decimal.
+ */
+ private static void testPowersOf2() {
+ for (float v = MIN_VALUE; v <= MAX_VALUE; v *= 2) {
+ toDec(v);
+ }
+ }
+
+ /*
+ There are tons of doubles that are rendered incorrectly by the JDK.
+ While the renderings correctly round back to the original value,
+ they are longer than needed or are not the closest decimal to the
double.
+ Here are just a very few examples.
+ */
+ private static final String[] Anomalies = {
+ // JDK renders these longer than needed.
+ "1.1754944E-38", "2.2E-44",
+ "1.0E16", "2.0E16", "3.0E16", "5.0E16", "3.0E17",
+ "3.2E18", "3.7E18", "3.7E16", "3.72E17",
+
+ // JDK does not render this as the closest.
+ "9.9E-44",
+ };
+
+ private static void testSomeAnomalies() {
+ for (String dec : Anomalies) {
+ toDec(parseFloat(dec));
+ }
+ }
+
+ /*
+ Values are from
+ Paxson V, "A Program for Testing IEEE Decimal-Binary Conversion"
+ tables 16 and 17
+ */
+ private static final float[] PaxsonSignificands = {
+ 12_676_506,
+ 15_445_013,
+ 13_734_123,
+ 12_428_269,
+ 12_676_506,
+ 15_334_037,
+ 11_518_287,
+ 12_584_953,
+ 15_961_084,
+ 14_915_817,
+ 10_845_484,
+ 16_431_059,
+
+ 16_093_626,
+ 9_983_778,
+ 12_745_034,
+ 12_706_553,
+ 11_005_028,
+ 15_059_547,
+ 16_015_691,
+ 8_667_859,
+ 14_855_922,
+ 14_855_922,
+ 10_144_164,
+ 13_248_074,
+ };
+
+ private static final int[] PaxsonExponents = {
+ -102,
+ -103,
+ 86,
+ -138,
+ -130,
+ -146,
+ -41,
+ -145,
+ -125,
+ -146,
+ -102,
+ -61,
+
+ 69,
+ 25,
+ 104,
+ 72,
+ 45,
+ 71,
+ -99,
+ 56,
+ -82,
+ -83,
+ -110,
+ 95,
+ };
+
+ private static void testPaxson() {
+ for (int i = 0; i < PaxsonSignificands.length; ++i) {
+ toDec(scalb(PaxsonSignificands[i], PaxsonExponents[i]));
+ }
+ }
+
+ /*
+ Tests all positive integers below 2^23.
+ These are all exact floats and exercise the fast path.
+ */
+ private static void testInts() {
+ for (int i = 1; i < 1 << P - 1; ++i) {
+ toDec(i);
+ }
+ }
+
+ /*
+ Random floats over the whole range.
+ */
+ private static void testRandom(int randomCount, Random r) {
+ for (int i = 0; i < randomCount; ++i) {
+ toDec(intBitsToFloat(r.nextInt()));
+ }
+ }
+
+ /*
+ All, really all, 2^32 possible floats. Takes between 90 and 120
minutes.
+ */
+ public static void testAll() {
+ // Avoid wrapping around Integer.MAX_VALUE
+ int bits = Integer.MIN_VALUE;
+ for (; bits < Integer.MAX_VALUE; ++bits) {
+ toDec(intBitsToFloat(bits));
+ }
+ toDec(intBitsToFloat(bits));
+ }
+
+ /*
+ All positive 2^31 floats.
+ */
+ public static void testPositive() {
+ // Avoid wrapping around Integer.MAX_VALUE
+ int bits = 0;
+ for (; bits < Integer.MAX_VALUE; ++bits) {
+ toDec(intBitsToFloat(bits));
+ }
+ toDec(intBitsToFloat(bits));
+ }
+
+ private static void testConstants() {
+ assertTrue(P == FloatToDecimal.P, "P");
+ assertTrue((long) (float) C_MIN == C_MIN, "C_MIN");
+ assertTrue((long) (float) C_MAX == C_MAX, "C_MAX");
+ assertTrue(MIN_VALUE == Float.MIN_VALUE, "MIN_VALUE");
+ assertTrue(MIN_NORMAL == Float.MIN_NORMAL, "MIN_NORMAL");
+ assertTrue(MAX_VALUE == Float.MAX_VALUE, "MAX_VALUE");
+
+ assertTrue(Q_MIN == FloatToDecimal.Q_MIN, "Q_MIN");
+ assertTrue(Q_MAX == FloatToDecimal.Q_MAX, "Q_MAX");
+
+ assertTrue(K_MIN == FloatToDecimal.K_MIN, "K_MIN");
+ assertTrue(K_MAX == FloatToDecimal.K_MAX, "K_MAX");
+ assertTrue(H == FloatToDecimal.H, "H");
+
+ assertTrue(E_MIN == FloatToDecimal.E_MIN, "E_MIN");
+ assertTrue(E_MAX == FloatToDecimal.E_MAX, "E_MAX");
+ assertTrue(C_TINY == FloatToDecimal.C_TINY, "C_TINY");
+ }
+
+ public static void test(int randomCount, Random r) {
+ testConstants();
+ testExtremeValues();
+ testSomeAnomalies();
+ testPowersOf2();
+ testPowersOf10();
+ testPaxson();
+ testInts();
+ testRandom(randomCount, r);
+ }
+
+ public static void main(String[] args) {
+ if (args.length > 0 && args[0].equals("all")) {
+ testAll();
+ return;
+ }
+ if (args.length > 0 && args[0].equals("positive")) {
+ testPositive();
+ return;
+ }
+ test(1_000_000, new Random());
+ }
+
+}
diff --git
a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/MathUtilsChecker.java
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/MathUtilsChecker.java
new file mode 100644
--- /dev/null
+++
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/MathUtilsChecker.java
@@ -0,0 +1,471 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+import java.math.BigInteger;
+
+import static java.lang.Double.*;
+import static java.lang.Long.numberOfTrailingZeros;
+import static java.lang.StrictMath.scalb;
+import static java.math.BigInteger.*;
+import static jdk.internal.math.MathUtils.*;
+
+public class MathUtilsChecker extends BasicChecker {
+
+ private static final BigInteger THREE = valueOf(3);
+
+ // binary constants
+ private static final int P =
+ numberOfTrailingZeros(doubleToRawLongBits(3)) + 2;
+ private static final int W = (SIZE - 1) - (P - 1);
+ private static final int Q_MIN = (-1 << W - 1) - P + 3;
+ private static final int Q_MAX = (1 << W - 1) - P;
+ private static final long C_MIN = 1L << P - 1;
+ private static final long C_MAX = (1L << P) - 1;
+
+ // decimal constants
+ private static final int K_MIN = flog10pow2(Q_MIN);
+ private static final int K_MAX = flog10pow2(Q_MAX);
+ private static final int H = flog10pow2(P) + 2;
+
+ /*
+ Let
+ 10^(-k) = beta 2^r
+ for the unique integer r and real beta meeting
+ 2^125 <= beta < 2^126
+ Further, let g = g1 2^63 + g0.
+ Checks that:
+ 2^62 <= g1 < 2^63,
+ 0 <= g0 < 2^63,
+ g - 1 <= beta < g, (that is, g = floor(beta) + 1)
+ The last predicate, after multiplying by 2^r, is equivalent to
+ (g - 1) 2^r <= 10^(-k) < g 2^r
+ This is the predicate that will be checked in various forms.
+ */
+ private static void testG(int k, long g1, long g0) {
+ // 2^62 <= g1 < 2^63, 0 <= g0 < 2^63
+ assertTrue(g1 << 1 < 0 && g1 >= 0 && g0 >= 0, "g");
+
+ BigInteger g = valueOf(g1).shiftLeft(63).or(valueOf(g0));
+ // double check that 2^125 <= g < 2^126
+ assertTrue(g.signum() > 0 && g.bitLength() == 126, "g");
+
+ // see javadoc of MathUtils.g1(int)
+ int r = flog2pow10(-k) - 125;
+
+ /*
+ The predicate
+ (g - 1) 2^r <= 10^(-k) < g 2^r
+ is equivalent to
+ g - 1 <= 10^(-k) 2^(-r) < g
+ When
+ k <= 0 & r < 0
+ all numerical subexpressions are integer-valued. This is the
same as
+ g - 1 = 10^(-k) 2^(-r)
+ */
+ if (k <= 0 && r < 0) {
+ assertTrue(
+
g.subtract(ONE).compareTo(TEN.pow(-k).shiftLeft(-r)) == 0,
+ "g");
+ return;
+ }
+
+ /*
+ The predicate
+ (g - 1) 2^r <= 10^(-k) < g 2^r
+ is equivalent to
+ g 10^k - 10^k <= 2^(-r) < g 10^k
+ When
+ k > 0 & r < 0
+ all numerical subexpressions are integer-valued.
+ */
+ if (k > 0 && r < 0) {
+ BigInteger pow5 = TEN.pow(k);
+ BigInteger mhs = ONE.shiftLeft(-r);
+ BigInteger rhs = g.multiply(pow5);
+ assertTrue(rhs.subtract(pow5).compareTo(mhs) <= 0
+ && mhs.compareTo(rhs) < 0,
+ "g");
+ return;
+ }
+
+ /*
+ Finally, when
+ k <= 0 & r >= 0
+ the predicate
+ (g - 1) 2^r <= 10^(-k) < g 2^r
+ can be used straightforwardly as all numerical subexpressions are
+ already integer-valued.
+ */
+ if (k <= 0) {
+ BigInteger mhs = TEN.pow(-k);
+ assertTrue(g.subtract(ONE).shiftLeft(r).compareTo(mhs) <= 0 &&
+ mhs.compareTo(g.shiftLeft(r)) < 0,
+ "g");
+ return;
+ }
+
+ /*
+ For combinatorial reasons, the only remaining case is
+ k > 0 & r >= 0
+ which, however, cannot arise. Indeed, the predicate
+ (g - 1) 2^r <= 10^(-k) < g 2^r
+ has a positive integer left-hand side and a middle side < 1,
+ which cannot hold.
+ */
+ assertTrue(false, "g");
+ }
+
+ /*
+ Verifies the soundness of the values returned by g1() and g0().
+ */
+ private static void testG() {
+ for (int k = MathUtils.K_MIN; k <= MathUtils.K_MAX; ++k) {
+ testG(k, g1(k), g0(k));
+ }
+ }
+
+ /*
+ Let
+ k = floor(log10(3/4 2^e))
+ The method verifies that
+ k = flog10threeQuartersPow2(e), Q_MIN <= e <= Q_MAX
+ This range covers all binary exponents of doubles and floats.
+
+ The first equation above is equivalent to
+ 10^k <= 3 2^(e-2) < 10^(k+1)
+ Equality never holds. Henceforth, the predicate to check is
+ 10^k < 3 2^(e-2) < 10^(k+1)
+ This will be transformed in various ways for checking purposes.
+
+ For integer n > 0, let further
+ b = len2(n)
+ denote its length in bits. This means exactly the same as
+ 2^(b-1) <= n < 2^b
+ */
+ private static void testFlog10threeQuartersPow2() {
+ // First check the case e = 1
+ assertTrue(flog10threeQuartersPow2(1) == 0,
+ "flog10threeQuartersPow2");
+
+ /*
+ Now check the range Q_MIN <= e <= 0.
+ By rewriting, the predicate to check is equivalent to
+ 3 10^(-k-1) < 2^(2-e) < 3 10^(-k)
+ As e <= 0, it follows that 2^(2-e) >= 4 and the right inequality
+ implies k < 0, so the powers of 10 are integers.
+
+ The left inequality is equivalent to
+ len2(3 10^(-k-1)) <= 2 - e
+ and the right inequality to
+ 2 - e < len2(3 10^(-k))
+ The original predicate is therefore equivalent to
+ len2(3 10^(-k-1)) <= 2 - e < len2(3 10^(-k))
+
+ Starting with e = 0 and decrementing until the lower bound, the
code
+ keeps track of the two powers of 10 to avoid recomputing them.
+ This is easy because at each iteration k changes at most by 1.
A simple
+ multiplication by 10 computes the next power of 10 when needed.
+ */
+ int e = 0;
+ int k0 = flog10threeQuartersPow2(e);
+ assertTrue(k0 < 0, "flog10threeQuartersPow2");
+ BigInteger l = THREE.multiply(TEN.pow(-k0 - 1));
+ BigInteger u = l.multiply(TEN);
+ for (;;) {
+ assertTrue(l.bitLength() <= 2 - e & 2 - e < u.bitLength(),
+ "flog10threeQuartersPow2");
+ --e;
+ if (e < Q_MIN) {
+ break;
+ }
+ int kp = flog10threeQuartersPow2(e);
+ assertTrue(kp <= k0, "flog10threeQuartersPow2");
+ if (kp < k0) {
+ // k changes at most by 1 at each iteration, hence:
+ assertTrue(k0 - kp == 1, "flog10threeQuartersPow2");
+ k0 = kp;
+ l = u;
+ u = u.multiply(TEN);
+ }
+ }
+
+ /*
+ Finally, check the range 2 <= e <= Q_MAX.
+ In predicate
+ 10^k < 3 2^(e-2) < 10^(k+1)
+ the right inequality shows that k >= 0 as soon as e >= 2.
+ It is equivalent to
+ 10^k / 3 < 2^(e-2) < 10^(k+1) / 3
+ Both the powers of 10 and the powers of 2 are integers.
+ The left inequality is therefore equivalent to
+ floor(10^k / 3) < 2^(e-2)
+ and thus to
+ len2(floor(10^k / 3)) <= e - 2
+ while the right inequality is equivalent to
+ 2^(e-2) <= floor(10^(k+1) / 3)
+ and hence to
+ e - 2 < len2(floor(10^(k+1) / 3))
+ These are summarized as
+ len2(floor(10^k / 3)) <= e - 2 < len2(floor(10^(k+1) / 3))
+ */
+ e = 2;
+ k0 = flog10threeQuartersPow2(e);
+ assertTrue(k0 >= 0, "flog10threeQuartersPow2");
+ BigInteger l10 = TEN.pow(k0);
+ BigInteger u10 = l10.multiply(TEN);
+ l = l10.divide(THREE);
+ u = u10.divide(THREE);
+ for (;;) {
+ assertTrue(l.bitLength() <= e - 2 & e - 2 < u.bitLength(),
+ "flog10threeQuartersPow2");
+ ++e;
+ if (e > Q_MAX) {
+ break;
+ }
+ int kp = flog10threeQuartersPow2(e);
+ assertTrue(kp >= k0, "flog10threeQuartersPow2");
+ if (kp > k0) {
+ // k changes at most by 1 at each iteration, hence:
+ assertTrue(kp - k0 == 1, "flog10threeQuartersPow2");
+ k0 = kp;
+ u10 = u10.multiply(TEN);
+ l = u;
+ u = u10.divide(THREE);
+ }
+ }
+ }
+
+ /*
+ Let
+ k = floor(log10(2^e))
+ The method verifies that
+ k = flog10pow2(e), Q_MIN <= e <= Q_MAX
+ This range covers all binary exponents of doubles and floats.
+
+ The first equation above is equivalent to
+ 10^k <= 2^e < 10^(k+1)
+ Equality holds iff e = k = 0.
+ Henceforth, the predicates to check are equivalent to
+ k = 0, if e = 0
+ 10^k < 2^e < 10^(k+1), otherwise
+ The latter will be transformed in various ways for checking purposes.
+
+ For integer n > 0, let further
+ b = len2(n)
+ denote its length in bits. This means exactly the same as
+ 2^(b-1) <= n < 2^b
+ */
+ private static void testFlog10pow2() {
+ // First check the case e = 0
+ assertTrue(flog10pow2(0) == 0, "flog10pow2");
+
+ /*
+ Now check the range F * Q_MIN <= e < 0.
+ By inverting all quantities, the predicate to check is
equivalent to
+ 10^(-k-1) < 2^(-e) < 10^(-k)
+ As e < 0, it follows that 2^(-e) >= 2 and the right inequality
+ implies k < 0.
+ The left inequality means exactly the same as
+ len2(10^(-k-1)) <= -e
+ Similarly, the right inequality is equivalent to
+ -e < len2(10^(-k))
+ The original predicate is therefore equivalent to
+ len2(10^(-k-1)) <= -e < len2(10^(-k))
+ The powers of 10 are integers because k < 0.
+
+ Starting with e = -1 and decrementing towards the lower bound,
the code
+ keeps track of the two powers of 10 so as to avoid recomputing
them.
+ This is easy because at each iteration k changes at most by 1.
A simple
+ multiplication by 10 computes the next power of 10 when needed.
+ */
+ int e = -1;
+ int k = flog10pow2(e);
+ assertTrue(k < 0, "flog10pow2");
+ BigInteger l = TEN.pow(-k - 1);
+ BigInteger u = l.multiply(TEN);
+ for (;;) {
+ assertTrue(l.bitLength() <= -e & -e < u.bitLength(),
+ "flog10pow2");
+ --e;
+ if (e < Q_MIN) {
+ break;
+ }
+ int kp = flog10pow2(e);
+ assertTrue(kp <= k, "flog10pow2");
+ if (kp < k) {
+ // k changes at most by 1 at each iteration, hence:
+ assertTrue(k - kp == 1, "flog10pow2");
+ k = kp;
+ l = u;
+ u = u.multiply(TEN);
+ }
+ }
+
+ /*
+ Finally, in a similar vein, check the range 0 <= e <= Q_MAX.
+ In predicate
+ 10^k < 2^e < 10^(k+1)
+ the right inequality shows that k >= 0.
+ The left inequality means the same as
+ len2(10^k) <= e
+ and the right inequality holds iff
+ e < len2(10^(k+1))
+ The original predicate is thus equivalent to
+ len2(10^k) <= e < len2(10^(k+1))
+ As k >= 0, the powers of 10 are integers.
+ */
+ e = 1;
+ k = flog10pow2(e);
+ assertTrue(k >= 0, "flog10pow2");
+ l = TEN.pow(k);
+ u = l.multiply(TEN);
+ for (;;) {
+ assertTrue(l.bitLength() <= e & e < u.bitLength(),
+ "flog10pow2");
+ ++e;
+ if (e > Q_MAX) {
+ break;
+ }
+ int kp = flog10pow2(e);
+ assertTrue(kp >= k, "flog10pow2");
+ if (kp > k) {
+ // k changes at most by 1 at each iteration, hence:
+ assertTrue(kp - k == 1, "flog10pow2");
+ k = kp;
+ l = u;
+ u = u.multiply(TEN);
+ }
+ }
+ }
+
+ /*
+ Let
+ k = floor(log2(10^e))
+ The method verifies that
+ k = flog2pow10(e), -K_MAX <= e <= -K_MIN
+ This range covers all decimal exponents of doubles and floats.
+
+ The first equation above is equivalent to
+ 2^k <= 10^e < 2^(k+1)
+ Equality holds iff e = 0, implying k = 0.
+ Henceforth, the equivalent predicates to check are
+ k = 0, if e = 0
+ 2^k < 10^e < 2^(k+1), otherwise
+ The latter will be transformed in various ways for checking purposes.
+
+ For integer n > 0, let further
+ b = len2(n)
+ denote its length in bits. This means exactly the same as
+ 2^(b-1) <= n < 2^b
+ */
+ private static void testFlog2pow10() {
+ // First check the case e = 0
+ assertTrue(flog2pow10(0) == 0, "flog2pow10");
+
+ /*
+ Now check the range K_MIN <= e < 0.
+ By inverting all quantities, the predicate to check is
equivalent to
+ 2^(-k-1) < 10^(-e) < 2^(-k)
+ As e < 0, this leads to 10^(-e) >= 10 and the right inequality
implies
+ k <= -4.
+ The above means the same as
+ len2(10^(-e)) = -k
+ The powers of 10 are integer values since e < 0.
+ */
+ int e = -1;
+ int k0 = flog2pow10(e);
+ assertTrue(k0 <= -4, "flog2pow10");
+ BigInteger l = TEN;
+ for (;;) {
+ assertTrue(l.bitLength() == -k0, "flog2pow10");
+ --e;
+ if (e < -K_MAX) {
+ break;
+ }
+ k0 = flog2pow10(e);
+ l = l.multiply(TEN);
+ }
+
+ /*
+ Finally check the range 0 < e <= K_MAX.
+ From the predicate
+ 2^k < 10^e < 2^(k+1)
+ as e > 0, it follows that 10^e >= 10 and the right inequality
implies
+ k >= 3.
+ The above means the same as
+ len2(10^e) = k + 1
+ The powers of 10 are all integer valued, as e > 0.
+ */
+ e = 1;
+ k0 = flog2pow10(e);
+ assertTrue(k0 >= 3, "flog2pow10");
+ l = TEN;
+ for (;;) {
+ assertTrue(l.bitLength() == k0 + 1, "flog2pow10");
+ ++e;
+ if (e > -K_MIN) {
+ break;
+ }
+ k0 = flog2pow10(e);
+ l = l.multiply(TEN);
+ }
+ }
+
+ private static void testBinaryConstants() {
+ assertTrue((long) (double) C_MIN == C_MIN, "C_MIN");
+ assertTrue((long) (double) C_MAX == C_MAX, "C_MAX");
+ assertTrue(scalb(1.0, Q_MIN) == MIN_VALUE, "MIN_VALUE");
+ assertTrue(scalb((double) C_MIN, Q_MIN) == MIN_NORMAL,
"MIN_NORMAL");
+ assertTrue(scalb((double) C_MAX, Q_MAX) == MAX_VALUE, "MAX_VALUE");
+ }
+
+ private static void testDecimalConstants() {
+ assertTrue(K_MIN == MathUtils.K_MIN, "K_MIN");
+ assertTrue(K_MAX == MathUtils.K_MAX, "K_MAX");
+ assertTrue(H == MathUtils.H, "H");
+ }
+
+ private static void testPow10() {
+ int e = 0;
+ long pow = 1;
+ for (; e <= H; e += 1, pow *= 10) {
+ assertTrue(pow == pow10(e), "pow10");
+ }
+ }
+
+ public static void test() {
+ testBinaryConstants();
+ testFlog10pow2();
+ testFlog10threeQuartersPow2();
+ testDecimalConstants();
+ testFlog2pow10();
+ testPow10();
+ testG();
+ }
+
+ public static void main(String[] args) {
+ test();
+ }
+
+}
diff --git
a/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/ToDecimalChecker.java
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/ToDecimalChecker.java
new file mode 100644
--- /dev/null
+++
b/test/jdk/jdk/internal/math/ToDecimal/java.base/jdk/internal/math/ToDecimalChecker.java
@@ -0,0 +1,409 @@
+/*
+ * Copyright 2018-2020 Raffaello Giulietti
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation
the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package jdk.internal.math;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import static java.math.BigInteger.*;
+
+/*
+A checker for the Javadoc specification.
+It just relies on straightforward use of (expensive) BigDecimal arithmetic,
+not optimized at all.
+ */
+abstract class ToDecimalChecker extends BasicChecker {
+
+ // The string to check
+ private final String s;
+
+ // The decimal parsed from s is c 10^q
+ private long c;
+ private int q;
+
+ // The number of digits parsed from s: 10^(len10-1) <= c < 10^len10
+ private int len10;
+
+ ToDecimalChecker(String s) {
+ this.s = s;
+ }
+
+ /*
+ Returns e be such that 10^(e-1) <= v < 10^e.
+ */
+ static int e(double v) {
+ // log10(v) + 1 is a first good approximation of e
+ int e = (int) Math.floor(Math.log10(v)) + 1;
+
+ // Full precision search for e such that 10^(e-1) <= c 2^q < 10^e.
+ BigDecimal vp = new BigDecimal(v);
+ BigDecimal low = new BigDecimal(BigInteger.ONE, -(e - 1));
+ while (low.compareTo(vp) > 0) {
+ e -= 1;
+ low = new BigDecimal(BigInteger.ONE, -(e - 1));
+ }
+ BigDecimal high = new BigDecimal(BigInteger.ONE, -e);
+ while (vp.compareTo(high) >= 0) {
+ e += 1;
+ high = new BigDecimal(BigInteger.ONE, -e);
+ }
+ return e;
+ }
+
+ static long cTiny(int qMin, int kMin) {
+ BigInteger[] qr = ONE.shiftLeft(-qMin)
+ .divideAndRemainder(TEN.pow(-(kMin + 1)));
+ BigInteger cTiny = qr[1].signum() > 0 ? qr[0].add(ONE) : qr[0];
+ assertTrue(cTiny.bitLength() < Long.SIZE, "C_TINY");
+ return cTiny.longValue();
+ }
+
+ void assertTrue() {
+ if (isOK()) {
+ return;
+ }
+ String msg = "toString applied to the bits " +
+ hexBits() +
+ " returns " +
+ "\"" + s + "\"" +
+ ", which is not correct according to the specification.";
+ if (FAILURE_THROWS_EXCEPTION) {
+ throw new RuntimeException(msg);
+ }
+ System.err.println(msg);
+ }
+
+ /*
+ Returns whether s syntactically meets the expected output of
+ toString. It is restricted to finite positive outputs.
+ It is an unusually long method but rather straightforward, too.
+ Many conditionals could be merged, but KISS here.
+ */
+ private boolean parse(String t) {
+ try {
+ // first determine interesting boundaries in the string
+ StringReader r = new StringReader(t);
+ int ch = r.read();
+
+ int i = 0;
+ while (ch == '0') {
+ ++i;
+ ch = r.read();
+ }
+ // i is just after zeroes starting the integer
+
+ int p = i;
+ while ('0' <= ch && ch <= '9') {
+ c = 10 * c + (ch - '0');
+ if (c < 0) {
+ return false;
+ }
+ ++len10;
+ ++p;
+ ch = r.read();
+ }
+ // p is just after digits ending the integer
+
+ int fz = p;
+ if (ch == '.') {
+ ++fz;
+ ch = r.read();
+ }
+ // fz is just after a decimal '.'
+
+ int f = fz;
+ while (ch == '0') {
+ c = 10 * c + (ch - '0');
+ if (c < 0) {
+ return false;
+ }
+ ++len10;
+ ++f;
+ ch = r.read();
+ }
+ // f is just after zeroes starting the fraction
+
+ if (c == 0) {
+ len10 = 0;
+ }
+ int x = f;
+ while ('0' <= ch && ch <= '9') {
+ c = 10 * c + (ch - '0');
+ if (c < 0) {
+ return false;
+ }
+ ++len10;
+ ++x;
+ ch = r.read();
+ }
+ // x is just after digits ending the fraction
+
+ int g = x;
+ if (ch == 'E') {
+ ++g;
+ ch = r.read();
+ }
+ // g is just after an exponent indicator 'E'
+
+ int ez = g;
+ if (ch == '-') {
+ ++ez;
+ ch = r.read();
+ }
+ // ez is just after a '-' sign in the exponent
+
+ int e = ez;
+ while (ch == '0') {
+ ++e;
+ ch = r.read();
+ }
+ // e is just after zeroes starting the exponent
+
+ int z = e;
+ while ('0' <= ch && ch <= '9') {
+ q = 10 * q + (ch - '0');
+ if (q < 0) {
+ return false;
+ }
+ ++z;
+ ch = r.read();
+ }
+ // z is just after digits ending the exponent
+
+ // No other char after the number
+ if (z != t.length()) {
+ return false;
+ }
+
+ // The integer must be present
+ if (p == 0) {
+ return false;
+ }
+
+ // The decimal '.' must be present
+ if (fz == p) {
+ return false;
+ }
+
+ // The fraction must be present
+ if (x == fz) {
+ return false;
+ }
+
+ // The fraction is not 0 or it consists of exactly one 0
+ if (f == x && f - fz > 1) {
+ return false;
+ }
+
+ // Plain notation, no exponent
+ if (x == z) {
+ // At most one 0 starting the integer
+ if (i > 1) {
+ return false;
+ }
+
+ // If the integer is 0, at most 2 zeroes start the fraction
+ if (i == 1 && f - fz > 2) {
+ return false;
+ }
+
+ // The integer cannot have more than 7 digits
+ if (p > 7) {
+ return false;
+ }
+
+ q = fz - x;
+
+ // OK for plain notation
+ return true;
+ }
+
+ // Computerized scientific notation
+
+ // The integer has exactly one nonzero digit
+ if (i != 0 || p != 1) {
+ return false;
+ }
+
+ //
+ // There must be an exponent indicator
+ if (x == g) {
+ return false;
+ }
+
+ // There must be an exponent
+ if (ez == z) {
+ return false;
+ }
+
+ // The exponent must not start with zeroes
+ if (ez != e) {
+ return false;
+ }
+
+ if (g != ez) {
+ q = -q;
+ }
+
+ // The exponent must not lie in [-3, 7)
+ if (-3 <= q && q < 7) {
+ return false;
+ }
+
+ q += fz - x;
+
+ // OK for computerized scientific notation
+ return true;
+ } catch (IOException ex) {
+ // An IOException on a StringReader??? Please...
+ return false;
+ }
+ }
+
+ private boolean isOK() {
+ if (isNaN()) {
+ return s.equals("NaN");
+ }
+ String t = s;
+ if (isNegative()) {
+ if (s.isEmpty() || s.charAt(0) != '-') {
+ return false;
+ }
+ negate();
+ t = s.substring(1);
+ }
+ if (isInfinity()) {
+ return t.equals("Infinity");
+ }
+ if (isZero()) {
+ return t.equals("0.0");
+ }
+ if (!parse(t)) {
+ return false;
+ }
+ if (len10 < 2) {
+ c *= 10;
+ q -= 1;
+ len10 += 1;
+ }
+ if (2 > len10 || len10 > maxLen10()) {
+ return false;
+ }
+
+ // The exponent is bounded
+ if (minExp() > q + len10 || q + len10 > maxExp()) {
+ return false;
+ }
+
+ // s must recover v
+ try {
+ if (!recovers(t)) {
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ return false;
+ }
+
+ // Get rid of trailing zeroes, still ensuring at least 2 digits
+ while (len10 > 2 && c % 10 == 0) {
+ c /= 10;
+ q += 1;
+ len10 -= 1;
+ }
+
+ if (len10 > 2) {
+ // Try with a shorter number less than v...
+ if (recovers(BigDecimal.valueOf(c / 10, -q - 1))) {
+ return false;
+ }
+
+ // ... and with a shorter number greater than v
+ if (recovers(BigDecimal.valueOf(c / 10 + 1, -q - 1))) {
+ return false;
+ }
+ }
+
+ // Try with the decimal predecessor...
+ BigDecimal dp = c == 10 ?
+ BigDecimal.valueOf(99, -q + 1) :
+ BigDecimal.valueOf(c - 1, -q);
+ if (recovers(dp)) {
+ BigDecimal bv = toBigDecimal();
+ BigDecimal deltav = bv.subtract(BigDecimal.valueOf(c, -q));
+ if (deltav.signum() >= 0) {
+ return true;
+ }
+ BigDecimal delta = dp.subtract(bv);
+ if (delta.signum() >= 0) {
+ return false;
+ }
+ int cmp = deltav.compareTo(delta);
+ return cmp > 0 || cmp == 0 && (c & 0x1) == 0;
+ }
+
+ // ... and with the decimal successor
+ BigDecimal ds = BigDecimal.valueOf(c + 1, -q);
+ if (recovers(ds)) {
+ BigDecimal bv = toBigDecimal();
+ BigDecimal deltav = bv.subtract(BigDecimal.valueOf(c, -q));
+ if (deltav.signum() <= 0) {
+ return true;
+ }
+ BigDecimal delta = ds.subtract(bv);
+ if (delta.signum() <= 0) {
+ return false;
+ }
+ int cmp = deltav.compareTo(delta);
+ return cmp < 0 || cmp == 0 && (c & 0x1) == 0;
+ }
+
+ return true;
+ }
+
+ abstract BigDecimal toBigDecimal();
+
+ abstract boolean recovers(BigDecimal b);
+
+ abstract boolean recovers(String s);
+
+ abstract String hexBits();
+
+ abstract int minExp();
+
+ abstract int maxExp();
+
+ abstract int maxLen10();
+
+ abstract boolean isZero();
+
+ abstract boolean isInfinity();
+
+ abstract void negate();
+
+ abstract boolean isNegative();
+
+ abstract boolean isNaN();
+
+}
2
5
17 Mar '20
Please review the CSR proposed for JEP 371 Hidden Classes [1].
CSR:
https://bugs.openjdk.java.net/browse/JDK-8238359
javadoc/specdiff:
http://cr.openjdk.java.net/~mchung/valhalla/webrevs/hidden-classes/api/
http://cr.openjdk.java.net/~mchung/valhalla/webrevs/hidden-classes/specdiff/
JVMS 5.4.4 change:
http://cr.openjdk.java.net/~mchung/valhalla/webrevs/hidden-classes/Draft-JV…
A brief summary of the changes:
1. A new Lookup::defineHiddenClass method is the API to create a hidden
class.
2. A new Lookup.ClassOption enum class defines NESTMATE and WEAK option that
can be specified when creating a hidden class.
3. A new Class::isHiddenClass method tests if a class is a hidden class.
4. Field::setXXX method will throw IAE on a final field of a hidden class
regardless of the value of the accessible flag.
5. Class::getNestMembers is updated not to throw any exception when it fails
to validate the nest membership. Instead this method will return all
members that are listed in `NestMembers` attribute if present and
determined to have the same nest host as this class.
We uncovered a bug in Lookup::defineClass spec throws LinkageError and
intends
to have the newly created class linked. However, the implementation in 14
does not link the class. A separate CSR proposes to update the
implementation
to match the spec - please also review:
https://bugs.openjdk.java.net/browse/JDK-8240338
This is tracked as a separate JBS issue JDK-8238195 that is fixed in
this patch.
The code review will be posted separately.
Thanks
Mandy
[1] https://openjdk.java.net/jeps/371
[2] JDK-8230502 Add support in JVM TI and JDI for hidden classes
[3] JDK-8219607 Add support in Graal and AOT for hidden and weak class
[4]
https://mail.openjdk.java.net/pipermail/valhalla-dev/2020-March/006872.html
1
1
Hi,
The jpackage tool on macOS supports adding a custom volume icon to DMGs
that it produces, but this functionality is currently broken.
** Analysis
------------------
A custom volume icon added as "*-volume.icns" in the resource directory
gets copied to the temporary DMG when building but is removed when the
DMGsetup.scpt script is run.
Specifically it is the line:
update without registering applications
at the end of the script that seems to remove it.
It is unclear what this line is for. Many DMG creation scripts found by
googling includes it, but not all.
The same problem is reported here:
https://github.com/andreyvit/create-dmg/issues/57
It was fixed in this commit:
https://github.com/andreyvit/create-dmg/commit/bb4651bc1bc8c9e3571ca17fe43e…
and according to this comment the fix works for at least macOS 10.9-10.13:
https://github.com/andreyvit/create-dmg/issues/57#issuecomment-425031425
I have verified the fix, and an alternative (see below), on macOS 10.15.
A Google search for "update without registering applications" turns up the
book "AppleScript: A Comprehensive Guide to Scripting and Automation on Mac
OS X":
https://books.google.se/books?id=t0snCgAAQBAJ&pg=PA33&lpg=PA33&dq=applescri…
The book uses the "update" command as an example of the AppleScript
dictionary and includes this section:
"The optional parameters are _necessity_, which is explained well, and
_registering applications_,
which I have no idea what it's good for or what it does.
The dictionary author either got a bit lazy, or simply didn't know
either."
The description of the update command is:
"Update the display of the specified object(s) to match their on-disk
representation"
Since the jpackage DMGsetup.scpt script closes the window just after using
the update command there doesn't seem to be much point in updating the
display of the window.
** Patches
------------------
I have tried two alternative ways to fix this problem and both are attached
as patches to this email.
Both of these fixes work, but I guess the first one is the simpler
approach.
- macos_dmg_volume_icon_fix_1.patch
This patch simply removes the "update without registering applications"
line from DMGsetup.scpt.
- macos_dmg_volume_icon_fix_2.patch
This patch changes the order of the code in MacDmgBundler.java so that the
volume icon is added after running the DMGsetup.scpt script.
This also fixes the problem.
** Unit test
------------------
- macos_dmg_volume_icon_test.patch
I am attaching a jtreg unit test showing the problem as a separate patch.
** OCA
------------------
I have previously signed an OCA for the OpenJFX project, and if I
understand the contribution document correctly that should be enough for
OpenJDK as well.
--
/Johan Kaving
1
0
RFC: 8132359: JarURLConnection.getJarFile() resource leak when file is not found
by Alex Kashchenko 16 Mar '20
by Alex Kashchenko 16 Mar '20
16 Mar '20
Hi,
Based on these maillist threads:
https://mail.openjdk.java.net/pipermail/core-libs-dev/2020-March/065076.html
https://mail.openjdk.java.net/pipermail/core-libs-dev/2019-November/063643.…
I am looking for comments and suggestions, whether the following change
to JarURLConnection.getJarFile() behaviour may be acceptable:
If, during connect() call, jarFile itself was created successfully, but
access to (non-existent) jarEntry failed - return this jarFile to caller
instead of throwing exception.
bug: https://bugs.openjdk.java.net/browse/JDK-8132359
webrev: http://cr.openjdk.java.net/~akasko/jdk/8132359/webrev.00/
This change also allows to fix JDK-8232854 with the minimal change to
URLClassPath (included with the patch).
This change doesn't cause regression failures in java/net.
This change causes one compatibility failure, when getManifest() doesn't
throw expected IOException when URL points to non-existent class inside JAR.
--
-Alex
2
1