1 /* 2 * Copyright (c) 2003, 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 package test.java.math.BigDecimal; 24 25 /* 26 * @test 27 * @bug 4902952 4905407 4916149 8057793 28 * @summary Tests that the scale of zero is propagated properly and has the 29 * proper effect and that setting the scale to zero does not mutate the 30 * BigDecimal. 31 * @author Joseph D. Darcy 32 */ 33 34 import java.math.*; 35 import java.util.*; 36 37 import org.testng.Assert; 38 import org.testng.annotations.Test; 39 40 // Android-changed: Replace error counting with asserts. 41 public class ZeroScalingTests { 42 43 static MathContext longEnough = new MathContext(50, RoundingMode.UNNECESSARY); 44 45 static BigDecimal[] zeros = new BigDecimal[23]; 46 static { 47 for(int i = 0; i < 21; i++) { 48 zeros[i] = new BigDecimal(BigInteger.ZERO, i-10); 49 } 50 zeros[21] = new BigDecimal(BigInteger.ZERO, Integer.MIN_VALUE); 51 zeros[22] = new BigDecimal(BigInteger.ZERO, Integer.MAX_VALUE); 52 } 53 54 static BigDecimal element = BigDecimal.valueOf(100, -2); 55 56 static MathContext[] contexts = { 57 new MathContext(0, RoundingMode.UNNECESSARY), 58 new MathContext(100, RoundingMode.UNNECESSARY), 59 new MathContext(5, RoundingMode.UNNECESSARY), 60 new MathContext(4, RoundingMode.UNNECESSARY), 61 new MathContext(3, RoundingMode.UNNECESSARY), 62 new MathContext(2, RoundingMode.UNNECESSARY), 63 new MathContext(1, RoundingMode.UNNECESSARY), 64 }; 65 66 67 @Test addTests()68 public void addTests() { 69 for(BigDecimal zero1: zeros) { 70 for(BigDecimal zero2: zeros) { 71 BigDecimal expected = new BigDecimal(BigInteger.ZERO, 72 Math.max(zero1.scale(), zero2.scale())); 73 BigDecimal result = zero1.add(zero2); 74 75 Assert.assertEquals(result, expected, "For classic exact add, expected scale of " + 76 expected.scale() + "; got " + 77 result.scale() + "."); 78 79 result = zero1.add(zero2, MathContext.UNLIMITED); 80 Assert.assertEquals(result, expected, "For UNLIMITED math context add," + 81 " expected scale of " + 82 expected.scale() + "; got " + 83 result.scale() + "."); 84 85 result = zero1.add(zero2, longEnough); 86 Assert.assertEquals(result, expected, "For longEnough math context add," + 87 " expected scale of " + 88 expected.scale() + "; got " + 89 result.scale() + "."); 90 } 91 } 92 93 // Test effect of adding zero to a nonzero value. 94 for (MathContext mc: contexts) { 95 for (BigDecimal zero: zeros) { 96 if (Math.abs((long)zero.scale()) < 100 ) { 97 98 int preferredScale = Math.max(zero.scale(), element.scale()); 99 if (mc.getPrecision() != 0) { 100 if (preferredScale < -4 ) 101 preferredScale = -4; 102 else if (preferredScale > -(5 - mc.getPrecision())) { 103 preferredScale = -(5 - mc.getPrecision()); 104 } 105 } 106 107 BigDecimal result = element.add(zero, mc); 108 Assert.assertFalse(result.scale() != preferredScale || 109 result.compareTo(element) != 0, 110 "Expected scale " + preferredScale + 111 " result scale was " + result.scale() + 112 " ; value was " + result); 113 114 result = zero.add(element, mc); 115 Assert.assertFalse(result.scale() != preferredScale || 116 result.compareTo(element) != 0, 117 "Expected scale " + preferredScale + 118 " result scale was " + result.scale() + 119 " ; value was " + result); 120 121 result = element.negate().add(zero, mc); 122 Assert.assertFalse(result.scale() != preferredScale || 123 result.compareTo(element.negate()) != 0, 124 "Expected scale " + preferredScale + 125 " result scale was " + result.scale() + 126 " ; value was " + result); 127 128 result = zero.add(element.negate(), mc); 129 Assert.assertFalse(result.scale() != preferredScale || 130 result.compareTo(element.negate()) != 0, 131 "Expected scale " + preferredScale + 132 " result scale was " + result.scale() + 133 " ; value was " + result); 134 } 135 } 136 } 137 } 138 139 @Test subtractTests()140 public void subtractTests() { 141 for(BigDecimal zero1: zeros) { 142 for(BigDecimal zero2: zeros) { 143 BigDecimal expected = new BigDecimal(BigInteger.ZERO, 144 Math.max(zero1.scale(), zero2.scale())); 145 BigDecimal result = zero1.subtract(zero2); 146 147 Assert.assertEquals(result, expected, 148 "For classic exact subtract, expected scale of " + 149 expected.scale() + "; got " + 150 result.scale() + "."); 151 152 result = zero1.subtract(zero2, MathContext.UNLIMITED); 153 Assert.assertEquals(result, expected, "For UNLIMITED math context subtract," + 154 " expected scale of " + 155 expected.scale() + "; got " + 156 result.scale() + "."); 157 158 result = zero1.subtract(zero2, longEnough); 159 Assert.assertEquals(result, expected, "For longEnough math context subtract," + 160 " expected scale of " + 161 expected.scale() + "; got " + 162 result.scale() + "."); 163 } 164 } 165 166 167 // Test effect of adding zero to a nonzero value. 168 for (MathContext mc: contexts) { 169 for (BigDecimal zero: zeros) { 170 if (Math.abs((long)zero.scale()) < 100 ) { 171 172 int preferredScale = Math.max(zero.scale(), element.scale()); 173 if (mc.getPrecision() != 0) { 174 if (preferredScale < -4 ) 175 preferredScale = -4; 176 else if (preferredScale > -(5 - mc.getPrecision())) { 177 preferredScale = -(5 - mc.getPrecision()); 178 } 179 } 180 181 BigDecimal result = element.subtract(zero, mc); 182 Assert.assertFalse(result.scale() != preferredScale || 183 result.compareTo(element) != 0, 184 "Expected scale " + preferredScale + 185 " result scale was " + result.scale() + 186 " ; value was " + result); 187 188 result = zero.subtract(element, mc); 189 Assert.assertFalse(result.scale() != preferredScale || 190 result.compareTo(element.negate()) != 0, 191 "Expected scale " + preferredScale + 192 " result scale was " + result.scale() + 193 " ; value was " + result); 194 195 result = element.negate().subtract(zero, mc); 196 Assert.assertFalse(result.scale() != preferredScale || 197 result.compareTo(element.negate()) != 0, 198 "Expected scale " + preferredScale + 199 " result scale was " + result.scale() + 200 " ; value was " + result); 201 202 result = zero.subtract(element.negate(), mc); 203 Assert.assertFalse(result.scale() != preferredScale || 204 result.compareTo(element) != 0, 205 "Expected scale " + preferredScale + 206 " result scale was " + result.scale() + 207 " ; value was " + result); 208 } 209 } 210 } 211 } 212 213 @Test multiplyTests()214 public void multiplyTests() { 215 BigDecimal[] ones = { 216 BigDecimal.valueOf(1, 0), 217 BigDecimal.valueOf(10, 1), 218 BigDecimal.valueOf(1000, 3), 219 BigDecimal.valueOf(100000000, 8), 220 }; 221 222 List<BigDecimal> values = new LinkedList<BigDecimal>(); 223 values.addAll(Arrays.asList(zeros)); 224 values.addAll(Arrays.asList(ones)); 225 226 for(BigDecimal zero1: zeros) { 227 for(BigDecimal value: values) { 228 BigDecimal expected = new BigDecimal(BigInteger.ZERO, 229 (int)Math.min(Math.max((long)zero1.scale()+value.scale(), 230 Integer.MIN_VALUE ), 231 Integer.MAX_VALUE ) ); 232 BigDecimal result = zero1.multiply(value); 233 234 Assert.assertEquals(result, expected, 235 "For classic exact multiply, expected scale of " + 236 expected.scale() + "; got " + 237 result.scale() + "."); 238 239 result = zero1.multiply(value, MathContext.UNLIMITED); 240 Assert.assertEquals(result, expected, "For UNLIMITED math context multiply," + 241 " expected scale of " + 242 expected.scale() + "; got " + 243 result.scale() + "."); 244 245 result = zero1.multiply(value, longEnough); 246 Assert.assertEquals(result, expected, "For longEnough math context multiply," + 247 " expected scale of " + 248 expected.scale() + "; got " + 249 result.scale() + "."); 250 } 251 } 252 } 253 254 @Test divideTests()255 public void divideTests() { 256 BigDecimal [] ones = { 257 BigDecimal.valueOf(1, 0), 258 BigDecimal.valueOf(10, -1), 259 BigDecimal.valueOf(100, -2), 260 BigDecimal.valueOf(1000, -3), 261 BigDecimal.valueOf(1000000, -5), 262 }; 263 264 for(BigDecimal one: ones) { 265 for(BigDecimal zero: zeros) { 266 BigDecimal expected = new BigDecimal(BigInteger.ZERO, 267 (int)Math.min(Math.max((long)zero.scale() - one.scale(), 268 Integer.MIN_VALUE ), 269 Integer.MAX_VALUE ) ); 270 BigDecimal result = zero.divide(one); 271 272 Assert.assertEquals(result, expected, "For classic exact divide, expected scale of " + 273 expected.scale() + "; got " + 274 result.scale() + "."); 275 276 result = zero.divide(one, MathContext.UNLIMITED); 277 Assert.assertEquals(result, expected, "For UNLIMITED math context divide," + 278 " expected scale of " + 279 expected.scale() + "; got " + 280 result.scale() + "."); 281 282 result = zero.divide(one, longEnough); 283 Assert.assertEquals(result, expected, "For longEnough math context divide," + 284 " expected scale of " + 285 expected.scale() + "; got " + 286 result.scale() + "."); 287 } 288 } 289 } 290 291 @Test setScaleTests()292 public void setScaleTests() { 293 int[] scales = { 294 Integer.MIN_VALUE, 295 Integer.MIN_VALUE+1, 296 -10000000, 297 -3, 298 -2, 299 -1, 300 0, 301 1, 302 2, 303 3, 304 10, 305 10000000, 306 Integer.MAX_VALUE-1, 307 Integer.MAX_VALUE 308 }; 309 310 for(BigDecimal zero: zeros) { 311 for(int scale: scales) { 312 try { 313 BigDecimal bd = zero.setScale(scale); 314 } 315 catch (ArithmeticException e) { 316 Assert.fail("Exception when trying to set a scale of " + scale + " on " + zero); 317 } 318 } 319 } 320 } 321 322 @Test toEngineeringStringTests()323 public void toEngineeringStringTests() { 324 String [][] testCases = { 325 {"0E+10", "0.00E+12"}, 326 {"0E+9", "0E+9"}, 327 {"0E+8", "0.0E+9"}, 328 {"0E+7", "0.00E+9"}, 329 330 {"0E-10", "0.0E-9"}, 331 {"0E-9", "0E-9"}, 332 {"0E-8", "0.00E-6"}, 333 {"0E-7", "0.0E-6"}, 334 }; 335 336 for(String[] testCase: testCases) { 337 BigDecimal bd = new BigDecimal(testCase[0]); 338 String result = bd.toEngineeringString(); 339 340 Assert.assertFalse(!result.equals(testCase[1]) || !bd.equals(new BigDecimal(result)), 341 "From input ``" + testCase[0] + ",'' " + 342 " bad engineering string output ``" + result + 343 "''; expected ``" + testCase[1] + ".''"); 344 } 345 } 346 347 @Test ulpTests()348 public void ulpTests() { 349 for(BigDecimal zero: zeros) { 350 BigDecimal result; 351 BigDecimal expected = BigDecimal.valueOf(1, zero.scale()); 352 353 result = zero.ulp(); 354 Assert.assertEquals(result, expected, "Unexpected ulp value for zero value " + 355 zero + "; expected " + expected + 356 ", got " + result); 357 } 358 } 359 360 @Test setScaleDoesNotMutateTest()361 public void setScaleDoesNotMutateTest() { 362 BigDecimal total = new BigDecimal("258815507198903607775511093103396443816569106750031264155319238473795838680758514810110764742309284477206138527975952150289602995045050194333030191178778772026538699925775139201970526695485362661420908248887297829319881475178467494779683293036572059595504702727301324759997409522995072582369210284334718757260859794972695026582432867589093687280300148141501712013226636373167978223780290547640482160818746599330924736802844173226042389174403401903999447463440670236056324929325189403433689" 363 + ".426167432065785331444814035799717606745777287606858873045971898862329763544687891847664736523584843544347118836628373041412918374550458884706686730726101338872517021688769782894793734049819222924171842793485919753186993388451909096042127903835765393729547730953942175461146061715108701615615142134282261293656760570061554783195726716403304101469782303957325142638493327692352838806741611887655695029948975509680496573999174402058593454203190963443179532640446352828089016874853634851387762579319853267317320515941105912189838719919259277721994880193541634872882180184303434360412344059435559680494807415573269199203376126242271766939666939316648575065702750502798973418978204972336924254702551350654650573582614211506856383897692911422458286912085339575875324832979140870119455620532272318122103640233069115700020760625493816902806241630788230268031695140687964931377988962507263990468276009750998066442971308866347136022907166625330623130307555914930120150437900510530537258665172619821272937026713977709974434967165159545592482710663639966781678268622620229577009317698254134914742098420792313931843709810905414336383757407675429663714210967924767434203021205270369316797752411974617662200898086335322218191674846795163102021505555508444216708745911194321674887527227200297039471799580744303346354057273540730643842091810899490590914195225087593013834388801018488174855060306804024894292757613618190472234110859436472645203753139820658279559340251226992556744343475086923568365637919479462424794554522865559888240039662899509652221329892034706445253487898044421278283079233226845124525434586324657471286953226255430662125870993375281512713207125720748163498642795960457639954616530163959004770092547297392499137383176609646505351001304840762905826237024982330597805063521162285806541220110524989649256399233792799406995068469271941269511818994954109392839548141262324660472253632382325038836831429045617036015122388070240133760858500132713255407855625837956886349324981003917084922808187223285051144454915441134217743066575863563572152133978905444998209075763950909784148142018992367290485890072303179512881131769414783097454103103347826517701720263541869335631166977965013552647906729408522950996105479525445916501155305220090853891226367184989434453290788068397817927893708837722255115237672194162924260945492012622891770365546831236789867922136747819364833843397165107825773447549885351449899330007200651144003961228091210630807333236718793283427788965479074476288255387824982443633190938302785760754436525586544523339170400053128503337395428393881357669568532722167493096151221381017320147344991331421789379785964440840684363041795410525097564979585773948558651896834067324427900848255265001498890329859444233861478388742393060996236783742654761350763876989363052609107226398858310051497856931093693697981165801539060516895227818925342535261227134364063673285588256280386915163875872231395348293505967057794409379709079685798908660258077792158532257603211711587587586356431658240229896344639704"); 364 365 Assert.assertEquals(total.setScale(0, RoundingMode.DOWN), 366 total.setScale(0, RoundingMode.DOWN)); 367 } 368 } 369