1/*
2 * Copyright (c) 2009, 2011, 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/*
25 * @test
26 * @bug 6908131
27 * @summary Check for correct implementation of Math.ceil and Math.floor
28 */
29
30public class CeilAndFloorTests {
31    private static int testCeilCase(double input, double expected) {
32        int failures = 0;
33        failures += Tests.test("Math.ceil",  input, Math.ceil(input),   expected);
34        failures += Tests.test("StrictMath.ceil",  input, StrictMath.ceil(input), expected);
35        return failures;
36    }
37
38    private static int testFloorCase(double input, double expected) {
39        int failures = 0;
40        failures += Tests.test("Math.floor",  input, Math.floor(input),   expected);
41        failures += Tests.test("StrictMath.floor",  input, StrictMath.floor(input), expected);
42        return failures;
43    }
44
45    private static int nearIntegerTests() {
46        int failures = 0;
47
48        double [] fixedPoints = {
49            -0.0,
50             0.0,
51            -1.0,
52             1.0,
53            -0x1.0p52,
54             0x1.0p52,
55            -Double.MAX_VALUE,
56             Double.MAX_VALUE,
57             Double.NEGATIVE_INFINITY,
58             Double.POSITIVE_INFINITY,
59             Double.NaN,
60        };
61
62        for(double fixedPoint : fixedPoints) {
63            failures += testCeilCase(fixedPoint, fixedPoint);
64            failures += testFloorCase(fixedPoint, fixedPoint);
65        }
66
67        for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
68            double powerOfTwo   = Math.scalb(1.0, i);
69            double neighborDown = Math.nextDown(powerOfTwo);
70            double neighborUp   = Math.nextUp(powerOfTwo);
71
72            if (i < 0) {
73                failures += testCeilCase( powerOfTwo,  1.0);
74                failures += testCeilCase(-powerOfTwo, -0.0);
75
76                failures += testFloorCase( powerOfTwo,  0.0);
77                failures += testFloorCase(-powerOfTwo, -1.0);
78
79                failures += testCeilCase( neighborDown, 1.0);
80                failures += testCeilCase(-neighborDown, -0.0);
81
82                failures += testFloorCase( neighborUp,  0.0);
83                failures += testFloorCase(-neighborUp, -1.0);
84            } else {
85                failures += testCeilCase(powerOfTwo, powerOfTwo);
86                failures += testFloorCase(powerOfTwo, powerOfTwo);
87
88                if (neighborDown==Math.rint(neighborDown)) {
89                    failures += testCeilCase( neighborDown,  neighborDown);
90                    failures += testCeilCase(-neighborDown, -neighborDown);
91
92                    failures += testFloorCase( neighborDown, neighborDown);
93                    failures += testFloorCase(-neighborDown,-neighborDown);
94                } else {
95                    failures += testCeilCase( neighborDown, powerOfTwo);
96                    failures += testFloorCase(-neighborDown, -powerOfTwo);
97                }
98
99                if (neighborUp==Math.rint(neighborUp)) {
100                    failures += testCeilCase(neighborUp, neighborUp);
101                    failures += testCeilCase(-neighborUp, -neighborUp);
102
103                    failures += testFloorCase(neighborUp, neighborUp);
104                    failures += testFloorCase(-neighborUp, -neighborUp);
105                } else {
106                    failures += testFloorCase(neighborUp, powerOfTwo);
107                    failures += testCeilCase(-neighborUp, -powerOfTwo);
108                }
109            }
110        }
111
112        for(int i = -(0x10000); i <= 0x10000; i++) {
113            double d = (double) i;
114            double neighborDown = Math.nextDown(d);
115            double neighborUp   = Math.nextUp(d);
116
117            failures += testCeilCase( d, d);
118            failures += testCeilCase(-d, -d);
119
120            failures += testFloorCase( d, d);
121            failures += testFloorCase(-d, -d);
122
123            if (Math.abs(d) > 1.0) {
124                failures += testCeilCase( neighborDown, d);
125                failures += testCeilCase(-neighborDown, -d+1);
126
127                failures += testFloorCase( neighborUp, d);
128                failures += testFloorCase(-neighborUp, -d-1);
129            }
130        }
131
132        return failures;
133    }
134
135    public static int roundingTests() {
136        int failures = 0;
137        double [][] testCases = {
138            { Double.MIN_VALUE,                           1.0},
139            {-Double.MIN_VALUE,                          -0.0},
140            { Math.nextDown(Double.MIN_NORMAL),           1.0},
141            {-Math.nextDown(Double.MIN_NORMAL),          -0.0},
142            { Double.MIN_NORMAL,                          1.0},
143            {-Double.MIN_NORMAL,                         -0.0},
144
145            { 0.1,                                        1.0},
146            {-0.1,                                       -0.0},
147
148            { 0.5,                                        1.0},
149            {-0.5,                                       -0.0},
150
151            { 1.5,                                        2.0},
152            {-1.5,                                       -1.0},
153
154            { 2.5,                                        3.0},
155            {-2.5,                                       -2.0},
156
157            { Math.nextDown(1.0),                         1.0},
158            { Math.nextDown(-1.0),                       -1.0},
159
160            { Math.nextUp(1.0),                           2.0},
161            { Math.nextUp(-1.0),                         -0.0},
162
163            { 0x1.0p51,                                 0x1.0p51},
164            {-0x1.0p51,                                -0x1.0p51},
165
166            { Math.nextDown(0x1.0p51),                  0x1.0p51},
167            {-Math.nextUp(0x1.0p51),                   -0x1.0p51},
168
169            { Math.nextUp(0x1.0p51),                    0x1.0p51+1},
170            {-Math.nextDown(0x1.0p51),                 -0x1.0p51+1},
171
172            { Math.nextDown(0x1.0p52),                  0x1.0p52},
173            {-Math.nextUp(0x1.0p52),                   -0x1.0p52-1.0},
174
175            { Math.nextUp(0x1.0p52),                    0x1.0p52+1.0},
176            {-Math.nextDown(0x1.0p52),                 -0x1.0p52+1.0},
177        };
178
179        for(double[] testCase : testCases) {
180            failures += testCeilCase(testCase[0], testCase[1]);
181            failures += testFloorCase(-testCase[0], -testCase[1]);
182        }
183        return failures;
184    }
185
186    public static void main(String... args) {
187        int failures = 0;
188
189        failures += nearIntegerTests();
190        failures += roundingTests();
191
192        if (failures > 0) {
193            System.err.println("Testing {Math, StrictMath}.ceil incurred "
194                               + failures + " failures.");
195            throw new RuntimeException();
196        }
197    }
198}
199