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