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 58 package jdk.nashorn.internal.runtime.doubleconv.test; 59 60 import java.io.BufferedReader; 61 import java.io.InputStreamReader; 62 import jdk.nashorn.internal.runtime.doubleconv.DoubleConversion; 63 import jdk.nashorn.internal.runtime.doubleconv.DtoaBuffer; 64 import jdk.nashorn.internal.runtime.doubleconv.DtoaMode; 65 66 import org.testng.annotations.Test; 67 68 import static org.testng.Assert.assertEquals; 69 import static org.testng.Assert.assertTrue; 70 71 /** 72 * BignumDtoa tests 73 */ 74 @SuppressWarnings("javadoc") 75 public 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 DoubleConversion.bignumDtoa(1e-23, DtoaMode.SHORTEST, 0, buffer); 224 assertEquals("1", buffer.getRawDigits()); 225 assertEquals(-22, buffer.getDecimalPoint()); 226 buffer.reset(); 227 228 final long smallest_normal64 = 0x0010000000000000L; 229 double v = Double.longBitsToDouble(smallest_normal64); 230 DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer); 231 assertEquals("22250738585072014", buffer.getRawDigits()); 232 assertEquals(-307, buffer.getDecimalPoint()); 233 buffer.reset(); 234 235 DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 20, buffer); 236 assertTrue(20 >= buffer.getLength()); 237 assertEquals("22250738585072013831", trimRepresentation(buffer.getRawDigits())); 238 assertEquals(-307, buffer.getDecimalPoint()); 239 buffer.reset(); 240 241 final long largest_denormal64 = 0x000FFFFFFFFFFFFFL; 242 v = Double.longBitsToDouble(largest_denormal64); 243 DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer); 244 assertEquals("2225073858507201", buffer.getRawDigits()); 245 assertEquals(-307, buffer.getDecimalPoint()); 246 buffer.reset(); 247 248 DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 20, buffer); 249 assertTrue(20 >= buffer.getLength()); 250 assertEquals("2225073858507200889", trimRepresentation(buffer.getRawDigits())); 251 assertEquals(-307, buffer.getDecimalPoint()); 252 buffer.reset(); 253 254 DoubleConversion.bignumDtoa(4128420500802942e-24, DtoaMode.SHORTEST, 0, buffer); 255 assertEquals("4128420500802942", buffer.getRawDigits()); 256 assertEquals(-8, buffer.getDecimalPoint()); 257 buffer.reset(); 258 259 DoubleConversion.bignumDtoa(3.9292015898194142585311918e-10, DtoaMode.SHORTEST, 0, buffer); 260 assertEquals("39292015898194143", buffer.getRawDigits()); 261 buffer.reset(); 262 263 v = 4194304.0; 264 DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, 5, buffer); 265 assertTrue(5 >= buffer.getLength() - buffer.getDecimalPoint()); 266 assertEquals("4194304", trimRepresentation(buffer.getRawDigits())); 267 buffer.reset(); 268 269 v = 3.3161339052167390562200598e-237; 270 DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 19, buffer); 271 assertTrue(19 >= buffer.getLength()); 272 assertEquals("3316133905216739056", trimRepresentation(buffer.getRawDigits())); 273 assertEquals(-236, buffer.getDecimalPoint()); 274 buffer.reset(); 275 276 v = 7.9885183916008099497815232e+191; 277 DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, 4, buffer); 278 assertTrue(4 >= buffer.getLength()); 279 assertEquals("7989", trimRepresentation(buffer.getRawDigits())); 280 assertEquals(192, buffer.getDecimalPoint()); 281 buffer.reset(); 282 283 v = 1.0000000000000012800000000e+17; 284 DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, 1, buffer); 285 assertTrue(1 >= buffer.getLength() - buffer.getDecimalPoint()); 286 assertEquals("100000000000000128", trimRepresentation(buffer.getRawDigits())); 287 assertEquals(18, buffer.getDecimalPoint()); 288 buffer.reset(); 289 } 290 291 292 @Test 293 public void testBignumShortest() { 294 new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-shortest.txt"))) 295 .lines() 296 .forEach(line -> { 297 if (line.isEmpty() || line.startsWith("//")) { 298 return; // comment or empty line 299 } 300 final String[] tokens = line.split(",\\s+"); 301 assertEquals(tokens.length, 3, "*" + line + "*"); 302 final double v = Double.parseDouble(tokens[0]); 303 final String str = tokens[1].replace('"', ' ').trim();; 304 final int point = Integer.parseInt(tokens[2]); 305 final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE); 306 307 DoubleConversion.bignumDtoa(v, DtoaMode.SHORTEST, 0, buffer); 308 assertEquals(str, buffer.getRawDigits()); 309 assertEquals(point, buffer.getDecimalPoint()); 310 }); 311 } 312 313 @Test 314 public void testBignumFixed() { 315 new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-fixed.txt"))) 316 .lines() 317 .forEach(line -> { 318 if (line.isEmpty() || line.startsWith("//")) { 319 return; // comment or empty line 320 } 321 final String[] tokens = line.split(",\\s+"); 322 assertEquals(tokens.length, 4); 323 final double v = Double.parseDouble(tokens[0]); 324 final int digits = Integer.parseInt(tokens[1]); 325 final String str = tokens[2].replace('"', ' ').trim(); 326 final int point = Integer.parseInt(tokens[3]); 327 final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE); 328 329 DoubleConversion.bignumDtoa(v, DtoaMode.FIXED, digits, buffer); 330 assertEquals(str, trimRepresentation(buffer.getRawDigits())); 331 assertEquals(point, buffer.getDecimalPoint()); 332 }); 333 } 334 335 @Test 336 public void testBignumPrecision() { 337 new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("resources/gay-precision.txt"))) 338 .lines() 339 .forEach(line -> { 340 if (line.isEmpty() || line.startsWith("//")) { 341 return; // comment or empty line 342 } 343 final String[] tokens = line.split(",\\s+"); 344 assertEquals(tokens.length, 4); 345 final double v = Double.parseDouble(tokens[0]); 346 final int digits = Integer.parseInt(tokens[1]); 347 final String str = tokens[2].replace('"', ' ').trim(); 348 final int point = Integer.parseInt(tokens[3]); 349 final DtoaBuffer buffer = new DtoaBuffer(BUFFER_SIZE); 350 351 DoubleConversion.bignumDtoa(v, DtoaMode.PRECISION, digits, buffer); 352 assertEquals(str, trimRepresentation(buffer.getRawDigits())); 353 assertEquals(point, buffer.getDecimalPoint()); 354 }); 355 } 356 357 }