/*
 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 6908131
 * @summary Check for correct implementation of Math.ceil and Math.floor
 */

import sun.misc.DoubleConsts;

public class CeilAndFloorTests {
    private static int testCeilCase(double input, double expected) {
        int failures = 0;
        failures += Tests.test("Math.ceil",  input, Math.ceil(input),   expected);
        failures += Tests.test("StrictMath.ceil",  input, StrictMath.ceil(input), expected);
        return failures;
    }

    private static int testFloorCase(double input, double expected) {
        int failures = 0;
        failures += Tests.test("Math.floor",  input, Math.floor(input),   expected);
        failures += Tests.test("StrictMath.floor",  input, StrictMath.floor(input), expected);
        return failures;
    }

    private static int nearIntegerTests() {
        int failures = 0;

        double [] fixedPoints = {
            -0.0,
             0.0,
            -1.0,
             1.0,
            -0x1.0p52,
             0x1.0p52,
            -Double.MAX_VALUE,
             Double.MAX_VALUE,
             Double.NEGATIVE_INFINITY,
             Double.POSITIVE_INFINITY,
             Double.NaN,
        };

        for(double fixedPoint : fixedPoints) {
            failures += testCeilCase(fixedPoint, fixedPoint);
            failures += testFloorCase(fixedPoint, fixedPoint);
        }

        for(int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
            double powerOfTwo   = Math.scalb(1.0, i);
            double neighborDown = Math.nextDown(powerOfTwo);
            double neighborUp   = Math.nextUp(powerOfTwo);

            if (i < 0) {
                failures += testCeilCase( powerOfTwo,  1.0);
                failures += testCeilCase(-powerOfTwo, -0.0);

                failures += testFloorCase( powerOfTwo,  0.0);
                failures += testFloorCase(-powerOfTwo, -1.0);

                failures += testCeilCase( neighborDown, 1.0);
                failures += testCeilCase(-neighborDown, -0.0);

                failures += testFloorCase( neighborUp,  0.0);
                failures += testFloorCase(-neighborUp, -1.0);
            } else {
                failures += testCeilCase(powerOfTwo, powerOfTwo);
                failures += testFloorCase(powerOfTwo, powerOfTwo);

                if (neighborDown==Math.rint(neighborDown)) {
                    failures += testCeilCase( neighborDown,  neighborDown);
                    failures += testCeilCase(-neighborDown, -neighborDown);

                    failures += testFloorCase( neighborDown, neighborDown);
                    failures += testFloorCase(-neighborDown,-neighborDown);
                } else {
                    failures += testCeilCase( neighborDown, powerOfTwo);
                    failures += testFloorCase(-neighborDown, -powerOfTwo);
                }

                if (neighborUp==Math.rint(neighborUp)) {
                    failures += testCeilCase(neighborUp, neighborUp);
                    failures += testCeilCase(-neighborUp, -neighborUp);

                    failures += testFloorCase(neighborUp, neighborUp);
                    failures += testFloorCase(-neighborUp, -neighborUp);
                } else {
                    failures += testFloorCase(neighborUp, powerOfTwo);
                    failures += testCeilCase(-neighborUp, -powerOfTwo);
                }
            }
        }

        for(int i = -(0x10000); i <= 0x10000; i++) {
            double d = (double) i;
            double neighborDown = Math.nextDown(d);
            double neighborUp   = Math.nextUp(d);

            failures += testCeilCase( d, d);
            failures += testCeilCase(-d, -d);

            failures += testFloorCase( d, d);
            failures += testFloorCase(-d, -d);

            if (Math.abs(d) > 1.0) {
                failures += testCeilCase( neighborDown, d);
                failures += testCeilCase(-neighborDown, -d+1);

                failures += testFloorCase( neighborUp, d);
                failures += testFloorCase(-neighborUp, -d-1);
            }
        }

        return failures;
    }

    public static int roundingTests() {
        int failures = 0;
        double [][] testCases = {
            { Double.MIN_VALUE,                           1.0},
            {-Double.MIN_VALUE,                          -0.0},
            { Math.nextDown(DoubleConsts.MIN_NORMAL),     1.0},
            {-Math.nextDown(DoubleConsts.MIN_NORMAL),    -0.0},
            { DoubleConsts.MIN_NORMAL,                    1.0},
            {-DoubleConsts.MIN_NORMAL,                   -0.0},

            { 0.1,                                        1.0},
            {-0.1,                                       -0.0},

            { 0.5,                                        1.0},
            {-0.5,                                       -0.0},

            { 1.5,                                        2.0},
            {-1.5,                                       -1.0},

            { 2.5,                                        3.0},
            {-2.5,                                       -2.0},

            { Math.nextDown(1.0),                         1.0},
            { Math.nextDown(-1.0),                       -1.0},

            { Math.nextUp(1.0),                           2.0},
            { Math.nextUp(-1.0),                         -0.0},

            { 0x1.0p51,                                 0x1.0p51},
            {-0x1.0p51,                                -0x1.0p51},

            { Math.nextDown(0x1.0p51),                  0x1.0p51},
            {-Math.nextUp(0x1.0p51),                   -0x1.0p51},

            { Math.nextUp(0x1.0p51),                    0x1.0p51+1},
            {-Math.nextDown(0x1.0p51),                 -0x1.0p51+1},

            { Math.nextDown(0x1.0p52),                  0x1.0p52},
            {-Math.nextUp(0x1.0p52),                   -0x1.0p52-1.0},

            { Math.nextUp(0x1.0p52),                    0x1.0p52+1.0},
            {-Math.nextDown(0x1.0p52),                 -0x1.0p52+1.0},
        };

        for(double[] testCase : testCases) {
            failures += testCeilCase(testCase[0], testCase[1]);
            failures += testFloorCase(-testCase[0], -testCase[1]);
        }
        return failures;
    }

    public static void main(String... args) {
        int failures = 0;

        failures += nearIntegerTests();
        failures += roundingTests();

        if (failures > 0) {
            System.err.println("Testing {Math, StrictMath}.ceil incurred "
                               + failures + " failures.");
            throw new RuntimeException();
        }
    }
}
