diffstat for rhino-1.7.15 rhino-1.7.15.1

 NOTICE.txt                                                   |   27 
 build.gradle                                                 |   17 
 debian/changelog                                             |    9 
 gradle.properties                                            |    4 
 src/org/mozilla/javascript/DToA.java                         |  820 -----------
 src/org/mozilla/javascript/NativeNumber.java                 |  138 -
 src/org/mozilla/javascript/ScriptRuntime.java                |   23 
 src/org/mozilla/javascript/dtoa/Decimal.java                 |  306 ++++
 src/org/mozilla/javascript/dtoa/DecimalFormatter.java        |  163 ++
 src/org/mozilla/javascript/dtoa/DoubleFormatter.java         |  253 +++
 src/org/mozilla/javascript/dtoa/MathUtils.java               |  804 ++++++++++
 src/org/mozilla/javascript/v8dtoa/CachedPowers.java          |  157 --
 src/org/mozilla/javascript/v8dtoa/DiyFp.java                 |  157 --
 src/org/mozilla/javascript/v8dtoa/DoubleHelper.java          |  131 -
 src/org/mozilla/javascript/v8dtoa/FastDtoa.java              |  509 ------
 src/org/mozilla/javascript/v8dtoa/FastDtoaBuilder.java       |  108 -
 testsrc/org/mozilla/javascript/tests/NumberToStringTest.java |   89 +
 testsrc/test262.properties                                   |    4 
 18 files changed, 1748 insertions(+), 1971 deletions(-)

