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