1 /* 2 * Copyright (c) 2019, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8211936 27 * @summary Tests of BigDecimal.intValue() and BigDecimal.longValue() 28 */ 29 package test.java.math.BigDecimal; 30 31 import java.math.BigDecimal; 32 import java.util.Map; 33 34 public class IntegralValueTests { main(String... args)35 public static void main(String... args) { 36 int failures = 37 integralValuesTest(INT_VALUES, true) + 38 integralValuesTest(LONG_VALUES, false); 39 if (failures != 0) { 40 throw new RuntimeException 41 ("Incurred " + failures + " failures for {int,long}Value()."); 42 } 43 } 44 45 private static final Map<BigDecimal, Number> INT_VALUES = 46 Map.ofEntries( 47 48 // 2**31 - 1 49 Map.entry(new BigDecimal("2147483647"), Integer.MAX_VALUE), 50 Map.entry(new BigDecimal("2147483647.0"), Integer.MAX_VALUE), 51 Map.entry(new BigDecimal("2147483647.00"), Integer.MAX_VALUE), 52 53 Map.entry(new BigDecimal("-2147483647"), -Integer.MAX_VALUE), 54 Map.entry(new BigDecimal("-2147483647.0"), -Integer.MAX_VALUE), 55 56 // -2**31 57 Map.entry(new BigDecimal("-2147483648"), Integer.MIN_VALUE), 58 Map.entry(new BigDecimal("-2147483648.1"), Integer.MIN_VALUE), 59 Map.entry(new BigDecimal("-2147483648.01"), Integer.MIN_VALUE), 60 61 // -2**31 + 1 truncation to 2**31 - 1 62 Map.entry(new BigDecimal("-2147483649"), Integer.MAX_VALUE), 63 64 // 2**64 - 1 truncation to 1 65 Map.entry(new BigDecimal("4294967295"), -1), 66 67 // 2**64 truncation to 0 68 Map.entry(new BigDecimal("4294967296"), 0), 69 70 // Fast path truncation to 0 71 Map.entry(new BigDecimal("1e32"), 0), 72 73 // Slow path truncation to -2**31 74 Map.entry(new BigDecimal("1e31"), Integer.MIN_VALUE), 75 76 // Slow path 77 Map.entry(new BigDecimal("1e0"), 1), 78 79 // Fast path round to 0 80 Map.entry(new BigDecimal("9e-1"), 0), 81 82 // Some random values 83 Map.entry(new BigDecimal("900e-1"), 90), // Increasing negative exponents 84 Map.entry(new BigDecimal("900e-2"), 9), 85 Map.entry(new BigDecimal("900e-3"), 0), 86 87 // Fast path round to 0 88 Map.entry(new BigDecimal("123456789e-9"), 0), 89 90 // Slow path round to 1 91 Map.entry(new BigDecimal("123456789e-8"), 1), 92 93 // Increasing positive exponents 94 Map.entry(new BigDecimal("10000001e1"), 100000010), 95 Map.entry(new BigDecimal("10000001e10"), -1315576832), 96 Map.entry(new BigDecimal("10000001e100"), 0), 97 Map.entry(new BigDecimal("10000001e1000"), 0), 98 Map.entry(new BigDecimal("10000001e10000"), 0), 99 Map.entry(new BigDecimal("10000001e100000"), 0), 100 Map.entry(new BigDecimal("10000001e1000000"), 0), 101 Map.entry(new BigDecimal("10000001e10000000"), 0), 102 Map.entry(new BigDecimal("10000001e100000000"), 0), 103 Map.entry(new BigDecimal("10000001e1000000000"), 0), 104 105 // Increasing negative exponents 106 Map.entry(new BigDecimal("10000001e-1"), 1000000), 107 Map.entry(new BigDecimal("10000001e-10"), 0), 108 Map.entry(new BigDecimal("10000001e-100"), 0), 109 Map.entry(new BigDecimal("10000001e-1000"), 0), 110 Map.entry(new BigDecimal("10000001e-10000"), 0), 111 Map.entry(new BigDecimal("10000001e-100000"), 0), 112 Map.entry(new BigDecimal("10000001e-1000000"), 0), 113 Map.entry(new BigDecimal("10000001e-10000000"), 0), 114 Map.entry(new BigDecimal("10000001e-100000000"), 0), 115 Map.entry(new BigDecimal("10000001e-1000000000"), 0), 116 117 // Currency calculation to 4 places 118 Map.entry(new BigDecimal("12345.0001"), 12345), 119 Map.entry(new BigDecimal("12345.9999"), 12345), 120 Map.entry(new BigDecimal("-12345.0001"), -12345), 121 Map.entry(new BigDecimal("-12345.9999"), -12345)); 122 123 private static final Map<BigDecimal, Number> LONG_VALUES = 124 Map.ofEntries( 125 // 2**63 - 1 126 Map.entry(new BigDecimal("9223372036854775807"), Long.MAX_VALUE), 127 Map.entry(new BigDecimal("9223372036854775807.0"), Long.MAX_VALUE), 128 Map.entry(new BigDecimal("9223372036854775807.00"), Long.MAX_VALUE), 129 130 // 2**63 truncation to -2**63 131 Map.entry(new BigDecimal("-9223372036854775808"), Long.MIN_VALUE), 132 Map.entry(new BigDecimal("-9223372036854775808.1"), Long.MIN_VALUE), 133 Map.entry(new BigDecimal("-9223372036854775808.01"), Long.MIN_VALUE), 134 135 // -2**63 + 1 truncation to 2**63 - 1 136 Map.entry(new BigDecimal("-9223372036854775809"), 9223372036854775807L), 137 138 // 2**64 - 1 truncation to -1 139 Map.entry(new BigDecimal("18446744073709551615"), -1L), 140 141 // 2**64 truncation to 0 142 Map.entry(new BigDecimal("18446744073709551616"), 0L), 143 144 // Slow path truncation to -2**63 145 Map.entry(new BigDecimal("1e63"), -9223372036854775808L), 146 Map.entry(new BigDecimal("-1e63"), -9223372036854775808L), 147 // Fast path with larger magnitude scale 148 Map.entry(new BigDecimal("1e64"), 0L), 149 Map.entry(new BigDecimal("-1e64"), 0L), 150 Map.entry(new BigDecimal("1e65"), 0L), 151 Map.entry(new BigDecimal("-1e65"), 0L), 152 153 // Slow path 154 Map.entry(new BigDecimal("1e0"), 1L), 155 156 // Fast path round to 0 157 Map.entry(new BigDecimal("9e-1"), 0L), 158 159 // Some random values 160 Map.entry(new BigDecimal("900e-1"), 90L), // Increasing negative exponents 161 Map.entry(new BigDecimal("900e-2"), 9L), 162 Map.entry(new BigDecimal("900e-3"), 0L), 163 164 // Fast path round to 0 165 Map.entry(new BigDecimal("123456789e-9"), 0L), 166 167 // Slow path round to 1 168 Map.entry(new BigDecimal("123456789e-8"), 1L), 169 170 // Increasing positive exponents 171 Map.entry(new BigDecimal("10000001e1"), 100000010L), 172 Map.entry(new BigDecimal("10000001e10"), 100000010000000000L), 173 Map.entry(new BigDecimal("10000001e100"), 0L), 174 Map.entry(new BigDecimal("10000001e1000"), 0L), 175 Map.entry(new BigDecimal("10000001e10000"), 0L), 176 Map.entry(new BigDecimal("10000001e100000"), 0L), 177 Map.entry(new BigDecimal("10000001e1000000"), 0L), 178 Map.entry(new BigDecimal("10000001e10000000"), 0L), 179 Map.entry(new BigDecimal("10000001e100000000"), 0L), 180 Map.entry(new BigDecimal("10000001e1000000000"), 0L), 181 182 // Increasing negative exponents 183 Map.entry(new BigDecimal("10000001e-1"), 1000000L), 184 Map.entry(new BigDecimal("10000001e-10"), 0L), 185 Map.entry(new BigDecimal("10000001e-100"), 0L), 186 Map.entry(new BigDecimal("10000001e-1000"), 0L), 187 Map.entry(new BigDecimal("10000001e-10000"), 0L), 188 Map.entry(new BigDecimal("10000001e-100000"), 0L), 189 Map.entry(new BigDecimal("10000001e-1000000"), 0L), 190 Map.entry(new BigDecimal("10000001e-10000000"), 0L), 191 Map.entry(new BigDecimal("10000001e-100000000"), 0L), 192 Map.entry(new BigDecimal("10000001e-1000000000"), 0L), 193 194 // Currency calculation to 4 places 195 Map.entry(new BigDecimal("12345.0001"), 12345L), 196 Map.entry(new BigDecimal("12345.9999"), 12345L), 197 Map.entry(new BigDecimal("-12345.0001"), -12345L), 198 Map.entry(new BigDecimal("-12345.9999"), -12345L)); 199 integralValuesTest(Map<BigDecimal, Number> v, boolean isInt)200 private static int integralValuesTest(Map<BigDecimal, Number> v, boolean isInt) { 201 System.err.format("Testing %s%n", isInt ? "Integer" : "Long"); 202 int failures = 0; 203 for (var testCase : v.entrySet()) { 204 BigDecimal bd = testCase.getKey(); 205 Number expected = testCase.getValue(); 206 try { 207 if (isInt) { 208 int intValue = bd.intValue(); 209 if (intValue != (int)expected) { 210 failures += reportError(bd, expected, intValue, isInt); 211 } 212 } else { 213 long longValue = bd.longValue(); 214 if (longValue != (long)expected) { 215 failures += reportError(bd, expected, longValue, isInt); 216 } 217 } 218 } catch (Exception e) { 219 failures++; 220 System.err.format("Unexpected exception %s for %s%n", 221 e, bd.toString()); 222 } 223 } 224 return failures; 225 } 226 reportError(BigDecimal bd, Number expected, long longValue, boolean isInt)227 private static int reportError(BigDecimal bd, Number expected, long longValue, boolean isInt) { 228 // Android-changed: Avoid conditional expression since JLS 15.25.2 promotes Integer to Long. 229 // This patch can be upstreamed in the future. 230 // System.err.format("For %s, scale=%d, expected %d, actual %d, simple %d%n", 231 // bd.toString(), bd.scale(), 232 // (isInt ? (Integer) expected : (Long) expected ), 233 // longValue, 234 // (isInt ? simpleIntValue(bd): simpleLongValue(bd) )); 235 if (isInt) { 236 System.err.format("For %s, scale=%d, expected %d, actual %d, simple %d%n", 237 bd.toString(), bd.scale(), expected, longValue, simpleIntValue(bd)); 238 } else { 239 System.err.format("For %s, scale=%d, expected %d, actual %d, simple %d%n", 240 bd.toString(), bd.scale(), expected, longValue, simpleLongValue(bd)); 241 } 242 return 1; 243 } 244 simpleLongValue(BigDecimal bd)245 private static long simpleLongValue(BigDecimal bd) { 246 return bd.toBigInteger().longValue(); 247 } 248 simpleIntValue(BigDecimal bd)249 private static int simpleIntValue(BigDecimal bd) { 250 return bd.toBigInteger().intValue(); 251 } 252 } 253