diff -Nru rhino-1.7.15/build.gradle rhino-1.7.15.1/build.gradle
--- rhino-1.7.15/build.gradle	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/build.gradle	2025-12-03 05:43:04.000000000 +0200
@@ -304,6 +304,7 @@
             pom.withXml {
                 def root = asNode()
 
+                root.appendNode('name', 'rhino')
                 root.appendNode('description', """
     Rhino is an open-source implementation of JavaScript written entirely in Java.
     It is typically embedded into Java applications to provide scripting to end users.
@@ -329,6 +330,10 @@
                 o.appendNode("name", "The Mozilla Foundation")
                 o.appendNode("url", "http://www.mozilla.org")
 
+                def d = root.appendNode("developers")
+                def dd = d.appendNode("developer")
+                dd.appendNode("name", "Greg Brail")
+                dd.appendNode("email", "gbrail@users.noreply.github.com")
             }
         }
 
@@ -340,6 +345,7 @@
             pom.withXml {
                 def root = asNode()
 
+                root.appendNode('name', 'rhino-runtime')
                 root.appendNode('description', """
     Rhino JavaScript runtime jar, excludes tools & JSR-223 Script Engine wrapper.
 """)
@@ -362,6 +368,11 @@
                 def o = root.appendNode("organization")
                 o.appendNode("name", "The Mozilla Foundation")
                 o.appendNode("url", "http://www.mozilla.org")
+
+                def d = root.appendNode("developers")
+                def dd = d.appendNode("developer")
+                dd.appendNode("name", "Greg Brail")
+                dd.appendNode("email", "gbrail@users.noreply.github.com")
             }
         }
 
@@ -373,6 +384,7 @@
             pom.withXml {
                 def root = asNode()
 
+                root.appendNode('name', 'rhino-engine')
                 root.appendNode('description', """
     Rhino Javascript JSR-223 Script Engine wrapper.
 """)
@@ -401,6 +413,11 @@
                 rhino.appendNode("groupId", "org.mozilla")
                 rhino.appendNode("artifactId", "rhino")
                 rhino.appendNode("version", getVersion())
+
+                def d = root.appendNode("developers")
+                def dd = d.appendNode("developer")
+                dd.appendNode("name", "Greg Brail")
+                dd.appendNode("email", "gbrail@users.noreply.github.com")
             }
         }
     }
diff -Nru rhino-1.7.15/debian/changelog rhino-1.7.15.1/debian/changelog
--- rhino-1.7.15/debian/changelog	2024-10-23 17:34:49.000000000 +0300
+++ rhino-1.7.15.1/debian/changelog	2026-06-30 21:23:20.000000000 +0300
@@ -1,3 +1,12 @@
+rhino (1.7.15.1-0.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * New upstream release.
+    - CVE-2025-66453: High CPU usage and potential DoS when passing
+      specific numbers to toFixed() (Closes: #1121953)
+
+ -- Adrian Bunk <bunk@debian.org>  Tue, 30 Jun 2026 21:23:20 +0300
+
 rhino (1.7.15-1) unstable; urgency=medium
 
   * Team upload.
diff -Nru rhino-1.7.15/gradle.properties rhino-1.7.15.1/gradle.properties
--- rhino-1.7.15/gradle.properties	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/gradle.properties	2025-12-03 05:43:04.000000000 +0200
@@ -1,8 +1,8 @@
 rootProject.name=rhino
 group=org.mozilla
-version=1.7.15
+version=1.7.15.1
 buildDir=buildGradle
 mavenSnapshotRepo=https://oss.sonatype.org/content/repositories/snapshots
 mavenReleaseRepo=https://oss.sonatype.org/service/local/staging/deploy/maven2/
 org.gradle.caching=true
-org.gradle.parallel=true
\ No newline at end of file
+org.gradle.parallel=true
diff -Nru rhino-1.7.15/NOTICE.txt rhino-1.7.15.1/NOTICE.txt
--- rhino-1.7.15/NOTICE.txt	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/NOTICE.txt	2025-12-03 05:43:04.000000000 +0200
@@ -32,4 +32,29 @@
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----
+
+Portions of the number-to-string code are subject to the following:
+
+ 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.
+ 
\ No newline at end of file
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/dtoa/DecimalFormatter.java rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/DecimalFormatter.java
--- rhino-1.7.15/src/org/mozilla/javascript/dtoa/DecimalFormatter.java	1970-01-01 02:00:00.000000000 +0200
+++ rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/DecimalFormatter.java	2025-12-03 05:43:04.000000000 +0200
@@ -0,0 +1,163 @@
+package org.mozilla.javascript.dtoa;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+public class DecimalFormatter {
+    private static final double MAX_FIXED = 1E21;
+
+    /**
+     * The algorithm of Number.prototype.toExponential. If fractionDigits is < 0, then it indicates
+     * the special case that the value was previously undefined, which calls for a different
+     * precision for the calculation.
+     */
+    public static String toExponential(double v, int fractionDigits) {
+        assert Double.isFinite(v);
+
+        if (fractionDigits < 0) {
+            // In this case, we are supposed to use the "shortest possible representation."
+            // This is what our usual toString implementation does
+            return DoubleFormatter.toDecimal(v).toString(Decimal.Mode.TO_EXPONENTIAL);
+        }
+
+        boolean negative = Math.signum(v) < 0;
+        double val = v;
+        if (negative) {
+            val = Math.abs(v);
+        }
+        BigDecimal bd =
+                new BigDecimal(val, new MathContext(fractionDigits + 1, RoundingMode.HALF_UP));
+
+        int exponent;
+        if (bd.scale() >= 0) {
+            exponent = bd.precision() - bd.scale() - 1;
+        } else {
+            // digits000
+            exponent = bd.precision() + -bd.scale() - 1;
+        }
+
+        return toExponentialString(bd, exponent, fractionDigits, negative);
+    }
+
+    /** The algorithm of Number.prototype.toFixed(fractionDigits). */
+    public static String toFixed(double v, int fractionDigits) {
+        assert Double.isFinite(v);
+        assert fractionDigits >= 0;
+        boolean negative = Math.signum(v) < 0;
+        double val = v;
+        if (negative) {
+            val = Math.abs(v);
+        }
+        if (val >= MAX_FIXED) {
+            return DoubleFormatter.toString(v);
+        }
+        BigDecimal bd = new BigDecimal(val, MathContext.UNLIMITED);
+        if (bd.scale() > fractionDigits) {
+            bd = bd.setScale(fractionDigits, RoundingMode.HALF_UP);
+        }
+        return toFixedString(bd, fractionDigits, negative);
+    }
+
+    /** The algorithm of Number.prototype.toPrecision() */
+    public static String toPrecision(double v, int precision) {
+        assert Double.isFinite(v);
+        assert precision >= 1;
+        boolean negative = Math.signum(v) < 0;
+        double val;
+        if (negative) {
+            val = -v;
+        } else {
+            val = v;
+        }
+        BigDecimal bd = new BigDecimal(val, new MathContext(precision, RoundingMode.HALF_UP));
+
+        int scale = bd.scale();
+        int numDigits = bd.precision();
+        int exponent;
+        int fractionDigits;
+        if (scale >= 0) {
+            if (scale >= numDigits) {
+                // 0.digits000
+                fractionDigits = precision;
+            } else {
+                // dig.its
+                fractionDigits = precision - (numDigits - scale);
+            }
+            exponent = numDigits - scale - 1;
+        } else {
+            // digits000
+            fractionDigits = 0;
+            exponent = numDigits + -scale - 1;
+        }
+
+        if (exponent < -6 || exponent >= precision) {
+            return toExponentialString(bd, exponent, precision - 1, negative);
+        }
+        return toFixedString(bd, fractionDigits, negative);
+    }
+
+    private static String toFixedString(BigDecimal d, int fractionDigits, boolean negative) {
+        int scale = d.scale();
+        // Turns out that, in UNLIMITED scale mode, BigDecimal will not
+        // produce a negative scale.
+        assert (scale >= 0);
+        String digits = d.unscaledValue().toString();
+        int numDigits = digits.length();
+        if (scale == 0 && fractionDigits == 0) {
+            if (negative) {
+                return "-" + digits;
+            }
+            return digits;
+        }
+
+        // Room for digits, -, ., extra 0
+        StringBuilder b = new StringBuilder(numDigits * 2 + 3);
+        if (negative) {
+            b.append('-');
+        }
+        if (scale >= numDigits) {
+            // 0.000digits000
+            b.append("0.");
+            fillZeroes(b, scale - numDigits);
+            b.append(digits);
+        } else {
+            // dig.its000
+            b.append(digits.substring(0, numDigits - scale));
+            b.append('.');
+            b.append(digits.substring(numDigits - scale));
+        }
+        fillZeroes(b, fractionDigits - scale);
+        return b.toString();
+    }
+
+    private static String toExponentialString(
+            BigDecimal d, int exponent, int fractionDigits, boolean negative) {
+        String digits = d.unscaledValue().toString();
+        int numDigits = digits.length();
+        // Room for digits, ., -, e+000
+        StringBuilder b = new StringBuilder(numDigits + fractionDigits + 7);
+
+        if (negative) {
+            b.append('-');
+        }
+        b.append(digits.charAt(0));
+        if (numDigits > 1 || fractionDigits >= 1) {
+            b.append('.');
+            b.append(digits.substring(1));
+            fillZeroes(b, fractionDigits - (numDigits - 1));
+        }
+        b.append('e');
+        if (exponent >= 0) {
+            b.append('+');
+        }
+        b.append(exponent);
+        return b.toString();
+    }
+
+    private static void fillZeroes(StringBuilder b, int count) {
+        for (int i = 0; i < count; i++) {
+            b.append('0');
+        }
+    }
+}
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/dtoa/Decimal.java rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/Decimal.java
--- rhino-1.7.15/src/org/mozilla/javascript/dtoa/Decimal.java	1970-01-01 02:00:00.000000000 +0200
+++ rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/Decimal.java	2025-12-03 05:43:04.000000000 +0200
@@ -0,0 +1,306 @@
+package org.mozilla.javascript.dtoa;
+
+/**
+ * This class formats a decimal number into a string representation and stores the result in a
+ * buffer. It is highly optimized for the case of formatting a double and only works if the number
+ * has a maximum of 17 digits of precision.
+ *
+ * <p>Based on code by Guilietti:
+ * https://github.com/c4f7fcce9cb06515/Schubfach/blob/3c92d3c9b1fead540616c918cdfef432bca53dfa/todec/src/math/FloatToDecimal.java
+ */
+public class Decimal {
+    // Used for left-to-right digit extraction.
+    private static final int MASK_28 = (1 << 28) - 1;
+
+    /*
+    Room for the longer of the forms.
+    Always 17 significant digits.
+        -ddddd.dddddddddddd             H + 2 characters
+        -0.000000ddddddddddddddddd      H + 9 characters
+            (JS will used fixed format down to -6 exponent)
+        -d.ddddddddddddddddE-eee        H + 7 characters
+        -ddddddddddddddddd0000          H + 5 characters
+            (JS will use fixed format up to 21 exponent)
+    where there are H digits d
+
+    That means we need 26 characters for the largest possible number.
+    We will use 32 because powers of two are good.
+    */
+    public static final int MAX_CHARS = 32;
+
+    private final long digits;
+    private final int exponent;
+    private final boolean negative;
+    private int length;
+    private final char[] buf = new char[MAX_CHARS];
+
+    enum Mode {
+        DEFAULT,
+        TO_EXPONENTIAL
+    };
+
+    Decimal(long d, int e, boolean n) {
+        this.digits = d;
+        this.exponent = e;
+        this.negative = n;
+    }
+
+    /**
+     * Format the number according to the formatting rules in EcmaScript chapter 6, as defined for
+     * the "Number::toString" operation, for radix 10.
+     */
+    @Override
+    public String toString() {
+        return toString(Mode.DEFAULT);
+    }
+
+    String toString(Mode mode) {
+        length = 0;
+
+        /*
+        For details not discussed here see section 10 of [1].
+
+        Determine len such that
+            10^(len-1) <= f < 10^len
+         */
+        int len = MathUtils.flog10pow2(Long.SIZE - Long.numberOfLeadingZeros(digits));
+        if (digits >= MathUtils.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
+         */
+        long f = digits * MathUtils.pow10(DoubleFormatter.H - len);
+        int e = exponent + 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)
+         */
+
+        /*
+         * Implementation note: The calculations above adjusts "f" so that
+         * the most significant bits are at the front, with trailing zeroes.
+         * That lets the bit of code below separate the digits into three
+         * parts -- the first digit, the next 8, and the 8 after that.
+         * We can then stringify it much more efficiently using this here clever
+         * algorithm by Giulietti. We have adapted his original code a bit
+         * to handle JavaScript, which requires fixed-format numbers for a
+         * wider range of values before switching to exponential format.
+         */
+        long hm = MathUtils.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_000L * h);
+
+        if (negative) {
+            append('-');
+        }
+
+        if (mode == Mode.DEFAULT) {
+            if (0 < e && e <= 8) {
+                return toFixed(h, m, l, e);
+            }
+            if (8 < e && e <= 16) {
+                return toFixedBigger(h, m, l, e);
+            }
+            if (16 < e && e <= 21) {
+                return toFixedBiggest(h, m, l, e);
+            }
+            if (-6 < e && e <= 0) {
+                return toFixedSmall(h, m, l, e);
+            }
+        }
+        return toExponential(h, m, l, e);
+    }
+
+    private String toFixed(int h, int m, int l, int e) {
+        assert e <= 8;
+        /*
+        0 < e <= 8: 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 makeString();
+    }
+
+    private String toFixedBigger(int h, int m, int l, int e) {
+        assert e > 8 && e <= 16;
+        /*
+        8 > e <= 16: plain format without leading zeroes.
+        Left-to-right digits extraction:
+        But the first 9 characters are before the decimal.
+         */
+        appendDigit(h);
+        append8Digits(m);
+        int y = y(l);
+        int t;
+        int i = 9;
+        for (; i < e; ++i) {
+            t = 10 * y;
+            appendDigit(t >>> 28);
+            y = t & MASK_28;
+        }
+        append('.');
+        for (; i <= 16; ++i) {
+            t = 10 * y;
+            appendDigit(t >>> 28);
+            y = t & MASK_28;
+        }
+        trimZeroes();
+        return makeString();
+    }
+
+    private String toFixedBiggest(int h, int m, int l, int e) {
+        assert e > 16;
+        /*
+        16 < e: plain format with trailing zeroes.
+         */
+        appendDigit(h);
+        append8Digits(m);
+        append8Digits(l);
+        for (int i = 17; i < e; i++) {
+            append('0');
+        }
+        return makeString();
+    }
+
+    private String toFixedSmall(int h, int m, int l, int e) {
+        assert e <= 0;
+        // -3 < e <= 0: plain format with leading zeroes.
+        appendDigit(0);
+        append('.');
+        for (; e < 0; ++e) {
+            appendDigit(0);
+        }
+        appendDigit(h);
+        append8Digits(m);
+        lowDigits(l);
+        return makeString();
+    }
+
+    private String toExponential(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 makeString();
+    }
+
+    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) (MathUtils.multiplyHigh((long) (a + 1) << 28, 193_428_131_138_340_668L) >>> 20)
+                - 1;
+    }
+
+    private void lowDigits(int l) {
+        if (l != 0) {
+            append8Digits(l);
+        }
+        trimZeroes();
+    }
+
+    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 exponent(int e) {
+        assert e >= -999 && e <= 999;
+        append('e');
+        if (e < 0) {
+            append('-');
+            e = -e;
+        } else {
+            append('+');
+        }
+        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 trimZeroes() {
+        while (length > 0 && buf[length - 1] == '0') {
+            length--;
+        }
+        if (length > 0 && buf[length - 1] == '.') {
+            length--;
+        }
+    }
+
+    private void append(char ch) {
+        buf[length++] = ch;
+    }
+
+    private void appendDigit(int d) {
+        buf[length++] = (char) ('0' + d);
+    }
+
+    private String makeString() {
+        return new String(buf, 0, length);
+    }
+}
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/dtoa/DoubleFormatter.java rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/DoubleFormatter.java
--- rhino-1.7.15/src/org/mozilla/javascript/dtoa/DoubleFormatter.java	1970-01-01 02:00:00.000000000 +0200
+++ rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/DoubleFormatter.java	2025-12-03 05:43:04.000000000 +0200
@@ -0,0 +1,253 @@
+package org.mozilla.javascript.dtoa;
+
+/**
+ * This class formats a double into a set of digits and an exponent for further formatting by the
+ * Double class. It is based on the same code used by Jackson and in OpenJDK with the following
+ * copyright:
+ *
+ * <p>Copyright 2018-2020 Raffaello Giulietti
+ *
+ * <p>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:
+ *
+ * <p>The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * <p>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.
+ */
+public class DoubleFormatter {
+    /*
+    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].
+     */
+
+    // Sources with the license are here:
+    // https://github.com/c4f7fcce9cb06515/Schubfach/blob/3c92d3c9b1fead540616c918cdfef432bca53dfa/todec/src/math/FloatToDecimal.java
+
+    // 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;
+
+    // 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;
+
+    /**
+     * Convert a double to String as defined in the "Number::toString" operation in ECMAScript. It
+     * can handle any number including non-finite numbers.
+     */
+    public static String toString(double v) {
+        long bits = Double.doubleToRawLongBits(v);
+        long t = bits & T_MASK;
+        int bq = (int) (bits >>> (P - 1)) & BQ_MASK;
+        if (bq < BQ_MASK) {
+            if (bq == 0 && t == 0) {
+                return "0";
+            }
+            return toDecimalImpl(bits, t, bq).toString();
+        }
+        if (t != 0) {
+            return "NaN";
+        }
+        return bits > 0 ? "Infinity" : "-Infinity";
+    }
+
+    /**
+     * Convert a double to a Decimal object that may be output in various ways. Unlike toString, and
+     * since it always returns a Decimal, it must be used with finite numbers only or the result is
+     * undetermined.
+     */
+    public static Decimal toDecimal(double v) {
+        assert Double.isFinite(v);
+        long bits = Double.doubleToRawLongBits(v);
+        long t = bits & T_MASK;
+        int bq = (int) (bits >>> (P - 1)) & BQ_MASK;
+        return toDecimalImpl(bits, t, bq);
+    }
+
+    private static Decimal toDecimalImpl(long bits, long t, int bq) {
+        /*
+        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)
+         */
+        // Only finite numbers are supported
+        assert bq < BQ_MASK;
+        boolean negative = false;
+        if (bits < 0) {
+            negative = true;
+        }
+        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 new Decimal(f, 0, negative);
+                }
+            }
+            return toDecimalFull(-mq, c, 0, negative);
+        }
+        if (t != 0) {
+            // subnormal value
+            return t < C_TINY
+                    ? toDecimalFull(Q_MIN, 10 * t, -1, negative)
+                    : toDecimalFull(Q_MIN, t, 0, negative);
+        }
+        return new Decimal(0, 1, false);
+    }
+
+    private static Decimal toDecimalFull(int q, long c, int dk, boolean negative) {
+        /*
+        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 = MathUtils.flog10pow2(q);
+        } else {
+            // irregular spacing
+            cbl = cb - 1;
+            k = MathUtils.flog10threeQuartersPow2(q);
+        }
+        int h = q + MathUtils.flog2pow10(-k) + 2;
+
+        // g1 and g0 are as in section 9.9.3 of [1], so g = g1 2^63 + g0
+        long g1 = MathUtils.g1(k);
+        long g0 = MathUtils.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 * MathUtils.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 new Decimal(upin ? sp10 : tp10, k, negative);
+            }
+        }
+
+        /*
+        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 new Decimal(uin ? s : t, k + dk, negative);
+        }
+        /*
+        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 new Decimal(cmp < 0 || (cmp == 0 && (s & 0x1) == 0) ? s : t, k + dk, negative);
+    }
+
+    /*
+    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 = MathUtils.multiplyHigh(g0, cp);
+        long y0 = g1 * cp;
+        long y1 = MathUtils.multiplyHigh(g1, cp);
+        long z = (y0 >>> 1) + x1;
+        long vbp = y1 + (z >>> 63);
+        return vbp | ((z & MASK_63) + MASK_63) >>> 63;
+    }
+}
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/dtoa/MathUtils.java rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/MathUtils.java
--- rhino-1.7.15/src/org/mozilla/javascript/dtoa/MathUtils.java	1970-01-01 02:00:00.000000000 +0200
+++ rhino-1.7.15.1/src/org/mozilla/javascript/dtoa/MathUtils.java	2025-12-03 05:43:04.000000000 +0200
@@ -0,0 +1,804 @@
+/*
+ * 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 org.mozilla.javascript.dtoa;
+
+/**
+ * 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 &le; {@code e} &le; {@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> &le; 2<sup>{@code
+     * e}</sup> &lt; 10<sup><i>k</i>+1</sup>.
+     *
+     * <p>The result is correct when |{@code e}| &le; 5_456_721. Otherwise the result is undefined.
+     *
+     * @param e The exponent of 2, which should meet |{@code e}| &le; 5_456_721 for safe results.
+     * @return &lfloor;log<sub>10</sub>2<sup>{@code e}</sup>&rfloor;.
+     */
+    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> &le; 3/4 &middot;
+     * 2<sup>{@code e}</sup> &lt; 10<sup><i>k</i>+1</sup>.
+     *
+     * <p>The result is correct when -2_956_395 &le; {@code e} &le; 2_500_325. Otherwise the result
+     * is undefined.
+     *
+     * @param e The exponent of 2, which should meet -2_956_395 &le; {@code e} &le; 2_500_325 for
+     *     safe results.
+     * @return &lfloor;log<sub>10</sub>(3/4 &middot; 2<sup>{@code e}</sup>)&rfloor;.
+     */
+    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> &le; 10<sup>{@code
+     * e}</sup> &lt; 2<sup><i>k</i>+1</sup>.
+     *
+     * <p>The result is correct when |{@code e}| &le; 1_838_394. Otherwise the result is undefined.
+     *
+     * @param e The exponent of 10, which should meet |{@code e}| &le; 1_838_394 for safe results.
+     * @return &lfloor;log<sub>2</sub>10<sup>{@code e}</sup>&rfloor;.
+     */
+    static int flog2pow10(int e) {
+        return (int) ((e * C_2) >> Q_2);
+    }
+
+    /**
+     * Let 10<sup>-{@code k}</sup> = <i>&beta;</i> 2<sup><i>r</i></sup>, for the unique pair of
+     * integer <i>r</i> and real <i>&beta;</i> meeting 2<sup>125</sup> &le; <i>&beta;</i> &lt;
+     * 2<sup>126</sup>. Further, let <i>g</i> = &lfloor;<i>&beta;</i>&rfloor; + 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> = &lfloor;<i>g</i> 2<sup>-63</sup>&rfloor; 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} &le; {@code e} &le; {@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} &le; {@code e} &le; {@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];
+    }
+
+    // a Java port of
+    // https://github.com/plokhotnyuk/jsoniter-scala/blob/c70a293ac802dc2eb44165471d76d7df2d4657b6/jsoniter-scala-core/native/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala#L2027
+    static long multiplyHigh(long x, long y) {
+        // Karatsuba technique for two positive ints
+        long x2 = x & 0xFFFFFFFFL;
+        long y2 = y & 0xFFFFFFFFL;
+        long b = x2 * y2;
+        long x1 = x >>> 32;
+        long y1 = y >>> 32;
+        long a = x1 * y1;
+        return (((b >>> 32) + (x1 + x2) * (y1 + y2) - b - a) >>> 32) + a;
+    }
+
+    /*
+    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 -Nru rhino-1.7.15/src/org/mozilla/javascript/DToA.java rhino-1.7.15.1/src/org/mozilla/javascript/DToA.java
--- rhino-1.7.15/src/org/mozilla/javascript/DToA.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/DToA.java	2025-12-03 05:43:04.000000000 +0200
@@ -32,14 +32,6 @@
         return (char) ((digit >= 10) ? 'a' - 10 + digit : '0' + digit);
     }
 
-    static final int DTOSTR_STANDARD = 0, /* Either fixed or exponential format; round-trip */
-            DTOSTR_STANDARD_EXPONENTIAL = 1, /* Always exponential format; round-trip */
-            DTOSTR_FIXED =
-                    2, /* Round to <precision> digits after the decimal point; exponential if number is large */
-            DTOSTR_EXPONENTIAL = 3, /* Always exponential format; <precision> significant digits */
-            DTOSTR_PRECISION =
-                    4; /* Either fixed or exponential format; <precision> significant digits */
-
     private static final int Frac_mask = 0xfffff;
     private static final int Exp_shift = 20;
     private static final int Exp_msk1 = 0x100000;
@@ -335,816 +327,4 @@
 
         return buffer.toString();
     }
-
-    /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
-     *
-     * Inspired by "How to Print Floating-Point Numbers Accurately" by
-     * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
-     *
-     * Modifications:
-     *  1. Rather than iterating, we use a simple numeric overestimate
-     *     to determine k = floor(log10(d)).  We scale relevant
-     *     quantities using O(log2(k)) rather than O(k) multiplications.
-     *  2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
-     *     try to generate digits strictly left to right.  Instead, we
-     *     compute with fewer bits and propagate the carry if necessary
-     *     when rounding the final digit up.  This is often faster.
-     *  3. Under the assumption that input will be rounded nearest,
-     *     mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
-     *     That is, we allow equality in stopping tests when the
-     *     round-nearest rule will give the same floating-point value
-     *     as would satisfaction of the stopping test with strict
-     *     inequality.
-     *  4. We remove common factors of powers of 2 from relevant
-     *     quantities.
-     *  5. When converting floating-point integers less than 1e16,
-     *     we use floating-point arithmetic rather than resorting
-     *     to multiple-precision integers.
-     *  6. When asked to produce fewer than 15 digits, we first try
-     *     to get by with floating-point arithmetic; we resort to
-     *     multiple-precision integer arithmetic only if we cannot
-     *     guarantee that the floating-point calculation has given
-     *     the correctly rounded result.  For k requested digits and
-     *     "uniformly" distributed input, the probability is
-     *     something like 10^(k-15) that we must resort to the Long
-     *     calculation.
-     */
-
-    static int word0(double d) {
-        long dBits = Double.doubleToLongBits(d);
-        return (int) (dBits >> 32);
-    }
-
-    static double setWord0(double d, int i) {
-        long dBits = Double.doubleToLongBits(d);
-        dBits = ((long) i << 32) | (dBits & 0x0FFFFFFFFL);
-        return Double.longBitsToDouble(dBits);
-    }
-
-    static int word1(double d) {
-        long dBits = Double.doubleToLongBits(d);
-        return (int) (dBits);
-    }
-
-    /* Return b * 5^k.  k must be nonnegative. */
-    // XXXX the C version built a cache of these
-    static BigInteger pow5mult(BigInteger b, int k) {
-        return b.multiply(BigInteger.valueOf(5).pow(k));
-    }
-
-    static boolean roundOff(StringBuilder buf) {
-        int i = buf.length();
-        while (i != 0) {
-            --i;
-            char c = buf.charAt(i);
-            if (c != '9') {
-                buf.setCharAt(i, (char) (c + 1));
-                buf.setLength(i + 1);
-                return false;
-            }
-        }
-        buf.setLength(0);
-        return true;
-    }
-
-    /* Always emits at least one digit. */
-    /* If biasUp is set, then rounding in modes 2 and 3 will round away from zero
-     * when the number is exactly halfway between two representable values.  For example,
-     * rounding 2.5 to zero digits after the decimal point will return 3 and not 2.
-     * 2.49 will still round to 2, and 2.51 will still round to 3. */
-    /* bufsize should be at least 20 for modes 0 and 1.  For the other modes,
-     * bufsize should be two greater than the maximum number of output characters expected. */
-    static int JS_dtoa(
-            double d, int mode, boolean biasUp, int ndigits, boolean[] sign, StringBuilder buf) {
-        /*  Arguments ndigits, decpt, sign are similar to those
-            of ecvt and fcvt; trailing zeros are suppressed from
-            the returned string.  If not null, *rve is set to point
-            to the end of the return value.  If d is +-Infinity or NaN,
-            then *decpt is set to 9999.
-
-            mode:
-            0 ==> shortest string that yields d when read in
-            and rounded to nearest.
-            1 ==> like 0, but with Steele & White stopping rule;
-            e.g. with IEEE P754 arithmetic , mode 0 gives
-            1e23 whereas mode 1 gives 9.999999999999999e22.
-            2 ==> max(1,ndigits) significant digits.  This gives a
-            return value similar to that of ecvt, except
-            that trailing zeros are suppressed.
-            3 ==> through ndigits past the decimal point.  This
-            gives a return value similar to that from fcvt,
-            except that trailing zeros are suppressed, and
-            ndigits can be negative.
-            4-9 should give the same return values as 2-3, i.e.,
-            4 <= mode <= 9 ==> same return as mode
-            2 + (mode & 1).  These modes are mainly for
-            debugging; often they run slower but sometimes
-            faster than modes 2-3.
-            4,5,8,9 ==> left-to-right digit generation.
-            6-9 ==> don't try fast floating-point estimate
-            (if applicable).
-
-            Values of mode other than 0-9 are treated as mode 0.
-
-            Sufficient space is allocated to the return value
-            to hold the suppressed trailing zeros.
-        */
-
-        int b2, b5, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0, m2, m5, s2, s5;
-        char dig;
-        long L;
-        long x;
-        BigInteger b, b1, delta, mlo, mhi, S;
-        int[] be = new int[1];
-        int[] bbits = new int[1];
-        double d2, ds, eps;
-        boolean spec_case, denorm, k_check, try_quick, leftright;
-
-        if ((word0(d) & Sign_bit) != 0) {
-            /* set sign for everything, including 0's and NaNs */
-            sign[0] = true;
-            // word0(d) &= ~Sign_bit;  /* clear sign bit */
-            d = setWord0(d, word0(d) & ~Sign_bit);
-        } else sign[0] = false;
-
-        if ((word0(d) & Exp_mask) == Exp_mask) {
-            /* Infinity or NaN */
-            buf.append(((word1(d) == 0) && ((word0(d) & Frac_mask) == 0)) ? "Infinity" : "NaN");
-            return 9999;
-        }
-        if (d == 0) {
-            //          no_digits:
-            buf.setLength(0);
-            buf.append('0'); /* copy "0" to buffer */
-            return 1;
-        }
-
-        b = d2b(d, be, bbits);
-        if ((i = (word0(d) >>> Exp_shift1 & (Exp_mask >> Exp_shift1))) != 0) {
-            d2 = setWord0(d, (word0(d) & Frac_mask1) | Exp_11);
-            /* log(x)   ~=~ log(1.5) + (x-1.5)/1.5
-             * log10(x)  =  log(x) / log(10)
-             *      ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
-             * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
-             *
-             * This suggests computing an approximation k to log10(d) by
-             *
-             * k = (i - Bias)*0.301029995663981
-             *  + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
-             *
-             * We want k to be too large rather than too small.
-             * The error in the first-order Taylor series approximation
-             * is in our favor, so we just round up the constant enough
-             * to compensate for any error in the multiplication of
-             * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
-             * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
-             * adding 1e-13 to the constant term more than suffices.
-             * Hence we adjust the constant term to 0.1760912590558.
-             * (We could get a more accurate k by invoking log10,
-             *  but this is probably not worthwhile.)
-             */
-            i -= Bias;
-            denorm = false;
-        } else {
-            /* d is denormalized */
-            i = bbits[0] + be[0] + (Bias + (P - 1) - 1);
-            x =
-                    (i > 32)
-                            ? ((long) word0(d)) << (64 - i) | word1(d) >>> (i - 32)
-                            : ((long) word1(d)) << (32 - i);
-            //            d2 = x;
-            //            word0(d2) -= 31*Exp_msk1; /* adjust exponent */
-            d2 = setWord0(x, word0(x) - 31 * Exp_msk1);
-            i -= (Bias + (P - 1) - 1) + 1;
-            denorm = true;
-        }
-        /* At this point d = f*2^i, where 1 <= f < 2.  d2 is an approximation of f. */
-        ds = (d2 - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981;
-        k = (int) ds;
-        if (ds < 0.0 && ds != k) k--; /* want k = floor(ds) */
-        k_check = true;
-        if (k >= 0 && k <= Ten_pmax) {
-            if (d < tens[k]) k--;
-            k_check = false;
-        }
-        /* At this point floor(log10(d)) <= k <= floor(log10(d))+1.
-        If k_check is zero, we're guaranteed that k = floor(log10(d)). */
-        j = bbits[0] - i - 1;
-        /* At this point d = b/2^j, where b is an odd integer. */
-        if (j >= 0) {
-            b2 = 0;
-            s2 = j;
-        } else {
-            b2 = -j;
-            s2 = 0;
-        }
-        if (k >= 0) {
-            b5 = 0;
-            s5 = k;
-            s2 += k;
-        } else {
-            b2 -= k;
-            b5 = -k;
-            s5 = 0;
-        }
-        /* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer,
-        b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */
-        if (mode < 0 || mode > 9) mode = 0;
-        try_quick = true;
-        if (mode > 5) {
-            mode -= 4;
-            try_quick = false;
-        }
-        leftright = true;
-        ilim = ilim1 = 0;
-        switch (mode) {
-            case 0:
-            case 1:
-                ilim = ilim1 = -1;
-                i = 18;
-                ndigits = 0;
-                break;
-            case 2:
-                leftright = false;
-                /* fall through */
-            case 4:
-                if (ndigits <= 0) ndigits = 1;
-                ilim = ilim1 = i = ndigits;
-                break;
-            case 3:
-                leftright = false;
-                /* fall through */
-            case 5:
-                i = ndigits + k + 1;
-                ilim = i;
-                ilim1 = i - 1;
-                if (i <= 0) i = 1;
-        }
-        /* ilim is the maximum number of significant digits we want, based on k and ndigits. */
-        /* ilim1 is the maximum number of significant digits we want, based on k and ndigits,
-        when it turns out that k was computed too high by one. */
-
-        boolean fast_failed = false;
-        if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
-            /* Try to get by with floating-point arithmetic. */
-
-            i = 0;
-            d2 = d;
-            k0 = k;
-            ilim0 = ilim;
-            ieps = 2; /* conservative */
-            /* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */
-            if (k > 0) {
-                ds = tens[k & 0xf];
-                j = k >> 4;
-                if ((j & Bletch) != 0) {
-                    /* prevent overflows */
-                    j &= Bletch - 1;
-                    d /= bigtens[n_bigtens - 1];
-                    ieps++;
-                }
-                for (; (j != 0); j >>= 1, i++)
-                    if ((j & 1) != 0) {
-                        ieps++;
-                        ds *= bigtens[i];
-                    }
-                d /= ds;
-            } else if ((j1 = -k) != 0) {
-                d *= tens[j1 & 0xf];
-                for (j = j1 >> 4; (j != 0); j >>= 1, i++)
-                    if ((j & 1) != 0) {
-                        ieps++;
-                        d *= bigtens[i];
-                    }
-            }
-            /* Check that k was computed correctly. */
-            if (k_check && d < 1.0 && ilim > 0) {
-                if (ilim1 <= 0) fast_failed = true;
-                else {
-                    ilim = ilim1;
-                    k--;
-                    d *= 10.;
-                    ieps++;
-                }
-            }
-            /* eps bounds the cumulative error. */
-            //            eps = ieps*d + 7.0;
-            //            word0(eps) -= (P-1)*Exp_msk1;
-            eps = ieps * d + 7.0;
-            eps = setWord0(eps, word0(eps) - (P - 1) * Exp_msk1);
-            if (ilim == 0) {
-                S = mhi = null;
-                d -= 5.0;
-                if (d > eps) {
-                    buf.append('1');
-                    k++;
-                    return k + 1;
-                }
-                if (d < -eps) {
-                    buf.setLength(0);
-                    buf.append('0'); /* copy "0" to buffer */
-                    return 1;
-                }
-                fast_failed = true;
-            }
-            if (!fast_failed) {
-                fast_failed = true;
-                if (leftright) {
-                    /* Use Steele & White method of only
-                     * generating digits needed.
-                     */
-                    eps = 0.5 / tens[ilim - 1] - eps;
-                    for (i = 0; ; ) {
-                        L = (long) d;
-                        d -= L;
-                        buf.append((char) ('0' + L));
-                        if (d < eps) {
-                            return k + 1;
-                        }
-                        if (1.0 - d < eps) {
-                            //                            goto bump_up;
-                            char lastCh;
-                            while (true) {
-                                lastCh = buf.charAt(buf.length() - 1);
-                                buf.setLength(buf.length() - 1);
-                                if (lastCh != '9') break;
-                                if (buf.length() == 0) {
-                                    k++;
-                                    lastCh = '0';
-                                    break;
-                                }
-                            }
-                            buf.append((char) (lastCh + 1));
-                            return k + 1;
-                        }
-                        if (++i >= ilim) break;
-                        eps *= 10.0;
-                        d *= 10.0;
-                    }
-                } else {
-                    /* Generate ilim digits, then fix them up. */
-                    eps *= tens[ilim - 1];
-                    for (i = 1; ; i++, d *= 10.0) {
-                        L = (long) d;
-                        d -= L;
-                        buf.append((char) ('0' + L));
-                        if (i == ilim) {
-                            if (d > 0.5 + eps) {
-                                //                                goto bump_up;
-                                char lastCh;
-                                while (true) {
-                                    lastCh = buf.charAt(buf.length() - 1);
-                                    buf.setLength(buf.length() - 1);
-                                    if (lastCh != '9') break;
-                                    if (buf.length() == 0) {
-                                        k++;
-                                        lastCh = '0';
-                                        break;
-                                    }
-                                }
-                                buf.append((char) (lastCh + 1));
-                                return k + 1;
-                            } else if (d < 0.5 - eps) {
-                                stripTrailingZeroes(buf);
-                                //                                    while(*--s == '0') ;
-                                //                                    s++;
-                                return k + 1;
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
-            if (fast_failed) {
-                buf.setLength(0);
-                d = d2;
-                k = k0;
-                ilim = ilim0;
-            }
-        }
-
-        /* Do we have a "small" integer? */
-
-        if (be[0] >= 0 && k <= Int_max) {
-            /* Yes. */
-            ds = tens[k];
-            if (ndigits < 0 && ilim <= 0) {
-                S = mhi = null;
-                if (ilim < 0 || d < 5 * ds || (!biasUp && d == 5 * ds)) {
-                    buf.setLength(0);
-                    buf.append('0'); /* copy "0" to buffer */
-                    return 1;
-                }
-                buf.append('1');
-                k++;
-                return k + 1;
-            }
-            for (i = 1; ; i++) {
-                L = (long) (d / ds);
-                d -= L * ds;
-                buf.append((char) ('0' + L));
-                if (i == ilim) {
-                    d += d;
-                    if ((d > ds) || (d == ds && (((L & 1) != 0) || biasUp))) {
-                        //                    bump_up:
-                        //                        while(*--s == '9')
-                        //                            if (s == buf) {
-                        //                                k++;
-                        //                                *s = '0';
-                        //                                break;
-                        //                            }
-                        //                        ++*s++;
-                        char lastCh;
-                        while (true) {
-                            lastCh = buf.charAt(buf.length() - 1);
-                            buf.setLength(buf.length() - 1);
-                            if (lastCh != '9') break;
-                            if (buf.length() == 0) {
-                                k++;
-                                lastCh = '0';
-                                break;
-                            }
-                        }
-                        buf.append((char) (lastCh + 1));
-                    }
-                    break;
-                }
-                d *= 10.0;
-                if (d == 0) break;
-            }
-            return k + 1;
-        }
-
-        m2 = b2;
-        m5 = b5;
-        mhi = mlo = null;
-        if (leftright) {
-            if (mode < 2) {
-                i = (denorm) ? be[0] + (Bias + (P - 1) - 1 + 1) : 1 + P - bbits[0];
-                /* i is 1 plus the number of trailing zero bits in d's significand. Thus,
-                (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */
-            } else {
-                j = ilim - 1;
-                if (m5 >= j) m5 -= j;
-                else {
-                    s5 += j -= m5;
-                    b5 += j;
-                    m5 = 0;
-                }
-                if ((i = ilim) < 0) {
-                    m2 -= i;
-                    i = 0;
-                }
-                /* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */
-            }
-            b2 += i;
-            s2 += i;
-            mhi = BigInteger.valueOf(1);
-            /* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or
-            input (when mode < 2) significant digit, divided by 10^k. */
-        }
-        /* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5).  Reduce common factors in
-        b2, m2, and s2 without changing the equalities. */
-        if (m2 > 0 && s2 > 0) {
-            i = (m2 < s2) ? m2 : s2;
-            b2 -= i;
-            m2 -= i;
-            s2 -= i;
-        }
-
-        /* Fold b5 into b and m5 into mhi. */
-        if (b5 > 0) {
-            if (leftright) {
-                if (m5 > 0) {
-                    mhi = pow5mult(mhi, m5);
-                    b1 = mhi.multiply(b);
-                    b = b1;
-                }
-                if ((j = b5 - m5) != 0) b = pow5mult(b, j);
-            } else b = pow5mult(b, b5);
-        }
-        /* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and
-        (mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */
-
-        S = BigInteger.valueOf(1);
-        if (s5 > 0) S = pow5mult(S, s5);
-        /* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and
-        (mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */
-
-        /* Check for special case that d is a normalized power of 2. */
-        spec_case = false;
-        if (mode < 2) {
-            if ((word1(d) == 0)
-                    && ((word0(d) & Bndry_mask) == 0)
-                    && ((word0(d) & (Exp_mask & Exp_mask << 1)) != 0)) {
-                /* The special case.  Here we want to be within a quarter of the last input
-                significant digit instead of one half of it when the decimal output string's value is less than d.  */
-                b2 += Log2P;
-                s2 += Log2P;
-                spec_case = true;
-            }
-        }
-
-        /* Arrange for convenient computation of quotients:
-         * shift left if necessary so divisor has 4 leading 0 bits.
-         *
-         * Perhaps we should just compute leading 28 bits of S once
-         * and for all and pass them and a shift to quorem, so it
-         * can do shifts and ors to compute the numerator for q.
-         */
-        byte[] S_bytes = S.toByteArray();
-        int S_hiWord = 0;
-        for (int idx = 0; idx < 4; idx++) {
-            S_hiWord = (S_hiWord << 8);
-            if (idx < S_bytes.length) S_hiWord |= (S_bytes[idx] & 0xFF);
-        }
-        if ((i = (((s5 != 0) ? 32 - hi0bits(S_hiWord) : 1) + s2) & 0x1f) != 0) i = 32 - i;
-        /* i is the number of leading zero bits in the most significant word of S*2^s2. */
-        if (i > 4) {
-            i -= 4;
-            b2 += i;
-            m2 += i;
-            s2 += i;
-        } else if (i < 4) {
-            i += 28;
-            b2 += i;
-            m2 += i;
-            s2 += i;
-        }
-        /* Now S*2^s2 has exactly four leading zero bits in its most significant word. */
-        if (b2 > 0) b = b.shiftLeft(b2);
-        if (s2 > 0) S = S.shiftLeft(s2);
-        /* Now we have d/10^k = b/S and
-        (mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */
-        if (k_check) {
-            if (b.compareTo(S) < 0) {
-                k--;
-                b = b.multiply(BigInteger.valueOf(10)); /* we botched the k estimate */
-                if (leftright) mhi = mhi.multiply(BigInteger.valueOf(10));
-                ilim = ilim1;
-            }
-        }
-        /* At this point 1 <= d/10^k = b/S < 10. */
-
-        if (ilim <= 0 && mode > 2) {
-            /* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode.
-            Output either zero or the minimum nonzero output depending on which is closer to d. */
-            if ((ilim < 0)
-                    || ((i = b.compareTo(S = S.multiply(BigInteger.valueOf(5)))) < 0)
-                    || ((i == 0 && !biasUp))) {
-                /* Always emit at least one digit.  If the number appears to be zero
-                using the current mode, then emit one '0' digit and set decpt to 1. */
-                /*no_digits:
-                k = -1 - ndigits;
-                goto ret; */
-                buf.setLength(0);
-                buf.append('0'); /* copy "0" to buffer */
-                return 1;
-                //                goto no_digits;
-            }
-            //        one_digit:
-            buf.append('1');
-            k++;
-            return k + 1;
-        }
-        if (leftright) {
-            if (m2 > 0) mhi = mhi.shiftLeft(m2);
-
-            /* Compute mlo -- check for special case
-             * that d is a normalized power of 2.
-             */
-
-            mlo = mhi;
-            if (spec_case) {
-                mhi = mlo;
-                mhi = mhi.shiftLeft(Log2P);
-            }
-            /* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */
-            /* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */
-
-            for (i = 1; ; i++) {
-                BigInteger[] divResult = b.divideAndRemainder(S);
-                b = divResult[1];
-                dig = (char) (divResult[0].intValue() + '0');
-                /* Do we yet have the shortest decimal string
-                 * that will round to d?
-                 */
-                j = b.compareTo(mlo);
-                /* j is b/S compared with mlo/S. */
-                delta = S.subtract(mhi);
-                j1 = (delta.signum() <= 0) ? 1 : b.compareTo(delta);
-                /* j1 is b/S compared with 1 - mhi/S. */
-                if ((j1 == 0) && (mode == 0) && ((word1(d) & 1) == 0)) {
-                    if (dig == '9') {
-                        buf.append('9');
-                        if (roundOff(buf)) {
-                            k++;
-                            buf.append('1');
-                        }
-                        return k + 1;
-                        //                        goto round_9_up;
-                    }
-                    if (j > 0) dig++;
-                    buf.append(dig);
-                    return k + 1;
-                }
-                if ((j < 0) || ((j == 0) && (mode == 0) && ((word1(d) & 1) == 0))) {
-                    if (j1 > 0) {
-                        /* Either dig or dig+1 would work here as the least significant decimal digit.
-                        Use whichever would produce a decimal value closer to d. */
-                        b = b.shiftLeft(1);
-                        j1 = b.compareTo(S);
-                        if (((j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp)))
-                                && (dig++ == '9')) {
-                            buf.append('9');
-                            if (roundOff(buf)) {
-                                k++;
-                                buf.append('1');
-                            }
-                            return k + 1;
-                            //                                goto round_9_up;
-                        }
-                    }
-                    buf.append(dig);
-                    return k + 1;
-                }
-                if (j1 > 0) {
-                    if (dig == '9') {
-                        /* possible if i == 1 */
-                        //                    round_9_up:
-                        //                        *s++ = '9';
-                        //                        goto roundoff;
-                        buf.append('9');
-                        if (roundOff(buf)) {
-                            k++;
-                            buf.append('1');
-                        }
-                        return k + 1;
-                    }
-                    buf.append((char) (dig + 1));
-                    return k + 1;
-                }
-                buf.append(dig);
-                if (i == ilim) break;
-                b = b.multiply(BigInteger.valueOf(10));
-                if (mlo == mhi) mlo = mhi = mhi.multiply(BigInteger.valueOf(10));
-                else {
-                    mlo = mlo.multiply(BigInteger.valueOf(10));
-                    mhi = mhi.multiply(BigInteger.valueOf(10));
-                }
-            }
-        } else
-            for (i = 1; ; i++) {
-                //                (char)(dig = quorem(b,S) + '0');
-                BigInteger[] divResult = b.divideAndRemainder(S);
-                b = divResult[1];
-                dig = (char) (divResult[0].intValue() + '0');
-                buf.append(dig);
-                if (i >= ilim) break;
-                b = b.multiply(BigInteger.valueOf(10));
-            }
-
-        /* Round off last digit */
-
-        b = b.shiftLeft(1);
-        j = b.compareTo(S);
-        if ((j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp))) {
-            //        roundoff:
-            //            while(*--s == '9')
-            //                if (s == buf) {
-            //                    k++;
-            //                    *s++ = '1';
-            //                    goto ret;
-            //                }
-            //            ++*s++;
-            if (roundOff(buf)) {
-                k++;
-                buf.append('1');
-                return k + 1;
-            }
-        } else {
-            stripTrailingZeroes(buf);
-            //            while(*--s == '0') ;
-            //            s++;
-        }
-        //      ret:
-        //        Bfree(S);
-        //        if (mhi) {
-        //            if (mlo && mlo != mhi)
-        //                Bfree(mlo);
-        //            Bfree(mhi);
-        //        }
-        //      ret1:
-        //        Bfree(b);
-        //        JS_ASSERT(s < buf + bufsize);
-        return k + 1;
-    }
-
-    private static void stripTrailingZeroes(StringBuilder buf) {
-        //      while(*--s == '0') ;
-        //      s++;
-        int bl = buf.length();
-        while (bl-- > 0 && buf.charAt(bl) == '0') {
-            // empty
-        }
-        buf.setLength(bl + 1);
-    }
-
-    /* Mapping of JSDToStrMode -> JS_dtoa mode */
-    private static final int[] dtoaModes = {
-        0, /* DTOSTR_STANDARD */ 0, /* DTOSTR_STANDARD_EXPONENTIAL, */ 3, /* DTOSTR_FIXED, */
-        2, /* DTOSTR_EXPONENTIAL, */ 2
-    }; /* DTOSTR_PRECISION */
-
-    static void JS_dtostr(StringBuilder buffer, int mode, int precision, double d) {
-        int decPt; /* Position of decimal point relative to first digit returned by JS_dtoa */
-        boolean[] sign = new boolean[1]; /* true if the sign bit was set in d */
-        int nDigits; /* Number of significand digits returned by JS_dtoa */
-
-        //        JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL ?
-        // DTOSTR_STANDARD_BUFFER_SIZE :
-        //                DTOSTR_VARIABLE_BUFFER_SIZE(precision)));
-
-        if (mode == DTOSTR_FIXED && (d >= 1e21 || d <= -1e21))
-            mode =
-                    DTOSTR_STANDARD; /* Change mode here rather than below because the buffer may not be large enough to hold a large integer. */
-
-        decPt = JS_dtoa(d, dtoaModes[mode], mode >= DTOSTR_FIXED, precision, sign, buffer);
-        nDigits = buffer.length();
-
-        /* If Infinity, -Infinity, or NaN, return the string regardless of the mode. */
-        if (decPt != 9999) {
-            boolean exponentialNotation = false;
-            int minNDigits =
-                    0; /* Minimum number of significand digits required by mode and precision */
-            int p;
-
-            switch (mode) {
-                case DTOSTR_STANDARD:
-                    if (decPt < -5 || decPt > 21) exponentialNotation = true;
-                    else minNDigits = decPt;
-                    break;
-
-                case DTOSTR_FIXED:
-                    if (precision >= 0) minNDigits = decPt + precision;
-                    else minNDigits = decPt;
-                    break;
-
-                case DTOSTR_EXPONENTIAL:
-                    //                    JS_ASSERT(precision > 0);
-                    minNDigits = precision;
-                    /* fall through */
-                case DTOSTR_STANDARD_EXPONENTIAL:
-                    exponentialNotation = true;
-                    break;
-
-                case DTOSTR_PRECISION:
-                    //                    JS_ASSERT(precision > 0);
-                    minNDigits = precision;
-                    if (decPt < -5 || decPt > precision) exponentialNotation = true;
-                    break;
-            }
-
-            /* If the number has fewer than minNDigits, pad it with zeros at the end */
-            if (nDigits < minNDigits) {
-                p = minNDigits;
-                nDigits = minNDigits;
-                do {
-                    buffer.append('0');
-                } while (buffer.length() != p);
-            }
-
-            if (exponentialNotation) {
-                /* Insert a decimal point if more than one significand digit */
-                if (nDigits != 1) {
-                    buffer.insert(1, '.');
-                }
-                buffer.append('e');
-                if ((decPt - 1) >= 0) buffer.append('+');
-                buffer.append(decPt - 1);
-                //                JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d",
-                // decPt-1);
-            } else if (decPt != nDigits) {
-                /* Some kind of a fraction in fixed notation */
-                //                JS_ASSERT(decPt <= nDigits);
-                if (decPt > 0) {
-                    /* dd...dd . dd...dd */
-                    buffer.insert(decPt, '.');
-                } else {
-                    /* 0 . 00...00dd...dd */
-                    for (int i = 0; i < 1 - decPt; i++) buffer.insert(0, '0');
-                    buffer.insert(1, '.');
-                }
-            }
-        }
-
-        /* If negative and neither -0.0 nor NaN, output a leading '-'. */
-        if (sign[0]
-                && !(word0(d) == Sign_bit && word1(d) == 0)
-                && !((word0(d) & Exp_mask) == Exp_mask
-                        && ((word1(d) != 0) || ((word0(d) & Frac_mask) != 0)))) {
-            buffer.insert(0, '-');
-        }
-    }
 }
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/NativeNumber.java rhino-1.7.15.1/src/org/mozilla/javascript/NativeNumber.java
--- rhino-1.7.15/src/org/mozilla/javascript/NativeNumber.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/NativeNumber.java	2025-12-03 05:43:04.000000000 +0200
@@ -6,6 +6,8 @@
 
 package org.mozilla.javascript;
 
+import org.mozilla.javascript.dtoa.DecimalFormatter;
+
 /**
  * This class implements the Number native object.
  *
@@ -156,49 +158,13 @@
                 return ScriptRuntime.wrapNumber(value);
 
             case Id_toFixed:
-                int precisionMin = cx.version < Context.VERSION_ES6 ? -20 : 0;
-                return num_to(value, args, DToA.DTOSTR_FIXED, DToA.DTOSTR_FIXED, precisionMin, 0);
+                return js_toFixed(cx, value, args);
 
             case Id_toExponential:
-                {
-                    // Handle special values before range check
-                    if (Double.isNaN(value)) {
-                        return "NaN";
-                    }
-                    if (Double.isInfinite(value)) {
-                        if (value >= 0) {
-                            return "Infinity";
-                        }
-                        return "-Infinity";
-                    }
-                    // General case
-                    return num_to(
-                            value,
-                            args,
-                            DToA.DTOSTR_STANDARD_EXPONENTIAL,
-                            DToA.DTOSTR_EXPONENTIAL,
-                            0,
-                            1);
-                }
+                return js_toExponential(value, args);
 
             case Id_toPrecision:
-                {
-                    // Undefined precision, fall back to ToString()
-                    if (args.length == 0 || Undefined.isUndefined(args[0])) {
-                        return ScriptRuntime.numberToString(value, 10);
-                    }
-                    // Handle special values before range check
-                    if (Double.isNaN(value)) {
-                        return "NaN";
-                    }
-                    if (Double.isInfinite(value)) {
-                        if (value >= 0) {
-                            return "Infinity";
-                        }
-                        return "-Infinity";
-                    }
-                    return num_to(value, args, DToA.DTOSTR_STANDARD, DToA.DTOSTR_PRECISION, 1, 0);
-                }
+                return js_toPrecision(value, args);
 
             default:
                 throw new IllegalArgumentException(String.valueOf(id));
@@ -249,37 +215,75 @@
         }
     }
 
-    @Override
-    public String toString() {
-        return ScriptRuntime.numberToString(doubleValue, 10);
+    private static Object js_toFixed(Context cx, double value, Object[] args) {
+        int fractionDigits;
+        if (args.length > 0 && !Undefined.isUndefined(args[0])) {
+            double p = ScriptRuntime.toInteger(args[0]);
+            int precisionMin = cx.version < Context.VERSION_ES6 ? -20 : 0;
+            /* We allow a larger range of precision than
+            ECMA requires; this is permitted by ECMA. */
+            checkPrecision(p, precisionMin, args[0]);
+            fractionDigits = ScriptRuntime.toInt32(p);
+        } else {
+            fractionDigits = 0;
+        }
+
+        if (!Double.isFinite(value)) {
+            return ScriptRuntime.toString(value);
+        }
+        return DecimalFormatter.toFixed(value, fractionDigits);
     }
 
-    private static String num_to(
-            double val,
-            Object[] args,
-            int zeroArgMode,
-            int oneArgMode,
-            int precisionMin,
-            int precisionOffset) {
-        int precision;
-        if (args.length == 0) {
-            precision = 0;
-            oneArgMode = zeroArgMode;
+    private static Object js_toExponential(double value, Object[] args) {
+        double p;
+        boolean wasUndefined;
+        if (args.length > 0 && !Undefined.isUndefined(args[0])) {
+            wasUndefined = false;
+            p = ScriptRuntime.toInteger(args[0]);
         } else {
-            /* We allow a larger range of precision than
-            ECMA requires; this is permitted by ECMA. */
-            double p = ScriptRuntime.toInteger(args[0]);
-            if (p < precisionMin || p > MAX_PRECISION) {
-                String msg =
-                        ScriptRuntime.getMessageById(
-                                "msg.bad.precision", ScriptRuntime.toString(args[0]));
-                throw ScriptRuntime.rangeError(msg);
-            }
-            precision = ScriptRuntime.toInt32(p);
+            wasUndefined = true;
+            p = 0.0;
         }
-        StringBuilder sb = new StringBuilder();
-        DToA.JS_dtostr(sb, oneArgMode, precision + precisionOffset, val);
-        return sb.toString();
+
+        if (!Double.isFinite(value)) {
+            return ScriptRuntime.toString(value);
+        }
+        checkPrecision(p, 0.0, args.length > 0 ? args[0] : Undefined.instance);
+
+        // Trigger the special handling for undefined, which requires that
+        // we hold off on this bit until the checks above,.
+        int fractionDigits = wasUndefined ? -1 : ScriptRuntime.toInt32(p);
+
+        return DecimalFormatter.toExponential(value, fractionDigits);
+    }
+
+    private static Object js_toPrecision(double value, Object[] args) {
+        // Undefined precision, fall back to ToString()
+        if (args.length == 0 || Undefined.isUndefined(args[0])) {
+            return ScriptRuntime.toString(value);
+        }
+
+        double p = ScriptRuntime.toInteger(args[0]);
+        if (!Double.isFinite(value)) {
+            return ScriptRuntime.toString(value);
+        }
+        checkPrecision(p, 1.0, args[0]);
+        int precision = ScriptRuntime.toInt32(p);
+
+        return DecimalFormatter.toPrecision(value, precision);
+    }
+
+    private static void checkPrecision(double p, double min, Object arg) {
+        if (p < min || p > MAX_PRECISION) {
+            String msg =
+                    ScriptRuntime.getMessageById("msg.bad.precision", ScriptRuntime.toString(arg));
+            throw ScriptRuntime.rangeError(msg);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return ScriptRuntime.numberToString(doubleValue, 10);
     }
 
     static Object isFinite(Object val) {
@@ -309,7 +313,7 @@
     }
 
     private static boolean isDoubleInteger(double d) {
-        return !Double.isInfinite(d) && !Double.isNaN(d) && (Math.floor(d) == d);
+        return Double.isFinite(d) && (Math.floor(d) == d);
     }
 
     private static boolean isSafeInteger(Number val) {
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/ScriptRuntime.java rhino-1.7.15.1/src/org/mozilla/javascript/ScriptRuntime.java
--- rhino-1.7.15/src/org/mozilla/javascript/ScriptRuntime.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/ScriptRuntime.java	2025-12-03 05:43:04.000000000 +0200
@@ -18,8 +18,8 @@
 import java.util.ResourceBundle;
 import java.util.function.BiConsumer;
 import org.mozilla.javascript.ast.FunctionNode;
+import org.mozilla.javascript.dtoa.DoubleFormatter;
 import org.mozilla.javascript.v8dtoa.DoubleConversion;
-import org.mozilla.javascript.v8dtoa.FastDtoa;
 import org.mozilla.javascript.xml.XMLLib;
 import org.mozilla.javascript.xml.XMLObject;
 
@@ -1061,27 +1061,20 @@
     }
 
     public static String numberToString(double d, int base) {
+        if (base == 10) {
+            // Common case: DoubleFormatter efficiently identifies non-finite
+            // numbers. Do this before other checks.
+            return DoubleFormatter.toString(d);
+        }
+
         if ((base < 2) || (base > 36)) {
             throw Context.reportRuntimeErrorById("msg.bad.radix", Integer.toString(base));
         }
-
         if (Double.isNaN(d)) return "NaN";
         if (d == Double.POSITIVE_INFINITY) return "Infinity";
         if (d == Double.NEGATIVE_INFINITY) return "-Infinity";
         if (d == 0.0) return "0";
-
-        if (base != 10) {
-            return DToA.JS_dtobasestr(base, d);
-        }
-        // V8 FastDtoa can't convert all numbers, so try it first but
-        // fall back to old DToA in case it fails
-        String result = FastDtoa.numberToString(d);
-        if (result != null) {
-            return result;
-        }
-        StringBuilder buffer = new StringBuilder();
-        DToA.JS_dtostr(buffer, DToA.DTOSTR_STANDARD, 0, d);
-        return buffer.toString();
+        return DToA.JS_dtobasestr(base, d);
     }
 
     public static String bigIntToString(BigInteger n, int base) {
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/CachedPowers.java rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/CachedPowers.java
--- rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/CachedPowers.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/CachedPowers.java	1970-01-01 02:00:00.000000000 +0200
@@ -1,157 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Ported to Java from Mozilla's version of V8-dtoa by Hannes Wallnoefer.
-// The original revision was 67d1049b0bf9 from the mozilla-central tree.
-
-package org.mozilla.javascript.v8dtoa;
-
-public class CachedPowers {
-
-    static final double kD_1_LOG2_10 = 0.30102999566398114; //  1 / lg(10)
-
-    static class CachedPower {
-        long significand;
-        short binaryExponent;
-        short decimalExponent;
-
-        CachedPower(long significand, short binaryExponent, short decimalExponent) {
-            this.significand = significand;
-            this.binaryExponent = binaryExponent;
-            this.decimalExponent = decimalExponent;
-        }
-    }
-
-    static int getCachedPower(int e, int alpha, int gamma, DiyFp c_mk) {
-        int kQ = DiyFp.kSignificandSize;
-        double k = Math.ceil((alpha - e + kQ - 1) * kD_1_LOG2_10);
-        int index = (GRISU_CACHE_OFFSET + (int) k - 1) / CACHED_POWERS_SPACING + 1;
-        CachedPower cachedPower = CACHED_POWERS[index];
-
-        c_mk.setF(cachedPower.significand);
-        c_mk.setE(cachedPower.binaryExponent);
-        assert ((alpha <= c_mk.e() + e) && (c_mk.e() + e <= gamma));
-        return cachedPower.decimalExponent;
-    }
-
-    // Code below is converted from GRISU_CACHE_NAME(8) in file "powers-ten.h"
-    // Regexp to convert this from original C++ source:
-    // \{GRISU_UINT64_C\((\w+), (\w+)\), (\-?\d+), (\-?\d+)\}
-
-    // interval between entries  of the powers cache below
-    static final int CACHED_POWERS_SPACING = 8;
-
-    static final CachedPower[] CACHED_POWERS = {
-        new CachedPower(0xe61acf033d1a45dfL, (short) -1087, (short) -308),
-        new CachedPower(0xab70fe17c79ac6caL, (short) -1060, (short) -300),
-        new CachedPower(0xff77b1fcbebcdc4fL, (short) -1034, (short) -292),
-        new CachedPower(0xbe5691ef416bd60cL, (short) -1007, (short) -284),
-        new CachedPower(0x8dd01fad907ffc3cL, (short) -980, (short) -276),
-        new CachedPower(0xd3515c2831559a83L, (short) -954, (short) -268),
-        new CachedPower(0x9d71ac8fada6c9b5L, (short) -927, (short) -260),
-        new CachedPower(0xea9c227723ee8bcbL, (short) -901, (short) -252),
-        new CachedPower(0xaecc49914078536dL, (short) -874, (short) -244),
-        new CachedPower(0x823c12795db6ce57L, (short) -847, (short) -236),
-        new CachedPower(0xc21094364dfb5637L, (short) -821, (short) -228),
-        new CachedPower(0x9096ea6f3848984fL, (short) -794, (short) -220),
-        new CachedPower(0xd77485cb25823ac7L, (short) -768, (short) -212),
-        new CachedPower(0xa086cfcd97bf97f4L, (short) -741, (short) -204),
-        new CachedPower(0xef340a98172aace5L, (short) -715, (short) -196),
-        new CachedPower(0xb23867fb2a35b28eL, (short) -688, (short) -188),
-        new CachedPower(0x84c8d4dfd2c63f3bL, (short) -661, (short) -180),
-        new CachedPower(0xc5dd44271ad3cdbaL, (short) -635, (short) -172),
-        new CachedPower(0x936b9fcebb25c996L, (short) -608, (short) -164),
-        new CachedPower(0xdbac6c247d62a584L, (short) -582, (short) -156),
-        new CachedPower(0xa3ab66580d5fdaf6L, (short) -555, (short) -148),
-        new CachedPower(0xf3e2f893dec3f126L, (short) -529, (short) -140),
-        new CachedPower(0xb5b5ada8aaff80b8L, (short) -502, (short) -132),
-        new CachedPower(0x87625f056c7c4a8bL, (short) -475, (short) -124),
-        new CachedPower(0xc9bcff6034c13053L, (short) -449, (short) -116),
-        new CachedPower(0x964e858c91ba2655L, (short) -422, (short) -108),
-        new CachedPower(0xdff9772470297ebdL, (short) -396, (short) -100),
-        new CachedPower(0xa6dfbd9fb8e5b88fL, (short) -369, (short) -92),
-        new CachedPower(0xf8a95fcf88747d94L, (short) -343, (short) -84),
-        new CachedPower(0xb94470938fa89bcfL, (short) -316, (short) -76),
-        new CachedPower(0x8a08f0f8bf0f156bL, (short) -289, (short) -68),
-        new CachedPower(0xcdb02555653131b6L, (short) -263, (short) -60),
-        new CachedPower(0x993fe2c6d07b7facL, (short) -236, (short) -52),
-        new CachedPower(0xe45c10c42a2b3b06L, (short) -210, (short) -44),
-        new CachedPower(0xaa242499697392d3L, (short) -183, (short) -36),
-        new CachedPower(0xfd87b5f28300ca0eL, (short) -157, (short) -28),
-        new CachedPower(0xbce5086492111aebL, (short) -130, (short) -20),
-        new CachedPower(0x8cbccc096f5088ccL, (short) -103, (short) -12),
-        new CachedPower(0xd1b71758e219652cL, (short) -77, (short) -4),
-        new CachedPower(0x9c40000000000000L, (short) -50, (short) 4),
-        new CachedPower(0xe8d4a51000000000L, (short) -24, (short) 12),
-        new CachedPower(0xad78ebc5ac620000L, (short) 3, (short) 20),
-        new CachedPower(0x813f3978f8940984L, (short) 30, (short) 28),
-        new CachedPower(0xc097ce7bc90715b3L, (short) 56, (short) 36),
-        new CachedPower(0x8f7e32ce7bea5c70L, (short) 83, (short) 44),
-        new CachedPower(0xd5d238a4abe98068L, (short) 109, (short) 52),
-        new CachedPower(0x9f4f2726179a2245L, (short) 136, (short) 60),
-        new CachedPower(0xed63a231d4c4fb27L, (short) 162, (short) 68),
-        new CachedPower(0xb0de65388cc8ada8L, (short) 189, (short) 76),
-        new CachedPower(0x83c7088e1aab65dbL, (short) 216, (short) 84),
-        new CachedPower(0xc45d1df942711d9aL, (short) 242, (short) 92),
-        new CachedPower(0x924d692ca61be758L, (short) 269, (short) 100),
-        new CachedPower(0xda01ee641a708deaL, (short) 295, (short) 108),
-        new CachedPower(0xa26da3999aef774aL, (short) 322, (short) 116),
-        new CachedPower(0xf209787bb47d6b85L, (short) 348, (short) 124),
-        new CachedPower(0xb454e4a179dd1877L, (short) 375, (short) 132),
-        new CachedPower(0x865b86925b9bc5c2L, (short) 402, (short) 140),
-        new CachedPower(0xc83553c5c8965d3dL, (short) 428, (short) 148),
-        new CachedPower(0x952ab45cfa97a0b3L, (short) 455, (short) 156),
-        new CachedPower(0xde469fbd99a05fe3L, (short) 481, (short) 164),
-        new CachedPower(0xa59bc234db398c25L, (short) 508, (short) 172),
-        new CachedPower(0xf6c69a72a3989f5cL, (short) 534, (short) 180),
-        new CachedPower(0xb7dcbf5354e9beceL, (short) 561, (short) 188),
-        new CachedPower(0x88fcf317f22241e2L, (short) 588, (short) 196),
-        new CachedPower(0xcc20ce9bd35c78a5L, (short) 614, (short) 204),
-        new CachedPower(0x98165af37b2153dfL, (short) 641, (short) 212),
-        new CachedPower(0xe2a0b5dc971f303aL, (short) 667, (short) 220),
-        new CachedPower(0xa8d9d1535ce3b396L, (short) 694, (short) 228),
-        new CachedPower(0xfb9b7cd9a4a7443cL, (short) 720, (short) 236),
-        new CachedPower(0xbb764c4ca7a44410L, (short) 747, (short) 244),
-        new CachedPower(0x8bab8eefb6409c1aL, (short) 774, (short) 252),
-        new CachedPower(0xd01fef10a657842cL, (short) 800, (short) 260),
-        new CachedPower(0x9b10a4e5e9913129L, (short) 827, (short) 268),
-        new CachedPower(0xe7109bfba19c0c9dL, (short) 853, (short) 276),
-        new CachedPower(0xac2820d9623bf429L, (short) 880, (short) 284),
-        new CachedPower(0x80444b5e7aa7cf85L, (short) 907, (short) 292),
-        new CachedPower(0xbf21e44003acdd2dL, (short) 933, (short) 300),
-        new CachedPower(0x8e679c2f5e44ff8fL, (short) 960, (short) 308),
-        new CachedPower(0xd433179d9c8cb841L, (short) 986, (short) 316),
-        new CachedPower(0x9e19db92b4e31ba9L, (short) 1013, (short) 324),
-        new CachedPower(0xeb96bf6ebadf77d9L, (short) 1039, (short) 332),
-        new CachedPower(0xaf87023b9bf0ee6bL, (short) 1066, (short) 340)
-    };
-
-    static final int GRISU_CACHE_MAX_DISTANCE = 27;
-    // nb elements (8): 82
-
-    static final int GRISU_CACHE_OFFSET = 308;
-}
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/DiyFp.java rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/DiyFp.java
--- rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/DiyFp.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/DiyFp.java	1970-01-01 02:00:00.000000000 +0200
@@ -1,157 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Ported to Java from Mozilla's version of V8-dtoa by Hannes Wallnoefer.
-// The original revision was 67d1049b0bf9 from the mozilla-central tree.
-
-package org.mozilla.javascript.v8dtoa;
-
-// This "Do It Yourself Floating Point" class implements a floating-point number
-// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
-// have the most significant bit of the significand set.
-// Multiplication and Subtraction do not normalize their results.
-// DiyFp are not designed to contain special doubles (NaN and Infinity).
-class DiyFp {
-
-    private long f;
-    private int e;
-
-    static final int kSignificandSize = 64;
-    static final long kUint64MSB = 0x8000000000000000L;
-
-    DiyFp() {
-        this.f = 0;
-        this.e = 0;
-    }
-
-    DiyFp(long f, int e) {
-        this.f = f;
-        this.e = e;
-    }
-
-    private static boolean uint64_gte(long a, long b) {
-        // greater-or-equal for unsigned int64 in java-style...
-        return (a == b) || ((a > b) ^ (a < 0) ^ (b < 0));
-    }
-
-    // this = this - other.
-    // The exponents of both numbers must be the same and the significand of this
-    // must be bigger than the significand of other.
-    // The result will not be normalized.
-    void subtract(DiyFp other) {
-        assert (e == other.e);
-        assert uint64_gte(f, other.f);
-        f -= other.f;
-    }
-
-    // Returns a - b.
-    // The exponents of both numbers must be the same and this must be bigger
-    // than other. The result will not be normalized.
-    static DiyFp minus(DiyFp a, DiyFp b) {
-        DiyFp result = new DiyFp(a.f, a.e);
-        result.subtract(b);
-        return result;
-    }
-
-    // this = this * other.
-    void multiply(DiyFp other) {
-        // Simply "emulates" a 128 bit multiplication.
-        // However: the resulting number only contains 64 bits. The least
-        // significant 64 bits are only used for rounding the most significant 64
-        // bits.
-        final long kM32 = 0xFFFFFFFFL;
-        long a = f >>> 32;
-        long b = f & kM32;
-        long c = other.f >>> 32;
-        long d = other.f & kM32;
-        long ac = a * c;
-        long bc = b * c;
-        long ad = a * d;
-        long bd = b * d;
-        long tmp = (bd >>> 32) + (ad & kM32) + (bc & kM32);
-        // By adding 1U << 31 to tmp we round the final result.
-        // Halfway cases will be round up.
-        tmp += 1L << 31;
-        long result_f = ac + (ad >>> 32) + (bc >>> 32) + (tmp >>> 32);
-        e += other.e + 64;
-        f = result_f;
-    }
-
-    // returns a * b;
-    static DiyFp times(DiyFp a, DiyFp b) {
-        DiyFp result = new DiyFp(a.f, a.e);
-        result.multiply(b);
-        return result;
-    }
-
-    void normalize() {
-        assert (f != 0);
-        long f = this.f;
-        int e = this.e;
-
-        // This method is mainly called for normalizing boundaries. In general
-        // boundaries need to be shifted by 10 bits. We thus optimize for this case.
-        final long k10MSBits = 0xFFC00000L << 32;
-        while ((f & k10MSBits) == 0) {
-            f <<= 10;
-            e -= 10;
-        }
-        while ((f & kUint64MSB) == 0) {
-            f <<= 1;
-            e--;
-        }
-        this.f = f;
-        this.e = e;
-    }
-
-    static DiyFp normalize(DiyFp a) {
-        DiyFp result = new DiyFp(a.f, a.e);
-        result.normalize();
-        return result;
-    }
-
-    long f() {
-        return f;
-    }
-
-    int e() {
-        return e;
-    }
-
-    void setF(long new_value) {
-        f = new_value;
-    }
-
-    void setE(int new_value) {
-        e = new_value;
-    }
-
-    @Override
-    public String toString() {
-        return "[DiyFp f:" + f + ", e:" + e + "]";
-    }
-}
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/DoubleHelper.java rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/DoubleHelper.java
--- rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/DoubleHelper.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/DoubleHelper.java	1970-01-01 02:00:00.000000000 +0200
@@ -1,131 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Ported to Java from Mozilla's version of V8-dtoa by Hannes Wallnoefer.
-// The original revision was 67d1049b0bf9 from the mozilla-central tree.
-
-package org.mozilla.javascript.v8dtoa;
-
-// Helper functions for doubles.
-public class DoubleHelper {
-
-    static final long kSignMask = 0x8000000000000000L;
-    static final long kExponentMask = 0x7FF0000000000000L;
-    static final long kSignificandMask = 0x000FFFFFFFFFFFFFL;
-    static final long kHiddenBit = 0x0010000000000000L;
-
-    static DiyFp asDiyFp(long d64) {
-        assert (!isSpecial(d64));
-        return new DiyFp(significand(d64), exponent(d64));
-    }
-
-    // this->Significand() must not be 0.
-    static DiyFp asNormalizedDiyFp(long d64) {
-        long f = significand(d64);
-        int e = exponent(d64);
-
-        assert (f != 0);
-
-        // The current double could be a denormal.
-        while ((f & kHiddenBit) == 0) {
-            f <<= 1;
-            e--;
-        }
-        // Do the final shifts in one go. Don't forget the hidden bit (the '-1').
-        f <<= DiyFp.kSignificandSize - kSignificandSize - 1;
-        e -= DiyFp.kSignificandSize - kSignificandSize - 1;
-        return new DiyFp(f, e);
-    }
-
-    static int exponent(long d64) {
-        if (isDenormal(d64)) return kDenormalExponent;
-
-        int biased_e = (int) (((d64 & kExponentMask) >>> kSignificandSize) & 0xffffffffL);
-        return biased_e - kExponentBias;
-    }
-
-    static long significand(long d64) {
-        long significand = d64 & kSignificandMask;
-        if (!isDenormal(d64)) {
-            return significand + kHiddenBit;
-        }
-        return significand;
-    }
-
-    // Returns true if the double is a denormal.
-    static boolean isDenormal(long d64) {
-        return (d64 & kExponentMask) == 0L;
-    }
-
-    // We consider denormals not to be special.
-    // Hence only Infinity and NaN are special.
-    static boolean isSpecial(long d64) {
-        return (d64 & kExponentMask) == kExponentMask;
-    }
-
-    static boolean isNan(long d64) {
-        return ((d64 & kExponentMask) == kExponentMask) && ((d64 & kSignificandMask) != 0L);
-    }
-
-    static boolean isInfinite(long d64) {
-        return ((d64 & kExponentMask) == kExponentMask) && ((d64 & kSignificandMask) == 0L);
-    }
-
-    static int sign(long d64) {
-        return (d64 & kSignMask) == 0L ? 1 : -1;
-    }
-
-    // Returns the two boundaries of first argument.
-    // The bigger boundary (m_plus) is normalized. The lower boundary has the same
-    // exponent as m_plus.
-    static void normalizedBoundaries(long d64, DiyFp m_minus, DiyFp m_plus) {
-        DiyFp v = asDiyFp(d64);
-        boolean significand_is_zero = (v.f() == kHiddenBit);
-        m_plus.setF((v.f() << 1) + 1);
-        m_plus.setE(v.e() - 1);
-        m_plus.normalize();
-        if (significand_is_zero && v.e() != kDenormalExponent) {
-            // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
-            // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
-            // at a distance of 1e8.
-            // The only exception is for the smallest normal: the largest denormal is
-            // at the same distance as its successor.
-            // Note: denormals have the same exponent as the smallest normals.
-            m_minus.setF((v.f() << 2) - 1);
-            m_minus.setE(v.e() - 2);
-        } else {
-            m_minus.setF((v.f() << 1) - 1);
-            m_minus.setE(v.e() - 1);
-        }
-        m_minus.setF(m_minus.f() << (m_minus.e() - m_plus.e()));
-        m_minus.setE(m_plus.e());
-    }
-
-    private static final int kSignificandSize = 52; // Excludes the hidden bit.
-    private static final int kExponentBias = 0x3FF + kSignificandSize;
-    private static final int kDenormalExponent = -kExponentBias + 1;
-}
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/FastDtoaBuilder.java rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/FastDtoaBuilder.java
--- rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/FastDtoaBuilder.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/FastDtoaBuilder.java	1970-01-01 02:00:00.000000000 +0200
@@ -1,108 +0,0 @@
-/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.javascript.v8dtoa;
-
-import java.util.Arrays;
-
-public class FastDtoaBuilder {
-
-    // allocate buffer for generated digits + extra notation + padding zeroes
-    final char[] chars = new char[FastDtoa.kFastDtoaMaximalLength + 8];
-    int end = 0;
-    int point;
-    boolean formatted = false;
-
-    void append(char c) {
-        chars[end++] = c;
-    }
-
-    void decreaseLast() {
-        chars[end - 1]--;
-    }
-
-    public void reset() {
-        end = 0;
-        formatted = false;
-    }
-
-    @Override
-    public String toString() {
-        return "[chars:" + new String(chars, 0, end) + ", point:" + point + "]";
-    }
-
-    public String format() {
-        if (!formatted) {
-            // check for minus sign
-            int firstDigit = chars[0] == '-' ? 1 : 0;
-            int decPoint = point - firstDigit;
-            if (decPoint < -5 || decPoint > 21) {
-                toExponentialFormat(firstDigit, decPoint);
-            } else {
-                toFixedFormat(firstDigit, decPoint);
-            }
-            formatted = true;
-        }
-        return new String(chars, 0, end);
-    }
-
-    private void toFixedFormat(int firstDigit, int decPoint) {
-        if (point < end) {
-            // insert decimal point
-            if (decPoint > 0) {
-                // >= 1, split decimals and insert point
-                System.arraycopy(chars, point, chars, point + 1, end - point);
-                chars[point] = '.';
-                end++;
-            } else {
-                // < 1,
-                int target = firstDigit + 2 - decPoint;
-                System.arraycopy(chars, firstDigit, chars, target, end - firstDigit);
-                chars[firstDigit] = '0';
-                chars[firstDigit + 1] = '.';
-                if (decPoint < 0) {
-                    Arrays.fill(chars, firstDigit + 2, target, '0');
-                }
-                end += 2 - decPoint;
-            }
-        } else if (point > end) {
-            // large integer, add trailing zeroes
-            Arrays.fill(chars, end, point, '0');
-            end += point - end;
-        }
-    }
-
-    private void toExponentialFormat(int firstDigit, int decPoint) {
-        if (end - firstDigit > 1) {
-            // insert decimal point if more than one digit was produced
-            int dot = firstDigit + 1;
-            System.arraycopy(chars, dot, chars, dot + 1, end - dot);
-            chars[dot] = '.';
-            end++;
-        }
-        chars[end++] = 'e';
-        char sign = '+';
-        int exp = decPoint - 1;
-        if (exp < 0) {
-            sign = '-';
-            exp = -exp;
-        }
-        chars[end++] = sign;
-
-        int charPos = exp > 99 ? end + 2 : exp > 9 ? end + 1 : end;
-        end = charPos + 1;
-
-        // code below is needed because Integer.getChars() is not public
-        for (; ; ) {
-            int r = exp % 10;
-            chars[charPos--] = digits[r];
-            exp = exp / 10;
-            if (exp == 0) break;
-        }
-    }
-
-    static final char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
-}
diff -Nru rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/FastDtoa.java rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/FastDtoa.java
--- rhino-1.7.15/src/org/mozilla/javascript/v8dtoa/FastDtoa.java	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/src/org/mozilla/javascript/v8dtoa/FastDtoa.java	1970-01-01 02:00:00.000000000 +0200
@@ -1,509 +0,0 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Ported to Java from Mozilla's version of V8-dtoa by Hannes Wallnoefer.
-// The original revision was 67d1049b0bf9 from the mozilla-central tree.
-
-package org.mozilla.javascript.v8dtoa;
-
-public class FastDtoa {
-
-    // FastDtoa will produce at most kFastDtoaMaximalLength digits.
-    static final int kFastDtoaMaximalLength = 17;
-
-    // The minimal and maximal target exponent define the range of w's binary
-    // exponent, where 'w' is the result of multiplying the input by a cached power
-    // of ten.
-    //
-    // A different range might be chosen on a different platform, to optimize digit
-    // generation, but a smaller range requires more powers of ten to be cached.
-    static final int minimal_target_exponent = -60;
-    static final int maximal_target_exponent = -32;
-
-    // Adjusts the last digit of the generated number, and screens out generated
-    // solutions that may be inaccurate. A solution may be inaccurate if it is
-    // outside the safe interval, or if we ctannot prove that it is closer to the
-    // input than a neighboring representation of the same length.
-    //
-    // Input: * buffer containing the digits of too_high / 10^kappa
-    //        * distance_too_high_w == (too_high - w).f() * unit
-    //        * unsafe_interval == (too_high - too_low).f() * unit
-    //        * rest = (too_high - buffer * 10^kappa).f() * unit
-    //        * ten_kappa = 10^kappa * unit
-    //        * unit = the common multiplier
-    // Output: returns true if the buffer is guaranteed to contain the closest
-    //    representable number to the input.
-    //  Modifies the generated digits in the buffer to approach (round towards) w.
-    static boolean roundWeed(
-            FastDtoaBuilder buffer,
-            long distance_too_high_w,
-            long unsafe_interval,
-            long rest,
-            long ten_kappa,
-            long unit) {
-        long small_distance = distance_too_high_w - unit;
-        long big_distance = distance_too_high_w + unit;
-        // Let w_low  = too_high - big_distance, and
-        //     w_high = too_high - small_distance.
-        // Note: w_low < w < w_high
-        //
-        // The real w (* unit) must lie somewhere inside the interval
-        // ]w_low; w_low[ (often written as "(w_low; w_low)")
-
-        // Basically the buffer currently contains a number in the unsafe interval
-        // ]too_low; too_high[ with too_low < w < too_high
-        //
-        //  too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-        //                     ^v 1 unit            ^      ^                 ^      ^
-        //  boundary_high ---------------------     .      .                 .      .
-        //                     ^v 1 unit            .      .                 .      .
-        //   - - - - - - - - - - - - - - - - - - -  +  - - + - - - - - -     .      .
-        //                                          .      .         ^       .      .
-        //                                          .  big_distance  .       .      .
-        //                                          .      .         .       .    rest
-        //                              small_distance     .         .       .      .
-        //                                          v      .         .       .      .
-        //  w_high - - - - - - - - - - - - - - - - - -     .         .       .      .
-        //                     ^v 1 unit                   .         .       .      .
-        //  w ----------------------------------------     .         .       .      .
-        //                     ^v 1 unit                   v         .       .      .
-        //  w_low  - - - - - - - - - - - - - - - - - - - - -         .       .      .
-        //                                                           .       .      v
-        //  buffer --------------------------------------------------+-------+--------
-        //                                                           .       .
-        //                                                  safe_interval    .
-        //                                                           v       .
-        //   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     .
-        //                     ^v 1 unit                                     .
-        //  boundary_low -------------------------                     unsafe_interval
-        //                     ^v 1 unit                                     v
-        //  too_low  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-        //
-        //
-        // Note that the value of buffer could lie anywhere inside the range too_low
-        // to too_high.
-        //
-        // boundary_low, boundary_high and w are approximations of the real boundaries
-        // and v (the input number). They are guaranteed to be precise up to one unit.
-        // In fact the error is guaranteed to be strictly less than one unit.
-        //
-        // Anything that lies outside the unsafe interval is guaranteed not to round
-        // to v when read again.
-        // Anything that lies inside the safe interval is guaranteed to round to v
-        // when read again.
-        // If the number inside the buffer lies inside the unsafe interval but not
-        // inside the safe interval then we simply do not know and bail out (returning
-        // false).
-        //
-        // Similarly we have to take into account the imprecision of 'w' when rounding
-        // the buffer. If we have two potential representations we need to make sure
-        // that the chosen one is closer to w_low and w_high since v can be anywhere
-        // between them.
-        //
-        // By generating the digits of too_high we got the largest (closest to
-        // too_high) buffer that is still in the unsafe interval. In the case where
-        // w_high < buffer < too_high we try to decrement the buffer.
-        // This way the buffer approaches (rounds towards) w.
-        // There are 3 conditions that stop the decrementation process:
-        //   1) the buffer is already below w_high
-        //   2) decrementing the buffer would make it leave the unsafe interval
-        //   3) decrementing the buffer would yield a number below w_high and farther
-        //      away than the current number. In other words:
-        //              (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high
-        // Instead of using the buffer directly we use its distance to too_high.
-        // Conceptually rest ~= too_high - buffer
-        while (rest < small_distance
-                && // Negated condition 1
-                unsafe_interval - rest >= ten_kappa
-                && // Negated condition 2
-                (rest + ten_kappa < small_distance
-                        || // buffer{-1} > w_high
-                        small_distance - rest >= rest + ten_kappa - small_distance)) {
-            buffer.decreaseLast();
-            rest += ten_kappa;
-        }
-
-        // We have approached w+ as much as possible. We now test if approaching w-
-        // would require changing the buffer. If yes, then we have two possible
-        // representations close to w, but we cannot decide which one is closer.
-        if (rest < big_distance
-                && unsafe_interval - rest >= ten_kappa
-                && (rest + ten_kappa < big_distance
-                        || big_distance - rest > rest + ten_kappa - big_distance)) {
-            return false;
-        }
-
-        // Weeding test.
-        //   The safe interval is [too_low + 2 ulp; too_high - 2 ulp]
-        //   Since too_low = too_high - unsafe_interval this is equivalent to
-        //      [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]
-        //   Conceptually we have: rest ~= too_high - buffer
-        return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);
-    }
-
-    static final int kTen4 = 10000;
-    static final int kTen5 = 100000;
-    static final int kTen6 = 1000000;
-    static final int kTen7 = 10000000;
-    static final int kTen8 = 100000000;
-    static final int kTen9 = 1000000000;
-
-    // Returns the biggest power of ten that is less than or equal than the given
-    // number. We furthermore receive the maximum number of bits 'number' has.
-    // If number_bits == 0 then 0^-1 is returned
-    // The number of bits must be <= 32.
-    // Precondition: (1 << number_bits) <= number < (1 << (number_bits + 1)).
-    static long biggestPowerTen(int number, int number_bits) {
-        int power, exponent;
-        switch (number_bits) {
-            case 32:
-            case 31:
-            case 30:
-                if (kTen9 <= number) {
-                    power = kTen9;
-                    exponent = 9;
-                    break;
-                } // else fallthrough
-            case 29:
-            case 28:
-            case 27:
-                if (kTen8 <= number) {
-                    power = kTen8;
-                    exponent = 8;
-                    break;
-                } // else fallthrough
-            case 26:
-            case 25:
-            case 24:
-                if (kTen7 <= number) {
-                    power = kTen7;
-                    exponent = 7;
-                    break;
-                } // else fallthrough
-            case 23:
-            case 22:
-            case 21:
-            case 20:
-                if (kTen6 <= number) {
-                    power = kTen6;
-                    exponent = 6;
-                    break;
-                } // else fallthrough
-            case 19:
-            case 18:
-            case 17:
-                if (kTen5 <= number) {
-                    power = kTen5;
-                    exponent = 5;
-                    break;
-                } // else fallthrough
-            case 16:
-            case 15:
-            case 14:
-                if (kTen4 <= number) {
-                    power = kTen4;
-                    exponent = 4;
-                    break;
-                } // else fallthrough
-            case 13:
-            case 12:
-            case 11:
-            case 10:
-                if (1000 <= number) {
-                    power = 1000;
-                    exponent = 3;
-                    break;
-                } // else fallthrough
-            case 9:
-            case 8:
-            case 7:
-                if (100 <= number) {
-                    power = 100;
-                    exponent = 2;
-                    break;
-                } // else fallthrough
-            case 6:
-            case 5:
-            case 4:
-                if (10 <= number) {
-                    power = 10;
-                    exponent = 1;
-                    break;
-                } // else fallthrough
-            case 3:
-            case 2:
-            case 1:
-                if (1 <= number) {
-                    power = 1;
-                    exponent = 0;
-                    break;
-                } // else fallthrough
-            case 0:
-                power = 0;
-                exponent = -1;
-                break;
-            default:
-                // Following assignments are here to silence compiler warnings.
-                power = 0;
-                exponent = 0;
-                // UNREACHABLE();
-        }
-        return ((long) power << 32) | (0xffffffffL & exponent);
-    }
-
-    private static boolean uint64_lte(long a, long b) {
-        // less-or-equal for unsigned int64 in java-style...
-        return (a == b) || ((a < b) ^ (a < 0) ^ (b < 0));
-    }
-
-    // Generates the digits of input number w.
-    // w is a floating-point number (DiyFp), consisting of a significand and an
-    // exponent. Its exponent is bounded by minimal_target_exponent and
-    // maximal_target_exponent.
-    //       Hence -60 <= w.e() <= -32.
-    //
-    // Returns false if it fails, in which case the generated digits in the buffer
-    // should not be used.
-    // Preconditions:
-    //  * low, w and high are correct up to 1 ulp (unit in the last place). That
-    //    is, their error must be less that a unit of their last digits.
-    //  * low.e() == w.e() == high.e()
-    //  * low < w < high, and taking into account their error: low~ <= high~
-    //  * minimal_target_exponent <= w.e() <= maximal_target_exponent
-    // Postconditions: returns false if procedure fails.
-    //   otherwise:
-    //     * buffer is not null-terminated, but len contains the number of digits.
-    //     * buffer contains the shortest possible decimal digit-sequence
-    //       such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the
-    //       correct values of low and high (without their error).
-    //     * if more than one decimal representation gives the minimal number of
-    //       decimal digits then the one closest to W (where W is the correct value
-    //       of w) is chosen.
-    // Remark: this procedure takes into account the imprecision of its input
-    //   numbers. If the precision is not enough to guarantee all the postconditions
-    //   then false is returned. This usually happens rarely (~0.5%).
-    //
-    // Say, for the sake of example, that
-    //   w.e() == -48, and w.f() == 0x1234567890abcdef
-    // w's value can be computed by w.f() * 2^w.e()
-    // We can obtain w's integral digits by simply shifting w.f() by -w.e().
-    //  -> w's integral part is 0x1234
-    //  w's fractional part is therefore 0x567890abcdef.
-    // Printing w's integral part is easy (simply print 0x1234 in decimal).
-    // In order to print its fraction we repeatedly multiply the fraction by 10 and
-    // get each digit. Example the first digit after the point would be computed by
-    //   (0x567890abcdef * 10) >> 48. -> 3
-    // The whole thing becomes slightly more complicated because we want to stop
-    // once we have enough digits. That is, once the digits inside the buffer
-    // represent 'w' we can stop. Everything inside the interval low - high
-    // represents w. However we have to pay attention to low, high and w's
-    // imprecision.
-    static boolean digitGen(DiyFp low, DiyFp w, DiyFp high, FastDtoaBuilder buffer, int mk) {
-        assert (low.e() == w.e() && w.e() == high.e());
-        assert uint64_lte(low.f() + 1, high.f() - 1);
-        assert (minimal_target_exponent <= w.e() && w.e() <= maximal_target_exponent);
-        // low, w and high are imprecise, but by less than one ulp (unit in the last
-        // place).
-        // If we remove (resp. add) 1 ulp from low (resp. high) we are certain that
-        // the new numbers are outside of the interval we want the final
-        // representation to lie in.
-        // Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield
-        // numbers that are certain to lie in the interval. We will use this fact
-        // later on.
-        // We will now start by generating the digits within the uncertain
-        // interval. Later we will weed out representations that lie outside the safe
-        // interval and thus _might_ lie outside the correct interval.
-        long unit = 1;
-        DiyFp too_low = new DiyFp(low.f() - unit, low.e());
-        DiyFp too_high = new DiyFp(high.f() + unit, high.e());
-        // too_low and too_high are guaranteed to lie outside the interval we want the
-        // generated number in.
-        DiyFp unsafe_interval = DiyFp.minus(too_high, too_low);
-        // We now cut the input number into two parts: the integral digits and the
-        // fractionals. We will not write any decimal separator though, but adapt
-        // kappa instead.
-        // Reminder: we are currently computing the digits (stored inside the buffer)
-        // such that:   too_low < buffer * 10^kappa < too_high
-        // We use too_high for the digit_generation and stop as soon as possible.
-        // If we stop early we effectively round down.
-        DiyFp one = new DiyFp(1L << -w.e(), w.e());
-        // Division by one is a shift.
-        int integrals = (int) ((too_high.f() >>> -one.e()) & 0xffffffffL);
-        // Modulo by one is an and.
-        long fractionals = too_high.f() & (one.f() - 1);
-        long result = biggestPowerTen(integrals, DiyFp.kSignificandSize - (-one.e()));
-        int divider = (int) ((result >>> 32) & 0xffffffffL);
-        int divider_exponent = (int) (result & 0xffffffffL);
-        int kappa = divider_exponent + 1;
-        // Loop invariant: buffer = too_high / 10^kappa  (integer division)
-        // The invariant holds for the first iteration: kappa has been initialized
-        // with the divider exponent + 1. And the divider is the biggest power of ten
-        // that is smaller than integrals.
-        while (kappa > 0) {
-            int digit = integrals / divider;
-            buffer.append((char) ('0' + digit));
-            integrals %= divider;
-            kappa--;
-            // Note that kappa now equals the exponent of the divider and that the
-            // invariant thus holds again.
-            long rest = ((long) integrals << -one.e()) + fractionals;
-            // Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e())
-            // Reminder: unsafe_interval.e() == one.e()
-            if (rest < unsafe_interval.f()) {
-                // Rounding down (by not emitting the remaining digits) yields a number
-                // that lies within the unsafe interval.
-                buffer.point = buffer.end - mk + kappa;
-                return roundWeed(
-                        buffer,
-                        DiyFp.minus(too_high, w).f(),
-                        unsafe_interval.f(),
-                        rest,
-                        (long) divider << -one.e(),
-                        unit);
-            }
-            divider /= 10;
-        }
-
-        // The integrals have been generated. We are at the point of the decimal
-        // separator. In the following loop we simply multiply the remaining digits by
-        // 10 and divide by one. We just need to pay attention to multiply associated
-        // data (like the interval or 'unit'), too.
-        // Instead of multiplying by 10 we multiply by 5 (cheaper operation) and
-        // increase its (imaginary) exponent. At the same time we decrease the
-        // divider's (one's) exponent and shift its significand.
-        // Basically, if fractionals was a DiyFp (with fractionals.e == one.e):
-        //      fractionals.f *= 10;
-        //      fractionals.f >>= 1; fractionals.e++; // value remains unchanged.
-        //      one.f >>= 1; one.e++;                 // value remains unchanged.
-        //      and we have again fractionals.e == one.e which allows us to divide
-        //           fractionals.f() by one.f()
-        // We simply combine the *= 10 and the >>= 1.
-        while (true) {
-            fractionals *= 5;
-            unit *= 5;
-            unsafe_interval.setF(unsafe_interval.f() * 5);
-            unsafe_interval.setE(unsafe_interval.e() + 1); // Will be optimized out.
-            one.setF(one.f() >>> 1);
-            one.setE(one.e() + 1);
-            // Integer division by one.
-            int digit = (int) ((fractionals >>> -one.e()) & 0xffffffffL);
-            buffer.append((char) ('0' + digit));
-            fractionals &= one.f() - 1; // Modulo by one.
-            kappa--;
-            if (fractionals < unsafe_interval.f()) {
-                buffer.point = buffer.end - mk + kappa;
-                return roundWeed(
-                        buffer,
-                        DiyFp.minus(too_high, w).f() * unit,
-                        unsafe_interval.f(),
-                        fractionals,
-                        one.f(),
-                        unit);
-            }
-        }
-    }
-
-    // Provides a decimal representation of v.
-    // Returns true if it succeeds, otherwise the result cannot be trusted.
-    // There will be *length digits inside the buffer (not null-terminated).
-    // If the function returns true then
-    //        v == (double) (buffer * 10^decimal_exponent).
-    // The digits in the buffer are the shortest representation possible: no
-    // 0.09999999999999999 instead of 0.1. The shorter representation will even be
-    // chosen even if the longer one would be closer to v.
-    // The last digit will be closest to the actual v. That is, even if several
-    // digits might correctly yield 'v' when read again, the closest will be
-    // computed.
-    static boolean grisu3(double v, FastDtoaBuilder buffer) {
-        long bits = Double.doubleToLongBits(v);
-        DiyFp w = DoubleHelper.asNormalizedDiyFp(bits);
-        // boundary_minus and boundary_plus are the boundaries between v and its
-        // closest floating-point neighbors. Any number strictly between
-        // boundary_minus and boundary_plus will round to v when convert to a double.
-        // Grisu3 will never output representations that lie exactly on a boundary.
-        DiyFp boundary_minus = new DiyFp(), boundary_plus = new DiyFp();
-        DoubleHelper.normalizedBoundaries(bits, boundary_minus, boundary_plus);
-        assert (boundary_plus.e() == w.e());
-        DiyFp ten_mk = new DiyFp(); // Cached power of ten: 10^-k
-        int mk =
-                CachedPowers.getCachedPower(
-                        w.e() + DiyFp.kSignificandSize,
-                        minimal_target_exponent,
-                        maximal_target_exponent,
-                        ten_mk);
-        assert (minimal_target_exponent <= w.e() + ten_mk.e() + DiyFp.kSignificandSize
-                && maximal_target_exponent >= w.e() + ten_mk.e() + DiyFp.kSignificandSize);
-        // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
-        // 64 bit significand and ten_mk is thus only precise up to 64 bits.
-
-        // The DiyFp::Times procedure rounds its result, and ten_mk is approximated
-        // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
-        // off by a small amount.
-        // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
-        // In other words: let f = scaled_w.f() and e = scaled_w.e(), then
-        //           (f-1) * 2^e < w*10^k < (f+1) * 2^e
-        DiyFp scaled_w = DiyFp.times(w, ten_mk);
-        assert (scaled_w.e() == boundary_plus.e() + ten_mk.e() + DiyFp.kSignificandSize);
-        // In theory it would be possible to avoid some recomputations by computing
-        // the difference between w and boundary_minus/plus (a power of 2) and to
-        // compute scaled_boundary_minus/plus by subtracting/adding from
-        // scaled_w. However the code becomes much less readable and the speed
-        // enhancements are not terriffic.
-        DiyFp scaled_boundary_minus = DiyFp.times(boundary_minus, ten_mk);
-        DiyFp scaled_boundary_plus = DiyFp.times(boundary_plus, ten_mk);
-
-        // DigitGen will generate the digits of scaled_w. Therefore we have
-        // v == (double) (scaled_w * 10^-mk).
-        // Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
-        // integer than it will be updated. For instance if scaled_w == 1.23 then
-        // the buffer will be filled with "123" und the decimal_exponent will be
-        // decreased by 2.
-        return digitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus, buffer, mk);
-    }
-
-    public static boolean dtoa(double v, FastDtoaBuilder buffer) {
-        assert (v > 0);
-        assert (!Double.isNaN(v));
-        assert (!Double.isInfinite(v));
-
-        return grisu3(v, buffer);
-    }
-
-    public static String numberToString(double v) {
-        FastDtoaBuilder buffer = new FastDtoaBuilder();
-        return numberToString(v, buffer) ? buffer.format() : null;
-    }
-
-    public static boolean numberToString(double v, FastDtoaBuilder buffer) {
-        buffer.reset();
-        if (v < 0) {
-            buffer.append('-');
-            v = -v;
-        }
-        return dtoa(v, buffer);
-    }
-}
diff -Nru rhino-1.7.15/testsrc/org/mozilla/javascript/tests/NumberToStringTest.java rhino-1.7.15.1/testsrc/org/mozilla/javascript/tests/NumberToStringTest.java
--- rhino-1.7.15/testsrc/org/mozilla/javascript/tests/NumberToStringTest.java	1970-01-01 02:00:00.000000000 +0200
+++ rhino-1.7.15.1/testsrc/org/mozilla/javascript/tests/NumberToStringTest.java	2025-12-03 05:43:04.000000000 +0200
@@ -0,0 +1,89 @@
+package org.mozilla.javascript.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.mozilla.javascript.ScriptRuntime;
+
+@RunWith(Parameterized.class)
+public class NumberToStringTest {
+    @Parameterized.Parameter(0)
+    public String expected;
+
+    @Parameterized.Parameter(1)
+    public double value;
+
+    // toString results from V8 compared to their inputs
+    private static final Object[][] TO_STRING_TESTS = {
+        // order: expected result, source
+        {"0", 0.0},
+        {"1", 1.0},
+        {"-1", -1.0},
+        {"100", 100},
+        {"0.000001", 0.000001},
+        {"0.9999", 0.9999},
+        {"123.456", 123.456},
+        {"-123.456", -123.456},
+        {"1e+23", 1E23},
+        {"1.0000000000000001e+23", 100000000000000000000001.0},
+        {"3.14", 3.14},
+        {"1000000000", 1E9},
+        {"1e+31", 1E31},
+        // Make sure we have various high and low ranges
+        {"3.141592653589793", Math.PI},
+        {"314159265358.9793", Math.PI * 100000000000.0},
+        {"3.141592653589793e-11", Math.PI / 100000000000.0},
+        {"3141592653589793000", Math.PI * 1000000000000000.0 * 1000.0},
+        {"3.1415926535897934e-14", 3.1415926535897934E-14},
+        {"3.141592653589793e+23", Math.PI * 1000000000000000.0 * 100000000.0},
+        {"9.352546905515962e+198", 9.3525469055159624998555744E198},
+        // Boundaries
+        {"1e-7", 1E-7},
+        {"1e+21", 1E21},
+        {"1e+21", 1.00000000000000001E21},
+        {"1e+21", 0.99999999999999999E21},
+        {"1.0000000000000001e+21", 1.0000000000000001E21},
+        {"999999999999999900000", 0.9999999999999999E21},
+        {"1e-7", 1.00000000000000001E-7},
+        {"1.0000000000000001e-7", 1.0000000000000001E-7},
+        {"1e-7", 0.9999999999999999E-7},
+        {"9.99999999999999e-8", 0.999999999999999E-7},
+        // Denormals
+        {"5.88e-39", 5.88E-39},
+        {"4.47118444e-314", 4.47118444E-314},
+        // Specific values from the JDK test suite
+        {"282879384806159000", 2.82879384806159E17},
+        {"1387364135037754000", 1.387364135037754E18},
+        {"145800632428665000", 1.45800632428665E17},
+        {"1.6e-322", 1.6E-322},
+        {"6.3e-322", 6.3E-322},
+        {"738790000000000000000", 7.3879E20},
+        {"2e+23", 2.0E23},
+        {"7e+22", 7.0E22},
+        {"9.2e+22", 9.2E22},
+        {"9.5e+21", 9.5E21},
+        {"3.1e+22", 3.1E22},
+        {"5.63e+21", 5.63E21},
+        {"8.41e+21", 8.41E21},
+        {"1.9400994884341945e+25", 1.9400994884341945E25},
+        {"3.6131332396758635e+25", 3.6131332396758635E25},
+        {"2.5138990223946153e+25", 2.5138990223946153E25},
+        // These are controversial -- Java gives a more rounded-
+        // off result but the original Schubfach code does not.
+        {"9.9e-324", 9.9E-324},
+        {"9.9e-323", 9.9E-323}
+    };
+
+    @Parameterized.Parameters()
+    public static Collection<Object[]> data() {
+        return java.util.Arrays.asList(TO_STRING_TESTS);
+    }
+
+    @Test
+    public void testToString() {
+        assertEquals(expected, ScriptRuntime.toString(value));
+    }
+}
diff -Nru rhino-1.7.15/testsrc/test262.properties rhino-1.7.15.1/testsrc/test262.properties
--- rhino-1.7.15/testsrc/test262.properties	2024-05-04 03:41:43.000000000 +0300
+++ rhino-1.7.15.1/testsrc/test262.properties	2025-12-03 05:43:04.000000000 +0200
@@ -730,11 +730,7 @@
     URIError/proto-from-ctor-realm.js {unsupported: [Reflect]}
 
 built-ins/Number 9/283 (3.18%)
-    prototype/toExponential/return-abrupt-tointeger-fractiondigits.js
-    prototype/toExponential/return-abrupt-tointeger-fractiondigits-symbol.js
-    prototype/toExponential/undefined-fractiondigits.js
     prototype/toLocaleString/length.js
-    prototype/toPrecision/nan.js
     proto-from-ctor-realm.js {unsupported: [Reflect]}
     S9.3.1_A2_U180E.js {unsupported: [u180e]}
     S9.3.1_A3_T1_U180E.js {unsupported: [u180e]}
