1 /*
   2  * Copyright 2003-2005 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  */
  23 /*
  24  * @test
  25  * @bug 4904082 4917089 6337226
  26  * @summary Tests that integral division and related methods return the proper result and scale.
  27  * @author Joseph D. Darcy
  28  * @compile -source 1.5 IntegralDivisionTests.java
  29  * @run main IntegralDivisionTests
  30  */
  31 import java.math.*;
  32 public class IntegralDivisionTests {
  33 
  34     static int dividetoIntegralValueTests() {
  35         int failures = 0;
  36 
  37         // Exact integer quotient should have the same results from
  38         // the exact divide and dividetoIntegralValue
  39 
  40 
  41         // Rounded results
  42         BigDecimal [][] moreTestCases = {
  43             {new BigDecimal("11003"),   new BigDecimal("10"),   new BigDecimal("1100")},
  44             {new BigDecimal("11003"),   new BigDecimal("1e1"),  new BigDecimal("1100.0")},
  45             {new BigDecimal("1e9"),     new BigDecimal("1"),    new BigDecimal("1e9")},
  46             {new BigDecimal("1e9"),     new BigDecimal("1.00"), new BigDecimal("1e9")},
  47             {new BigDecimal("1e9"),     new BigDecimal("0.1"),  new BigDecimal("1e10")},
  48             {new BigDecimal("10e8"),    new BigDecimal("0.1"),  new BigDecimal("10e9")},
  49             {new BigDecimal("400e1"),   new BigDecimal("5"),    new BigDecimal("80e1")},
  50             {new BigDecimal("400e1"),   new BigDecimal("4.999999999"),  new BigDecimal("8e2")},
  51             {new BigDecimal("40e2"),    new BigDecimal("5"),    new BigDecimal("8e2")},
  52         };
  53 
  54         for(BigDecimal [] testCase: moreTestCases) {
  55             BigDecimal quotient;
  56             if (! (quotient=testCase[0].divideToIntegralValue(testCase[1])).equals(testCase[2]) ){
  57                 failures++;
  58                 // BigDecimal exact = testCase[0].divide(testCase[1]);
  59                 System.err.println();
  60                 System.err.println("dividend  = " + testCase[0] + " scale = " + testCase[0].scale());
  61                 System.err.println("divisor   = " + testCase[1] + " scale = " + testCase[1].scale());
  62                 System.err.println("quotient  = " + quotient    + " scale = " + quotient.scale());
  63                 System.err.println("expected  = " + testCase[2] + " scale = " + testCase[2].scale());
  64                 // System.err.println("exact     = " + exact       + " scale = " + exact.scale());
  65             }
  66         }
  67 
  68         return failures;
  69     }
  70 
  71     static int dividetoIntegralValueRoundedTests() {
  72         int failures = 0;
  73 
  74         BigDecimal dividend = new BigDecimal("11003");
  75         BigDecimal divisor = new BigDecimal("10");
  76         BigDecimal [] quotients = {     // Expected results with precision =
  77             new BigDecimal("1100"),     // 0
  78             null,                       // 1
  79             new BigDecimal("11e2"),     // 2
  80             new BigDecimal("110e1"),    // 3
  81             new BigDecimal("1100"),     // 4
  82         };
  83         failures += divideContextTestPrecs(dividend, divisor, quotients);
  84 
  85         dividend = new BigDecimal("11003");
  86         divisor = new BigDecimal("1e1");
  87         BigDecimal [] quotients2 = {    // Expected results with precision =
  88             new BigDecimal("1100.0"),   // 0
  89             null,                       // 1
  90             new BigDecimal("11e2"),     // 2
  91             new BigDecimal("110e1"),    // 3
  92             new BigDecimal("1100"),     // 4
  93             new BigDecimal("1100.0"),   // 5
  94         };
  95         failures += divideContextTestPrecs(dividend, divisor, quotients2);
  96 
  97         dividend = new BigDecimal("1230000");
  98         divisor = new BigDecimal("100");
  99         BigDecimal [] quotients3 = {    // Expected results with precision =
 100             new BigDecimal("12300"),    // 0
 101             null,                       // 1
 102             null,                       // 2
 103             new BigDecimal("123e2"),    // 3
 104             new BigDecimal("1230e1"),   // 4
 105             new BigDecimal("12300"),    // 5
 106         };
 107         failures += divideContextTestPrecs(dividend, divisor, quotients3);
 108 
 109         dividend = new BigDecimal("33");
 110         divisor  = new BigDecimal("3");
 111         BigDecimal [] quotients4 = {    // Expected results with precision =
 112             new BigDecimal("11"),       // 0
 113             null,                       // 1
 114             new BigDecimal("11"),       // 2
 115             new BigDecimal("11"),       // 3
 116         };
 117         failures += divideContextTestPrecs(dividend, divisor, quotients4);
 118 
 119         dividend = new BigDecimal("34");
 120         divisor  = new BigDecimal("3");
 121         BigDecimal [] quotients5 = {    // Expected results with precision =
 122             new BigDecimal("11"),       // 0
 123             null,                       // 1
 124             new BigDecimal("11"),       // 2
 125             new BigDecimal("11"),       // 3
 126         };
 127         failures += divideContextTestPrecs(dividend, divisor, quotients5);
 128 
 129         return failures;
 130     }
 131 
 132     static int divideContextTestPrecs(BigDecimal dividend,
 133                                       BigDecimal divisor,
 134                                       BigDecimal[] quotients)
 135     {
 136         int failures = 0;
 137         for(int i = 0; i < quotients.length; i++) {
 138             BigDecimal result = null;
 139             BigDecimal quotient = quotients[i];
 140 
 141             try {
 142                 result = dividend.divideToIntegralValue(divisor,
 143                                                         new MathContext(i, RoundingMode.DOWN));
 144             } catch (ArithmeticException e) {
 145                 if (quotient != null) {
 146                     failures++;
 147                     System.err.println();
 148                     System.err.println("Unexpected exception:");
 149                     System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
 150                     System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
 151                     System.err.println("expected  = " + quotient     + " scale = " + quotient.scale());
 152                 }
 153             }
 154 
 155             if (quotient != null) {
 156                 if (! result.equals(quotient)) {
 157                     failures++;
 158                     System.err.println();
 159                     System.err.println("Unexpected result:");
 160                     System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
 161                     System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
 162                     System.err.println("quotient  = " + result       + " scale = " + result.scale());
 163                     System.err.println("expected  = " + quotient     + " scale = " + quotient.scale());
 164                     System.err.println("precision = " + i);
 165                 }
 166             } else {
 167                 if (result != null) {
 168                     failures++;
 169                     System.err.println();
 170                     System.err.println("Unexpected unexceptional result:");
 171                     System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
 172                     System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
 173                     System.err.println("quotient  = " + result       + " scale = " + result.scale());
 174                     System.err.println("precision = " + i);
 175                 }
 176             }
 177 
 178         }
 179         return failures;
 180     }
 181 
 182 
 183     static int divideContextTests(BigDecimal dividend,
 184                                   BigDecimal divisor,
 185                                   BigDecimal expected,
 186                                   MathContext mc) {
 187         int failures = 0;
 188 
 189         failures += divideContextTest(dividend,              divisor,          expected,                mc);
 190         failures += divideContextTest(dividend.negate(),     divisor.negate(), expected,                mc);
 191 
 192         if (expected != null) {
 193             failures += divideContextTest(dividend.negate(), divisor,          expected.negate(),       mc);
 194             failures += divideContextTest(dividend,          divisor.negate(), expected.negate(),       mc);
 195         }
 196 
 197         return failures;
 198     }
 199 
 200 
 201     static int divideContextTest(BigDecimal dividend,
 202                                  BigDecimal divisor,
 203                                  BigDecimal expected,
 204                                  MathContext mc)
 205     {
 206         int failures = 0;
 207 
 208         BigDecimal result = null;
 209 
 210         try {
 211             result = dividend.divideToIntegralValue(divisor, mc);
 212         } catch (ArithmeticException e) {
 213             if (expected != null) {
 214                 failures++;
 215                 System.err.println();
 216                 System.err.println("Unexpected exception:");
 217                 System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
 218                 System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
 219                 System.err.println("expected  = " + expected     + " scale = " + expected.scale());
 220                 System.err.println("MathContext  = " + mc);
 221             }
 222         }
 223 
 224         if (expected != null) {
 225             if (! result.equals(expected)) {
 226                 failures++;
 227                 System.err.println();
 228                 System.err.println("Unexpected result:");
 229                 System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
 230                 System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
 231                 System.err.println("expected  = " + expected     + " scale = " + expected.scale());
 232                 System.err.println("result    = " + result       + " scale = " + result.scale());
 233                 System.err.println("MathContext  = " + mc);
 234             }
 235         } else {
 236             if (result != null) {
 237                 failures++;
 238                 System.err.println();
 239                 System.err.println("Unexpected unexceptional result:");
 240                 System.err.println("dividend  = " + dividend     + " scale = " + dividend.scale());
 241                 System.err.println("divisor   = " + divisor      + " scale = " + divisor.scale());
 242                 System.err.println("quotient  = " + result       + " scale = " + result.scale());
 243                 System.err.println("MathConext = " + mc);
 244                 }
 245         }
 246 
 247         return failures;
 248     }
 249 
 250     static int dividetoIntegralValueScalingTests() {
 251         int failures = 0;
 252 
 253         BigDecimal dividend = new BigDecimal("123456789000");
 254         BigDecimal divisor = BigDecimal.ONE;
 255         BigDecimal expected = new BigDecimal("123456789e3");
 256         MathContext mc = new MathContext(9,RoundingMode.DOWN);
 257         failures += divideContextTests(dividend, divisor, expected, mc);
 258 
 259 
 260         // 100/3 = 33 remainder 1
 261         int [] precisions = {0, 2, 3, 4};
 262         dividend = new BigDecimal(100);
 263         divisor  = new BigDecimal(3);
 264         expected = new BigDecimal(33);
 265 
 266         for(RoundingMode rm: RoundingMode.values())
 267             for(int precision: precisions) {
 268                 failures += divideContextTests(dividend, divisor, expected,
 269                                                new MathContext(precision, rm));
 270             }
 271 
 272         // 123000/10 = 12300 remainder 0
 273         dividend = new BigDecimal(123000);
 274         divisor  = new BigDecimal(10);
 275         int[] precisions1 = {0, 1, 2, 3, 4, 5};
 276         BigDecimal[] expected1 = {
 277             new BigDecimal("12300"),
 278             null,
 279             null,
 280             new BigDecimal("123e2"),
 281             new BigDecimal("1230e1"),
 282             new BigDecimal("12300"),
 283         };
 284 
 285         for(RoundingMode rm: RoundingMode.values())
 286             for(int i = 0; i < precisions1.length; i++) {
 287                 failures += divideContextTests(dividend, divisor,
 288                                                expected1[i],
 289                                                new MathContext(precisions1[i], rm));
 290             }
 291 
 292         // 123e3/10 = 123e2 remainder 0
 293         dividend = new BigDecimal("123e3");
 294         divisor  = new BigDecimal(10);
 295         int[] precisions2 = {0, 1, 2, 3, 4, 5};
 296         BigDecimal[] expected2 = {
 297             new BigDecimal("123e2"),
 298             null,
 299             null,
 300             new BigDecimal("123e2"),
 301             new BigDecimal("123e2"),
 302             new BigDecimal("123e2"),
 303         };
 304 
 305         for(RoundingMode rm: RoundingMode.values())
 306             for(int i = 0; i < precisions2.length; i++) {
 307                 failures += divideContextTests(dividend, divisor,
 308                                                expected2[i],
 309                                                new MathContext(precisions2[i], rm));
 310             }
 311 
 312 
 313         // 123000/1e1 = 12300.0 remainder 0
 314         dividend = new BigDecimal("123000");
 315         divisor  = new BigDecimal("1e1");
 316         int[] precisions3 = {0, 1, 2, 3, 4, 5, 6};
 317         BigDecimal[] expected3 = {
 318             new BigDecimal("12300.0"),
 319             null,
 320             null,
 321             new BigDecimal("123e2"),
 322             new BigDecimal("1230e1"),
 323             new BigDecimal("12300"),
 324             new BigDecimal("12300.0"),
 325         };
 326 
 327         for(RoundingMode rm: RoundingMode.values())
 328             for(int i = 0; i < precisions3.length; i++) {
 329                 failures += divideContextTests(dividend, divisor,
 330                                                expected3[i],
 331                                                new MathContext(precisions3[i], rm));
 332             }
 333 
 334 
 335 
 336         return failures;
 337     }
 338 
 339     public static void main(String argv[]) {
 340         int failures = 0;
 341 
 342         failures += dividetoIntegralValueTests();
 343         failures += dividetoIntegralValueRoundedTests();
 344         failures += dividetoIntegralValueScalingTests();
 345 
 346         if (failures > 0) {
 347             System.err.println("Encountered " + failures +
 348                                " failures while testing integral division.");
 349             throw new RuntimeException();
 350         }
 351     }
 352 }