BignumDtoaTest.java revision 1507:549f06563f1c
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 * @test
75 * @run testng jdk.nashorn.internal.runtime.doubleconv.test.FastDtoaTest
76 */
77@SuppressWarnings("javadoc")
78public class BignumDtoaTest {
79
80    final static private int BUFFER_SIZE = 100;
81
82    // Removes trailing '0' digits.
83    // Can return the empty string if all digits are 0.
84    private static String trimRepresentation(final String representation) {
85        final int len = representation.length();
86        int i;
87        for (i = len - 1; i >= 0; --i) {
88            if (representation.charAt(i) != '0') break;
89        }
90        return representation.substring(0, i + 1);
91    }
92
93    @Test
94    public void testBignumVarious() {
95        final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
96
97        DoubleConversion.bignumDtoa(1, DtoaMode.SHORTEST, 0, buffer);
98        assertEquals("1", buffer.getRawDigits());
99        assertEquals(1, buffer.getDecimalPoint());
100        buffer.reset();
101
102        DoubleConversion.bignumDtoa(1.0, DtoaMode.FIXED, 3, buffer);
103        assertTrue(3 >= buffer.getLength() - buffer.getDecimalPoint());
104        assertEquals("1", trimRepresentation(buffer.getRawDigits()));
105        assertEquals(1, buffer.getDecimalPoint());
106        buffer.reset();
107
108        DoubleConversion.bignumDtoa(1.0, DtoaMode.PRECISION, 3, buffer);
109        assertTrue(3 >= buffer.getLength());
110        assertEquals("1", trimRepresentation(buffer.getRawDigits()));
111        assertEquals(1, buffer.getDecimalPoint());
112        buffer.reset();
113
114        DoubleConversion.bignumDtoa(1.5, DtoaMode.SHORTEST, 0, buffer);
115        assertEquals("15", buffer.getRawDigits());
116        assertEquals(1, buffer.getDecimalPoint());
117        buffer.reset();
118
119        DoubleConversion.bignumDtoa(1.5, DtoaMode.FIXED, 10, buffer);
120        assertTrue(10 >= buffer.getLength() - buffer.getDecimalPoint());
121        assertEquals("15", trimRepresentation(buffer.getRawDigits()));
122        assertEquals(1, buffer.getDecimalPoint());
123        buffer.reset();
124
125        DoubleConversion.bignumDtoa(1.5, DtoaMode.PRECISION, 10, buffer);
126        assertTrue(10 >= buffer.getLength());
127        assertEquals("15", trimRepresentation(buffer.getRawDigits()));
128        assertEquals(1, buffer.getDecimalPoint());
129        buffer.reset();
130
131        final double min_double = 5e-324;
132        DoubleConversion.bignumDtoa(min_double, DtoaMode.SHORTEST, 0, buffer);
133        assertEquals("5", buffer.getRawDigits());
134        assertEquals(-323, buffer.getDecimalPoint());
135        buffer.reset();
136
137        DoubleConversion.bignumDtoa(min_double, DtoaMode.FIXED, 5, buffer);
138        assertTrue(5 >= buffer.getLength() - buffer.getDecimalPoint());
139        assertEquals("", trimRepresentation(buffer.getRawDigits()));
140        buffer.reset();
141
142        DoubleConversion.bignumDtoa(min_double, DtoaMode.PRECISION, 5, buffer);
143        assertTrue(5 >= buffer.getLength());
144        assertEquals("49407", trimRepresentation(buffer.getRawDigits()));
145        assertEquals(-323, buffer.getDecimalPoint());
146        buffer.reset();
147
148        final double max_double = 1.7976931348623157e308;
149        DoubleConversion.bignumDtoa(max_double, DtoaMode.SHORTEST, 0, buffer);
150        assertEquals("17976931348623157", buffer.getRawDigits());
151        assertEquals(309, buffer.getDecimalPoint());
152        buffer.reset();
153
154        DoubleConversion.bignumDtoa(max_double, DtoaMode.PRECISION, 7, buffer);
155        assertTrue(7 >= buffer.getLength());
156        assertEquals("1797693", trimRepresentation(buffer.getRawDigits()));
157        assertEquals(309, buffer.getDecimalPoint());
158        buffer.reset();
159
160        DoubleConversion.bignumDtoa(4294967272.0, DtoaMode.SHORTEST, 0, buffer);
161        assertEquals("4294967272", buffer.getRawDigits());
162        assertEquals(10, buffer.getDecimalPoint());
163        buffer.reset();
164
165        DoubleConversion.bignumDtoa(4294967272.0, DtoaMode.FIXED, 5, buffer);
166        assertEquals("429496727200000", buffer.getRawDigits());
167        assertEquals(10, buffer.getDecimalPoint());
168        buffer.reset();
169
170        DoubleConversion.bignumDtoa(4294967272.0, DtoaMode.PRECISION, 14, buffer);
171        assertTrue(14 >= buffer.getLength());
172        assertEquals("4294967272", trimRepresentation(buffer.getRawDigits()));
173        assertEquals(10, buffer.getDecimalPoint());
174        buffer.reset();
175
176        DoubleConversion.bignumDtoa(4.1855804968213567e298, DtoaMode.SHORTEST, 0, buffer);
177        assertEquals("4185580496821357", buffer.getRawDigits());
178        assertEquals(299, buffer.getDecimalPoint());
179        buffer.reset();
180
181        DoubleConversion.bignumDtoa(4.1855804968213567e298, DtoaMode.PRECISION, 20, buffer);
182        assertTrue(20 >= buffer.getLength());
183        assertEquals("41855804968213567225", trimRepresentation(buffer.getRawDigits()));
184        assertEquals(299, buffer.getDecimalPoint());
185        buffer.reset();
186
187        DoubleConversion.bignumDtoa(5.5626846462680035e-309, DtoaMode.SHORTEST, 0, buffer);
188        assertEquals("5562684646268003", buffer.getRawDigits());
189        assertEquals(-308, buffer.getDecimalPoint());
190        buffer.reset();
191
192        DoubleConversion.bignumDtoa(5.5626846462680035e-309, DtoaMode.PRECISION, 1, buffer);
193        assertTrue(1 >= buffer.getLength());
194        assertEquals("6", trimRepresentation(buffer.getRawDigits()));
195        assertEquals(-308, buffer.getDecimalPoint());
196        buffer.reset();
197
198        DoubleConversion.bignumDtoa(2147483648.0, DtoaMode.SHORTEST, 0, buffer);
199        assertEquals("2147483648", buffer.getRawDigits());
200        assertEquals(10, buffer.getDecimalPoint());
201        buffer.reset();
202
203        DoubleConversion.bignumDtoa(2147483648.0, DtoaMode.FIXED, 2, buffer);
204        assertTrue(2 >= buffer.getLength() - buffer.getDecimalPoint());
205        assertEquals("2147483648", trimRepresentation(buffer.getRawDigits()));
206        assertEquals(10, buffer.getDecimalPoint());
207        buffer.reset();
208
209        DoubleConversion.bignumDtoa(2147483648.0, DtoaMode.PRECISION, 5, buffer);
210        assertTrue(5 >= buffer.getLength());
211        assertEquals("21475", trimRepresentation(buffer.getRawDigits()));
212        assertEquals(10, buffer.getDecimalPoint());
213        buffer.reset();
214
215        DoubleConversion.bignumDtoa(3.5844466002796428e+298, DtoaMode.SHORTEST, 0, buffer);
216        assertEquals("35844466002796428", buffer.getRawDigits());
217        assertEquals(299, buffer.getDecimalPoint());
218        buffer.reset();
219
220        DoubleConversion.bignumDtoa(3.5844466002796428e+298, DtoaMode.PRECISION, 10, buffer);
221        assertTrue(10 >= buffer.getLength());
222        assertEquals("35844466", trimRepresentation(buffer.getRawDigits()));
223        assertEquals(299, buffer.getDecimalPoint());
224        buffer.reset();
225
226        final long smallest_normal64 = 0x0010000000000000L;
227        double v = Double.longBitsToDouble(smallest_normal64);
228        DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer);
229        assertEquals("22250738585072014", buffer.getRawDigits());
230        assertEquals(-307, buffer.getDecimalPoint());
231        buffer.reset();
232
233        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 20, buffer);
234        assertTrue(20 >= buffer.getLength());
235        assertEquals("22250738585072013831", trimRepresentation(buffer.getRawDigits()));
236        assertEquals(-307, buffer.getDecimalPoint());
237        buffer.reset();
238
239        final long largest_denormal64 = 0x000FFFFFFFFFFFFFL;
240        v = Double.longBitsToDouble(largest_denormal64);
241        DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer);
242        assertEquals("2225073858507201", buffer.getRawDigits());
243        assertEquals(-307, buffer.getDecimalPoint());
244        buffer.reset();
245
246        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 20, buffer);
247        assertTrue(20 >= buffer.getLength());
248        assertEquals("2225073858507200889", trimRepresentation(buffer.getRawDigits()));
249        assertEquals(-307, buffer.getDecimalPoint());
250        buffer.reset();
251
252        DoubleConversion.bignumDtoa(4128420500802942e-24, DtoaMode.SHORTEST, 0, buffer);
253        assertEquals("4128420500802942", buffer.getRawDigits());
254        assertEquals(-8, buffer.getDecimalPoint());
255        buffer.reset();
256
257        DoubleConversion.bignumDtoa(3.9292015898194142585311918e-10, DtoaMode.SHORTEST, 0, buffer);
258        assertEquals("39292015898194143", buffer.getRawDigits());
259        buffer.reset();
260
261        v = 4194304.0;
262        DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, 5, buffer);
263        assertTrue(5 >= buffer.getLength() - buffer.getDecimalPoint());
264        assertEquals("4194304", trimRepresentation(buffer.getRawDigits()));
265        buffer.reset();
266
267        v = 3.3161339052167390562200598e-237;
268        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 19, buffer);
269        assertTrue(19 >= buffer.getLength());
270        assertEquals("3316133905216739056", trimRepresentation(buffer.getRawDigits()));
271        assertEquals(-236, buffer.getDecimalPoint());
272        buffer.reset();
273
274        v = 7.9885183916008099497815232e+191;
275        DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 4, buffer);
276        assertTrue(4 >= buffer.getLength());
277        assertEquals("7989", trimRepresentation(buffer.getRawDigits()));
278        assertEquals(192, buffer.getDecimalPoint());
279        buffer.reset();
280
281        v = 1.0000000000000012800000000e+17;
282        DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, 1, buffer);
283        assertTrue(1 >= buffer.getLength() - buffer.getDecimalPoint());
284        assertEquals("100000000000000128", trimRepresentation(buffer.getRawDigits()));
285        assertEquals(18, buffer.getDecimalPoint());
286        buffer.reset();
287    }
288
289
290    @Test
291    public void testBignumShortest() {
292        new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-shortest.txt")))
293                .lines()
294                .forEach(line -> {
295                    if (line.isEmpty() || line.startsWith("//")) {
296                        return; // comment or empty line
297                    }
298                    final String[] tokens = line.split(",\\s+");
299                    assertEquals(tokens.length, 3, "*" + line + "*");
300                    final double v = Double.parseDouble(tokens[0]);
301                    final String str = tokens[1].replace('"', ' ').trim();;
302                    final int point = Integer.parseInt(tokens[2]);
303                    final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
304
305                    DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer);
306                    assertEquals(str, buffer.getRawDigits());
307                    assertEquals(point, buffer.getDecimalPoint());
308                });
309    }
310
311    @Test
312    public void testBignumFixed()  {
313        new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-fixed.txt")))
314                .lines()
315                .forEach(line -> {
316                    if (line.isEmpty() || line.startsWith("//")) {
317                        return; // comment or empty line
318                    }
319                    final String[] tokens = line.split(",\\s+");
320                    assertEquals(tokens.length, 4);
321                    final double v = Double.parseDouble(tokens[0]);
322                    final int digits = Integer.parseInt(tokens[1]);
323                    final String str = tokens[2].replace('"', ' ').trim();
324                    final int point = Integer.parseInt(tokens[3]);
325                    final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
326
327                    DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, digits, buffer);
328                    assertEquals(str, trimRepresentation(buffer.getRawDigits()));
329                    assertEquals(point, buffer.getDecimalPoint());
330                });
331    }
332
333    @Test
334    public void testBignumPrecision() {
335        new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-precision.txt")))
336                .lines()
337                .forEach(line -> {
338                    if (line.isEmpty() || line.startsWith("//")) {
339                        return; // comment or empty line
340                    }
341                    final String[] tokens = line.split(",\\s+");
342                    assertEquals(tokens.length, 4);
343                    final double v = Double.parseDouble(tokens[0]);
344                    final int digits = Integer.parseInt(tokens[1]);
345                    final String str = tokens[2].replace('"', ' ').trim();
346                    final int point = Integer.parseInt(tokens[3]);
347                    final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE);
348
349                    DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, digits, buffer);
350                    assertEquals(str, trimRepresentation(buffer.getRawDigits()));
351                    assertEquals(point, buffer.getDecimalPoint());
352                });
353    }
354
355}
356