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