1 /*
   2  * Copyright (c) 2012, 2016, 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 import java.math.BigDecimal;
  25 import java.math.RoundingMode;
  26 
  27 /**
  28  * @test Test Math and StrictMath Floor Div / Modulo operations.
  29  * @bug 6282196
  30  * @summary Basic tests for Floor division and modulo methods for both Math
  31  * and StrictMath for int and long datatypes.
  32  */
  33 public class DivModTests {
  34 
  35     /**
  36      * The count of test errors.
  37      */
  38     private static int errors = 0;
  39 
  40     /**
  41      * @param args the command line arguments are unused
  42      */
  43     public static void main(String[] args) {
  44         errors = 0;
  45         testIntFloorDivMod();
  46         testLongFloorDivMod();
  47 
  48         if (errors > 0) {
  49             throw new RuntimeException(errors + " errors found in DivMod methods.");
  50         }
  51     }
  52 
  53     /**
  54      * Report a test failure and increment the error count.
  55      * @param message the formatting string
  56      * @param args the variable number of arguments for the message.
  57      */
  58     static void fail(String message, Object... args) {
  59         errors++;
  60         System.out.printf(message, args);
  61     }
  62 
  63     /**
  64      * Test the integer floorDiv and floorMod methods.
  65      * Math and StrictMath tested and the same results are expected for both.
  66      */
  67     static void testIntFloorDivMod() {
  68         testIntFloorDivMod(4, 0, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException
  69         testIntFloorDivMod(4, 3, 1, 1);
  70         testIntFloorDivMod(3, 3, 1, 0);
  71         testIntFloorDivMod(2, 3, 0, 2);
  72         testIntFloorDivMod(1, 3, 0, 1);
  73         testIntFloorDivMod(0, 3, 0, 0);
  74         testIntFloorDivMod(4, -3, -2, -2);
  75         testIntFloorDivMod(3, -3, -1, 0);
  76         testIntFloorDivMod(2, -3, -1, -1);
  77         testIntFloorDivMod(1, -3, -1, -2);
  78         testIntFloorDivMod(0, -3, 0, 0);
  79         testIntFloorDivMod(-1, 3, -1, 2);
  80         testIntFloorDivMod(-2, 3, -1, 1);
  81         testIntFloorDivMod(-3, 3, -1, 0);
  82         testIntFloorDivMod(-4, 3, -2, 2);
  83         testIntFloorDivMod(-1, -3, 0, -1);
  84         testIntFloorDivMod(-2, -3, 0, -2);
  85         testIntFloorDivMod(-3, -3, 1, 0);
  86         testIntFloorDivMod(-4, -3, 1, -1);
  87         testIntFloorDivMod(Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
  88         testIntFloorDivMod(Integer.MAX_VALUE, -1, -Integer.MAX_VALUE, 0);
  89         testIntFloorDivMod(Integer.MAX_VALUE, 3, 715827882, 1);
  90         testIntFloorDivMod(Integer.MAX_VALUE - 1, 3, 715827882, 0);
  91         testIntFloorDivMod(Integer.MIN_VALUE, 3, -715827883, 1);
  92         testIntFloorDivMod(Integer.MIN_VALUE + 1, 3, -715827883, 2);
  93         testIntFloorDivMod(Integer.MIN_VALUE + 1, -1, Integer.MAX_VALUE, 0);
  94         // Special case of integer overflow
  95         testIntFloorDivMod(Integer.MIN_VALUE, -1, Integer.MIN_VALUE, 0);
  96     }
  97 
  98     /**
  99      * Test FloorDiv and then FloorMod with int data.
 100      */
 101     static void testIntFloorDivMod(int x, int y, Object divExpected, Object modExpected) {
 102         testIntFloorDiv(x, y, divExpected);
 103         testIntFloorMod(x, y, modExpected);
 104     }
 105 
 106     /**
 107      * Test FloorDiv with int data.
 108      */
 109     static void testIntFloorDiv(int x, int y, Object expected) {
 110         Object result = doFloorDiv(x, y);
 111         if (!resultEquals(result, expected)) {
 112             fail("FAIL: Math.floorDiv(%d, %d) = %s; expected %s%n", x, y, result, expected);
 113         }
 114 
 115         Object strict_result = doStrictFloorDiv(x, y);
 116         if (!resultEquals(strict_result, expected)) {
 117             fail("FAIL: StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
 118         }
 119     }
 120 
 121     /**
 122      * Test FloorMod with int data.
 123      */
 124     static void testIntFloorMod(int x, int y, Object expected) {
 125         Object result = doFloorMod(x, y);
 126         if (!resultEquals(result, expected)) {
 127             fail("FAIL: Math.floorMod(%d, %d) = %s; expected %s%n", x, y, result, expected);
 128         }
 129 
 130         Object strict_result = doStrictFloorMod(x, y);
 131         if (!resultEquals(strict_result, expected)) {
 132             fail("FAIL: StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
 133         }
 134 
 135         try {
 136             // Verify result against double precision floor function
 137             int tmp = x / y;     // Force ArithmeticException for divide by zero
 138             double ff = x - Math.floor((double)x / (double)y) * y;
 139             int fr = (int)ff;
 140             boolean t = (fr == ((Integer)result));
 141             if (!result.equals(fr)) {
 142                 fail("FAIL: Math.floorMod(%d, %d) = %s differs from Math.floor(x, y): %d%n", x, y, result, fr);
 143             }
 144         } catch (ArithmeticException ae) {
 145             if (y != 0) {
 146                 fail("FAIL: Math.floorMod(%d, %d); unexpected %s%n", x, y, ae);
 147             }
 148         }
 149     }
 150 
 151     /**
 152      * Test the floorDiv and floorMod methods for primitive long.
 153      */
 154     static void testLongFloorDivMod() {
 155         testLongFloorDivMod(4L, 0L, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException
 156         testLongFloorDivMod(4L, 3L, 1L, 1L);
 157         testLongFloorDivMod(3L, 3L, 1L, 0L);
 158         testLongFloorDivMod(2L, 3L, 0L, 2L);
 159         testLongFloorDivMod(1L, 3L, 0L, 1L);
 160         testLongFloorDivMod(0L, 3L, 0L, 0L);
 161         testLongFloorDivMod(4L, -3L, -2L, -2L);
 162         testLongFloorDivMod(3L, -3L, -1L, 0l);
 163         testLongFloorDivMod(2L, -3L, -1L, -1L);
 164         testLongFloorDivMod(1L, -3L, -1L, -2L);
 165         testLongFloorDivMod(0L, -3L, 0L, 0L);
 166         testLongFloorDivMod(-1L, 3L, -1L, 2L);
 167         testLongFloorDivMod(-2L, 3L, -1L, 1L);
 168         testLongFloorDivMod(-3L, 3L, -1L, 0L);
 169         testLongFloorDivMod(-4L, 3L, -2L, 2L);
 170         testLongFloorDivMod(-1L, -3L, 0L, -1L);
 171         testLongFloorDivMod(-2L, -3L, 0L, -2L);
 172         testLongFloorDivMod(-3L, -3L, 1L, 0L);
 173         testLongFloorDivMod(-4L, -3L, 1L, -1L);
 174 
 175         testLongFloorDivMod(Long.MAX_VALUE, 1, Long.MAX_VALUE, 0L);
 176         testLongFloorDivMod(Long.MAX_VALUE, -1, -Long.MAX_VALUE, 0L);
 177         testLongFloorDivMod(Long.MAX_VALUE, 3L, Long.MAX_VALUE / 3L, 1L);
 178         testLongFloorDivMod(Long.MAX_VALUE - 1L, 3L, (Long.MAX_VALUE - 1L) / 3L, 0L);
 179         testLongFloorDivMod(Long.MIN_VALUE, 3L, Long.MIN_VALUE / 3L - 1L, 1L);
 180         testLongFloorDivMod(Long.MIN_VALUE + 1L, 3L, Long.MIN_VALUE / 3L - 1L, 2L);
 181         testLongFloorDivMod(Long.MIN_VALUE + 1, -1, Long.MAX_VALUE, 0L);
 182         // Special case of integer overflow
 183         testLongFloorDivMod(Long.MIN_VALUE, -1, Long.MIN_VALUE, 0L);
 184     }
 185 
 186     /**
 187      * Test the long floorDiv and floorMod methods.
 188      * Math and StrictMath are tested and the same results are expected for both.
 189      */
 190     static void testLongFloorDivMod(long x, long y, Object divExpected, Object modExpected) {
 191         testLongFloorDiv(x, y, divExpected);
 192         testLongFloorMod(x, y, modExpected);
 193     }
 194 
 195     /**
 196      * Test FloorDiv with long arguments against expected value.
 197      * The expected value is usually a Long but in some cases  is
 198      * an ArithmeticException.
 199      *
 200      * @param x dividend
 201      * @param y modulus
 202      * @param expected expected value,
 203      */
 204     static void testLongFloorDiv(long x, long y, Object expected) {
 205         Object result = doFloorDiv(x, y);
 206         if (!resultEquals(result, expected)) {
 207             fail("FAIL: long Math.floorDiv(%d, %d) = %s; expected %s%n", x, y, result, expected);
 208         }
 209 
 210         Object strict_result = doStrictFloorDiv(x, y);
 211         if (!resultEquals(strict_result, expected)) {
 212             fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
 213         }
 214     }
 215 
 216     /**
 217      * Test FloorMod of long arguments against expected value.
 218      * The expected value is usually a Long but in some cases  is
 219      * an ArithmeticException.
 220      *
 221      * @param x dividend
 222      * @param y modulus
 223      * @param expected expected value
 224      */
 225     static void testLongFloorMod(long x, long y, Object expected) {
 226         Object result = doFloorMod(x, y);
 227         if (!resultEquals(result, expected)) {
 228             fail("FAIL: long Math.floorMod(%d, %d) = %s; expected %s%n", x, y, result, expected);
 229         }
 230 
 231         Object strict_result = doStrictFloorMod(x, y);
 232         if (!resultEquals(strict_result, expected)) {
 233             fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
 234         }
 235 
 236         try {
 237             // Verify the result against BigDecimal rounding mode.
 238             BigDecimal xD = new BigDecimal(x);
 239             BigDecimal yD = new BigDecimal(y);
 240             BigDecimal resultD = xD.divide(yD, RoundingMode.FLOOR);
 241             resultD = resultD.multiply(yD);
 242             resultD = xD.subtract(resultD);
 243             long fr = resultD.longValue();
 244             if (!result.equals(fr)) {
 245                 fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n", x, y, result, fr);
 246 
 247             }
 248         } catch (ArithmeticException ae) {
 249             if (y != 0) {
 250                 fail("FAIL: long Math.floorMod(%d, %d); unexpected ArithmeticException from bigdecimal");
 251             }
 252         }
 253     }
 254 
 255     /**
 256      * Test the floorDiv and floorMod methods for mixed long and int.
 257      */
 258     static void testLongIntFloorDivMod() {
 259         testLongIntFloorDivMod(4L, 0, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException
 260         testLongIntFloorDivMod(4L, 3, 1L, 1);
 261         testLongIntFloorDivMod(3L, 3, 1L, 0);
 262         testLongIntFloorDivMod(2L, 3, 0L, 2);
 263         testLongIntFloorDivMod(1L, 3, 0L, 1);
 264         testLongIntFloorDivMod(0L, 3, 0L, 0);
 265         testLongIntFloorDivMod(4L, -3, -2L, -2);
 266         testLongIntFloorDivMod(3L, -3, -1L, 0);
 267         testLongIntFloorDivMod(2L, -3, -1L, -1);
 268         testLongIntFloorDivMod(1L, -3, -1L, -2);
 269         testLongIntFloorDivMod(0L, -3, 0L, 0);
 270         testLongIntFloorDivMod(-1L, 3, -1L, 2);
 271         testLongIntFloorDivMod(-2L, 3, -1L, 1);
 272         testLongIntFloorDivMod(-3L, 3, -1L, 0);
 273         testLongIntFloorDivMod(-4L, 3, -2L, 2);
 274         testLongIntFloorDivMod(-1L, -3, 0L, -1);
 275         testLongIntFloorDivMod(-2L, -3, 0L, -2);
 276         testLongIntFloorDivMod(-3L, -3, 1L, 0);
 277         testLongIntFloorDivMod(-4L, -3, 1L, -1);
 278 
 279         testLongIntFloorDivMod(Long.MAX_VALUE, 1, Long.MAX_VALUE, 0L);
 280         testLongIntFloorDivMod(Long.MAX_VALUE, -1, -Long.MAX_VALUE, 0L);
 281         testLongIntFloorDivMod(Long.MAX_VALUE, 3, Long.MAX_VALUE / 3L, 1L);
 282         testLongIntFloorDivMod(Long.MAX_VALUE - 1L, 3, (Long.MAX_VALUE - 1L) / 3L, 0L);
 283         testLongIntFloorDivMod(Long.MIN_VALUE, 3, Long.MIN_VALUE / 3L - 1L, 1L);
 284         testLongIntFloorDivMod(Long.MIN_VALUE + 1L, 3, Long.MIN_VALUE / 3L - 1L, 2L);
 285         testLongIntFloorDivMod(Long.MIN_VALUE + 1, -1, Long.MAX_VALUE, 0L);
 286         // Special case of integer overflow
 287         testLongIntFloorDivMod(Long.MIN_VALUE, -1, Long.MIN_VALUE, 0L);
 288     }
 289 
 290     /**
 291      * Test the integer floorDiv and floorMod methods.
 292      * Math and StrictMath are tested and the same results are expected for both.
 293      */
 294     static void testLongIntFloorDivMod(long x, int y, Object divExpected, Object modExpected) {
 295         testLongIntFloorDiv(x, y, divExpected);
 296         testLongIntFloorMod(x, y, modExpected);
 297     }
 298 
 299     /**
 300      * Test FloorDiv with long arguments against expected value.
 301      * The expected value is usually a Long but in some cases  is
 302      * an ArithmeticException.
 303      *
 304      * @param x dividend
 305      * @param y modulus
 306      * @param expected expected value,
 307      */
 308     static void testLongIntFloorDiv(long x, int y, Object expected) {
 309         Object result = doFloorDiv(x, y);
 310         if (!resultEquals(result, expected)) {
 311             fail("FAIL: long Math.floorDiv(%d, %d) = %s; expected %s%n", x, y, result, expected);
 312         }
 313 
 314         Object strict_result = doStrictFloorDiv(x, y);
 315         if (!resultEquals(strict_result, expected)) {
 316             fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
 317         }
 318     }
 319 
 320     /**
 321      * Test FloorMod of long arguments against expected value.
 322      * The expected value is usually a Long but in some cases  is
 323      * an ArithmeticException.
 324      *
 325      * @param x dividend
 326      * @param y modulus
 327      * @param expected expected value
 328      */
 329     static void testLongIntFloorMod(long x, int y, Object expected) {
 330         Object result = doFloorMod(x, y);
 331         if (!resultEquals(result, expected)) {
 332             fail("FAIL: long Math.floorMod(%d, %d) = %s; expected %s%n", x, y, result, expected);
 333         }
 334 
 335         Object strict_result = doStrictFloorMod(x, y);
 336         if (!resultEquals(strict_result, expected)) {
 337             fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
 338         }
 339 
 340         try {
 341             // Verify the result against BigDecimal rounding mode.
 342             BigDecimal xD = new BigDecimal(x);
 343             BigDecimal yD = new BigDecimal(y);
 344             BigDecimal resultD = xD.divide(yD, RoundingMode.FLOOR);
 345             resultD = resultD.multiply(yD);
 346             resultD = xD.subtract(resultD);
 347             long fr = resultD.longValue();
 348             if (!result.equals(fr)) {
 349                 fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n", x, y, result, fr);
 350 
 351             }
 352         } catch (ArithmeticException ae) {
 353             if (y != 0) {
 354                 fail("FAIL: long Math.floorMod(%d, %d); unexpected ArithmeticException from bigdecimal");
 355             }
 356         }
 357     }
 358 
 359     /**
 360      * Invoke floorDiv and return the result or any exception.
 361      * @param x the x value
 362      * @param y the y value
 363      * @return the result Integer or an exception.
 364      */
 365     static Object doFloorDiv(int x, int y) {
 366         try {
 367             return Math.floorDiv(x, y);
 368         } catch (ArithmeticException ae) {
 369             return ae;
 370         }
 371     }
 372 
 373     /**
 374      * Invoke floorDiv and return the result or any exception.
 375      * @param x the x value
 376      * @param y the y value
 377      * @return the result Integer or an exception.
 378      */
 379     static Object doFloorDiv(long x, int y) {
 380         try {
 381             return Math.floorDiv(x, y);
 382         } catch (ArithmeticException ae) {
 383             return ae;
 384         }
 385     }
 386 
 387     /**
 388      * Invoke floorDiv and return the result or any exception.
 389      * @param x the x value
 390      * @param y the y value
 391      * @return the result Integer or an exception.
 392      */
 393     static Object doFloorDiv(long x, long y) {
 394         try {
 395             return Math.floorDiv(x, y);
 396         } catch (ArithmeticException ae) {
 397             return ae;
 398         }
 399     }
 400 
 401     /**
 402      * Invoke floorDiv and return the result or any exception.
 403      * @param x the x value
 404      * @param y the y value
 405      * @return the result Integer or an exception.
 406      */
 407     static Object doFloorMod(int x, int y) {
 408         try {
 409             return Math.floorMod(x, y);
 410         } catch (ArithmeticException ae) {
 411             return ae;
 412         }
 413     }
 414 
 415     /**
 416      * Invoke floorDiv and return the result or any exception.
 417      * @param x the x value
 418      * @param y the y value
 419      * @return the result Integer or an exception.
 420      */
 421     static Object doFloorMod(long x, int y) {
 422         try {
 423             return Math.floorMod(x, y);
 424         } catch (ArithmeticException ae) {
 425             return ae;
 426         }
 427     }
 428 
 429     /**
 430      * Invoke floorDiv and return the result or any exception.
 431      * @param x the x value
 432      * @param y the y value
 433      * @return the result Integer or an exception.
 434      */
 435     static Object doFloorMod(long x, long y) {
 436         try {
 437             return Math.floorMod(x, y);
 438         } catch (ArithmeticException ae) {
 439             return ae;
 440         }
 441     }
 442 
 443     /**
 444      * Invoke floorDiv and return the result or any exception.
 445      * @param x the x value
 446      * @param y the y value
 447      * @return the result Integer or an exception.
 448      */
 449     static Object doStrictFloorDiv(int x, int y) {
 450         try {
 451             return StrictMath.floorDiv(x, y);
 452         } catch (ArithmeticException ae) {
 453             return ae;
 454         }
 455     }
 456 
 457     /**
 458      * Invoke floorDiv and return the result or any exception.
 459      * @param x the x value
 460      * @param y the y value
 461      * @return the result Integer or an exception.
 462      */
 463     static Object doStrictFloorDiv(long x, int y) {
 464         try {
 465             return StrictMath.floorDiv(x, y);
 466         } catch (ArithmeticException ae) {
 467             return ae;
 468         }
 469     }
 470 
 471     /**
 472      * Invoke floorDiv and return the result or any exception.
 473      * @param x the x value
 474      * @param y the y value
 475      * @return the result Integer or an exception.
 476      */
 477     static Object doStrictFloorDiv(long x, long y) {
 478         try {
 479             return StrictMath.floorDiv(x, y);
 480         } catch (ArithmeticException ae) {
 481             return ae;
 482         }
 483     }
 484 
 485     /**
 486      * Invoke floorDiv and return the result or any exception.
 487      * @param x the x value
 488      * @param y the y value
 489      * @return the result Integer or an exception.
 490      */
 491     static Object doStrictFloorMod(int x, int y) {
 492         try {
 493             return StrictMath.floorMod(x, y);
 494         } catch (ArithmeticException ae) {
 495             return ae;
 496         }
 497     }
 498 
 499     /**
 500      * Invoke floorDiv and return the result or any exception.
 501      * @param x the x value
 502      * @param y the y value
 503      * @return the result Integer or an exception.
 504      */
 505     static Object doStrictFloorMod(long x, int y) {
 506         try {
 507             return StrictMath.floorMod(x, y);
 508         } catch (ArithmeticException ae) {
 509             return ae;
 510         }
 511     }
 512 
 513     /**
 514      * Invoke floorDiv and return the result or any exception.
 515      * @param x the x value
 516      * @param y the y value
 517      * @return the result Integer or an exception.
 518      */
 519     static Object doStrictFloorMod(long x, long y) {
 520         try {
 521             return StrictMath.floorMod(x, y);
 522         } catch (ArithmeticException ae) {
 523             return ae;
 524         }
 525     }
 526 
 527     /**
 528      * Returns a boolean by comparing the result and the expected value.
 529      * The equals method is not defined for ArithmeticException but it is
 530      * desirable to have equals return true if the expected and the result
 531      * both threw the same exception (class and message.)
 532      *
 533      * @param result the result from testing the method
 534      * @param expected the expected value
 535      * @return true if the result is equal to the expected values; false otherwise.
 536      */
 537     static boolean resultEquals(Object result, Object expected) {
 538         if (result.getClass() != expected.getClass()) {
 539             fail("FAIL: Result type mismatch, %s; expected: %s%n",
 540                     result.getClass().getName(), expected.getClass().getName());
 541             return false;
 542         }
 543 
 544         if (result.equals(expected)) {
 545             return true;
 546         }
 547         // Handle special case to compare ArithmeticExceptions
 548         if (result instanceof ArithmeticException && expected instanceof ArithmeticException) {
 549             return true;
 550         }
 551         return false;
 552     }
 553 
 554 }