BignumDtoaTest.java revision 1511:a1f59730bfb5
1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26// This file is available under and governed by the GNU General Public
27// License version 2 only, as published by the Free Software Foundation.
28// However, the following notice accompanied the original version of this
29// file:
30//
31// Copyright 2012 the V8 project authors. All rights reserved.
32// Redistribution and use in source and binary forms, with or without
33// modification, are permitted provided that the following conditions are
34// met:
35//
36//     * Redistributions of source code must retain the above copyright
37//       notice, this list of conditions and the following disclaimer.
38//     * Redistributions in binary form must reproduce the above
39//       copyright notice, this list of conditions and the following
40//       disclaimer in the documentation and/or other materials provided
41//       with the distribution.
42//     * Neither the name of Google Inc. nor the names of its
43//       contributors may be used to endorse or promote products derived
44//       from this software without specific prior written permission.
45//
46// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
49// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
50// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
56// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
58package jdk.nashorn.internal.runtime.doubleconv.test;
59
60import java.io.BufferedReader;
61import java.io.InputStreamReader;
62import jdk.nashorn.internal.runtime.doubleconv.DoubleConversion;
63import jdk.nashorn.internal.runtime.doubleconv.DtoaBuffer;
64import jdk.nashorn.internal.runtime.doubleconv.DtoaMode;
65
66import org.testng.annotations.Test;
67
68import static org.testng.Assert.assertEquals;
69import static org.testng.Assert.assertTrue;
70
71/**
72 * FastDtoa tests
73 */
74@SuppressWarnings("javadoc")
75public class BignumDtoaTest {
76
77    final static private int BUFFER_SIZE = 100;
78
79    // Removes trailing '0' digits.
80    // Can return the empty string if all digits are 0.
81    private static String trimRepresentation(final String representation) {
82        final int len = representation.length();
83        int i;
84        for (i = len - 1; i >= 0; --i) {
85            if (representation.charAt(i) != '0') break;
86        }
87        return representation.substring(0, i + 1);
88    }
89
90    @Test
91    public void testBignumVarious() {
92        final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
93
94        DoubleConversion.bignumDtoa(1, DtoaMode.SHORTEST, 0, buffer);
95        assertEquals("1", buffer.getRawDigits());
96        assertEquals(1, buffer.getDecimalPoint());
97        buffer.reset();
98
99        DoubleConversion.bignumDtoa(1.0, DtoaMode.FIXED, 3, buffer);
100        assertTrue(3 >= buffer.getLength() - buffer.getDecimalPoint());
101        assertEquals("1", trimRepresentation(buffer.getRawDigits()));
102        assertEquals(1, buffer.getDecimalPoint());
103        buffer.reset();
104
105        DoubleConversion.bignumDtoa(1.0, DtoaMode.PRECISION, 3, buffer);
106        assertTrue(3 >= buffer.getLength());
107        assertEquals("1", trimRepresentation(buffer.getRawDigits()));
108        assertEquals(1, buffer.getDecimalPoint());
109        buffer.reset();
110
111        DoubleConversion.bignumDtoa(1.5, DtoaMode.SHORTEST, 0, buffer);
112        assertEquals("15", buffer.getRawDigits());
113        assertEquals(1, buffer.getDecimalPoint());
114        buffer.reset();
115
116        DoubleConversion.bignumDtoa(1.5, DtoaMode.FIXED, 10, buffer);
117        assertTrue(10 >= buffer.getLength() - buffer.getDecimalPoint());
118        assertEquals("15", trimRepresentation(buffer.getRawDigits()));
119        assertEquals(1, buffer.getDecimalPoint());
120        buffer.reset();
121
122        DoubleConversion.bignumDtoa(1.5, DtoaMode.PRECISION, 10, buffer);
123        assertTrue(10 >= buffer.getLength());
124        assertEquals("15", trimRepresentation(buffer.getRawDigits()));
125        assertEquals(1, buffer.getDecimalPoint());
126        buffer.reset();
127
128        final double min_double = 5e-324;
129        DoubleConversion.bignumDtoa(min_double, DtoaMode.SHORTEST, 0, buffer);
130        assertEquals("5", buffer.getRawDigits());
131        assertEquals(-323, buffer.getDecimalPoint());
132        buffer.reset();
133
134        DoubleConversion.bignumDtoa(min_double, DtoaMode.FIXED, 5, buffer);
135        assertTrue(5 >= buffer.getLength() - buffer.getDecimalPoint());
136        assertEquals("", trimRepresentation(buffer.getRawDigits()));
137        buffer.reset();
138
139        DoubleConversion.bignumDtoa(min_double, DtoaMode.PRECISION, 5, buffer);
140        assertTrue(5 >= buffer.getLength());
141        assertEquals("49407", trimRepresentation(buffer.getRawDigits()));
142        assertEquals(-323, buffer.getDecimalPoint());
143        buffer.reset();
144
145        final double max_double = 1.7976931348623157e308;
146        DoubleConversion.bignumDtoa(max_double, DtoaMode.SHORTEST, 0, buffer);
147        assertEquals("17976931348623157", buffer.getRawDigits());
148        assertEquals(309, buffer.getDecimalPoint());
149        buffer.reset();
150
151        DoubleConversion.bignumDtoa(max_double, DtoaMode.PRECISION, 7, buffer);
152        assertTrue(7 >= buffer.getLength());
153        assertEquals("1797693", trimRepresentation(buffer.getRawDigits()));
154        assertEquals(309, buffer.getDecimalPoint());
155        buffer.reset();
156
157        DoubleConversion.bignumDtoa(4294967272.0, DtoaMode.SHORTEST, 0, buffer);
158        assertEquals("4294967272", buffer.getRawDigits());
159        assertEquals(10, buffer.getDecimalPoint());
160        buffer.reset();
161
162        DoubleConversion.bignumDtoa(4294967272.0, DtoaMode.FIXED, 5, buffer);
163        assertEquals("429496727200000", buffer.getRawDigits());
164        assertEquals(10, buffer.getDecimalPoint());
165        buffer.reset();
166
167        DoubleConversion.bignumDtoa(4294967272.0, DtoaMode.PRECISION, 14, buffer);
168        assertTrue(14 >= buffer.getLength());
169        assertEquals("4294967272", trimRepresentation(buffer.getRawDigits()));
170        assertEquals(10, buffer.getDecimalPoint());
171        buffer.reset();
172
173        DoubleConversion.bignumDtoa(4.1855804968213567e298, DtoaMode.SHORTEST, 0, buffer);
174        assertEquals("4185580496821357", buffer.getRawDigits());
175        assertEquals(299, buffer.getDecimalPoint());
176        buffer.reset();
177
178        DoubleConversion.bignumDtoa(4.1855804968213567e298, DtoaMode.PRECISION, 20, buffer);
179        assertTrue(20 >= buffer.getLength());
180        assertEquals("41855804968213567225", trimRepresentation(buffer.getRawDigits()));
181        assertEquals(299, buffer.getDecimalPoint());
182        buffer.reset();
183
184        DoubleConversion.bignumDtoa(5.5626846462680035e-309, DtoaMode.SHORTEST, 0, buffer);
185        assertEquals("5562684646268003", buffer.getRawDigits());
186        assertEquals(-308, buffer.getDecimalPoint());
187        buffer.reset();
188
189        DoubleConversion.bignumDtoa(5.5626846462680035e-309, DtoaMode.PRECISION, 1, buffer);
190        assertTrue(1 >= buffer.getLength());
191        assertEquals("6", trimRepresentation(buffer.getRawDigits()));
192        assertEquals(-308, buffer.getDecimalPoint());
193        buffer.reset();
194
195        DoubleConversion.bignumDtoa(2147483648.0, DtoaMode.SHORTEST, 0, buffer);
196        assertEquals("2147483648", buffer.getRawDigits());
197        assertEquals(10, buffer.getDecimalPoint());
198        buffer.reset();
199
200        DoubleConversion.bignumDtoa(2147483648.0, DtoaMode.FIXED, 2, buffer);
201        assertTrue(2 >= buffer.getLength() - buffer.getDecimalPoint());
202        assertEquals("2147483648", trimRepresentation(buffer.getRawDigits()));
203        assertEquals(10, buffer.getDecimalPoint());
204        buffer.reset();
205
206        DoubleConversion.bignumDtoa(2147483648.0, DtoaMode.PRECISION, 5, buffer);
207        assertTrue(5 >= buffer.getLength());
208        assertEquals("21475", trimRepresentation(buffer.getRawDigits()));
209        assertEquals(10, buffer.getDecimalPoint());
210        buffer.reset();
211
212        DoubleConversion.bignumDtoa(3.5844466002796428e+298, DtoaMode.SHORTEST, 0, buffer);
213        assertEquals("35844466002796428", buffer.getRawDigits());
214        assertEquals(299, buffer.getDecimalPoint());
215        buffer.reset();
216
217        DoubleConversion.bignumDtoa(3.5844466002796428e+298, DtoaMode.PRECISION, 10, buffer);
218        assertTrue(10 >= buffer.getLength());
219        assertEquals("35844466", trimRepresentation(buffer.getRawDigits()));
220        assertEquals(299, buffer.getDecimalPoint());
221        buffer.reset();
222
223        final long smallest_normal64 = 0x0010000000000000L;
224        double v = Double.longBitsToDouble(smallest_normal64);
225        DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer);
226        assertEquals("22250738585072014", buffer.getRawDigits());
227        assertEquals(-307, buffer.getDecimalPoint());
228        buffer.reset();
229
230        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 20, buffer);
231        assertTrue(20 >= buffer.getLength());
232        assertEquals("22250738585072013831", trimRepresentation(buffer.getRawDigits()));
233        assertEquals(-307, buffer.getDecimalPoint());
234        buffer.reset();
235
236        final long largest_denormal64 = 0x000FFFFFFFFFFFFFL;
237        v = Double.longBitsToDouble(largest_denormal64);
238        DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer);
239        assertEquals("2225073858507201", buffer.getRawDigits());
240        assertEquals(-307, buffer.getDecimalPoint());
241        buffer.reset();
242
243        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 20, buffer);
244        assertTrue(20 >= buffer.getLength());
245        assertEquals("2225073858507200889", trimRepresentation(buffer.getRawDigits()));
246        assertEquals(-307, buffer.getDecimalPoint());
247        buffer.reset();
248
249        DoubleConversion.bignumDtoa(4128420500802942e-24, DtoaMode.SHORTEST, 0, buffer);
250        assertEquals("4128420500802942", buffer.getRawDigits());
251        assertEquals(-8, buffer.getDecimalPoint());
252        buffer.reset();
253
254        DoubleConversion.bignumDtoa(3.9292015898194142585311918e-10, DtoaMode.SHORTEST, 0, buffer);
255        assertEquals("39292015898194143", buffer.getRawDigits());
256        buffer.reset();
257
258        v = 4194304.0;
259        DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, 5, buffer);
260        assertTrue(5 >= buffer.getLength() - buffer.getDecimalPoint());
261        assertEquals("4194304", trimRepresentation(buffer.getRawDigits()));
262        buffer.reset();
263
264        v = 3.3161339052167390562200598e-237;
265        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 19, buffer);
266        assertTrue(19 >= buffer.getLength());
267        assertEquals("3316133905216739056", trimRepresentation(buffer.getRawDigits()));
268        assertEquals(-236, buffer.getDecimalPoint());
269        buffer.reset();
270
271        v = 7.9885183916008099497815232e+191;
272        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 4, buffer);
273        assertTrue(4 >= buffer.getLength());
274        assertEquals("7989", trimRepresentation(buffer.getRawDigits()));
275        assertEquals(192, buffer.getDecimalPoint());
276        buffer.reset();
277
278        v = 1.0000000000000012800000000e+17;
279        DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, 1, buffer);
280        assertTrue(1 >= buffer.getLength() - buffer.getDecimalPoint());
281        assertEquals("100000000000000128", trimRepresentation(buffer.getRawDigits()));
282        assertEquals(18, buffer.getDecimalPoint());
283        buffer.reset();
284    }
285
286
287    @Test
288    public void testBignumShortest() {
289        new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-shortest.txt")))
290                .lines()
291                .forEach(line -> {
292                    if (line.isEmpty() || line.startsWith("//")) {
293                        return; // comment or empty line
294                    }
295                    final String[] tokens = line.split(",\\s+");
296                    assertEquals(tokens.length, 3, "*" + line + "*");
297                    final double v = Double.parseDouble(tokens[0]);
298                    final String str = tokens[1].replace('"', ' ').trim();;
299                    final int point = Integer.parseInt(tokens[2]);
300                    final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
301
302                    DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer);
303                    assertEquals(str, buffer.getRawDigits());
304                    assertEquals(point, buffer.getDecimalPoint());
305                });
306    }
307
308    @Test
309    public void testBignumFixed()  {
310        new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-fixed.txt")))
311                .lines()
312                .forEach(line -> {
313                    if (line.isEmpty() || line.startsWith("//")) {
314                        return; // comment or empty line
315                    }
316                    final String[] tokens = line.split(",\\s+");
317                    assertEquals(tokens.length, 4);
318                    final double v = Double.parseDouble(tokens[0]);
319                    final int digits = Integer.parseInt(tokens[1]);
320                    final String str = tokens[2].replace('"', ' ').trim();
321                    final int point = Integer.parseInt(tokens[3]);
322                    final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
323
324                    DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, digits, buffer);
325                    assertEquals(str, trimRepresentation(buffer.getRawDigits()));
326                    assertEquals(point, buffer.getDecimalPoint());
327                });
328    }
329
330    @Test
331    public void testBignumPrecision() {
332        new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-precision.txt")))
333                .lines()
334                .forEach(line -> {
335                    if (line.isEmpty() || line.startsWith("//")) {
336                        return; // comment or empty line
337                    }
338                    final String[] tokens = line.split(",\\s+");
339                    assertEquals(tokens.length, 4);
340                    final double v = Double.parseDouble(tokens[0]);
341                    final int digits = Integer.parseInt(tokens[1]);
342                    final String str = tokens[2].replace('"', ' ').trim();
343                    final int point = Integer.parseInt(tokens[3]);
344                    final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
345
346                    DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, digits, buffer);
347                    assertEquals(str, trimRepresentation(buffer.getRawDigits()));
348                    assertEquals(point, buffer.getDecimalPoint());
349                });
350    }
351
352}
353