Path: blob/master/test/jdk/java/lang/Math/HypotTests.java
41149 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @library /test/lib26* @build jdk.test.lib.RandomFactory27* @run main HypotTests28* @bug 4851638 4939441 8078672 824063229* @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed)30* @author Joseph D. Darcy31* @key randomness32*/3334import jdk.test.lib.RandomFactory;3536public class HypotTests {37private HypotTests(){}3839static final double infinityD = Double.POSITIVE_INFINITY;40static final double NaNd = Double.NaN;4142/**43* Given integers m and n, assuming m < n, the triple (n^2 - m^2,44* 2mn, and n^2 + m^2) is a Pythagorean triple with a^2 + b^2 =45* c^2. This methods returns a long array holding the Pythagorean46* triple corresponding to the inputs.47*/48static long [] pythagoreanTriple(int m, int n) {49long M = m;50long N = n;51long result[] = new long[3];525354result[0] = Math.abs(M*M - N*N);55result[1] = Math.abs(2*M*N);56result[2] = Math.abs(M*M + N*N);5758return result;59}6061static int testHypot() {62int failures = 0;6364double [][] testCases = {65// Special cases66{infinityD, infinityD, infinityD},67{infinityD, 0.0, infinityD},68{infinityD, 1.0, infinityD},69{infinityD, NaNd, infinityD},70{NaNd, NaNd, NaNd},71{0.0, NaNd, NaNd},72{1.0, NaNd, NaNd},73{Double.longBitsToDouble(0x7FF0000000000001L), 1.0, NaNd},74{Double.longBitsToDouble(0xFFF0000000000001L), 1.0, NaNd},75{Double.longBitsToDouble(0x7FF8555555555555L), 1.0, NaNd},76{Double.longBitsToDouble(0xFFF8555555555555L), 1.0, NaNd},77{Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), 1.0, NaNd},78{Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), 1.0, NaNd},79{Double.longBitsToDouble(0x7FFDeadBeef00000L), 1.0, NaNd},80{Double.longBitsToDouble(0xFFFDeadBeef00000L), 1.0, NaNd},81{Double.longBitsToDouble(0x7FFCafeBabe00000L), 1.0, NaNd},82{Double.longBitsToDouble(0xFFFCafeBabe00000L), 1.0, NaNd},83};8485for(int i = 0; i < testCases.length; i++) {86failures += testHypotCase(testCases[i][0], testCases[i][1],87testCases[i][2]);88}8990// Verify hypot(x, 0.0) is close to x over the entire exponent91// range.92for(int i = DoubleConsts.MIN_SUB_EXPONENT;93i <= Double.MAX_EXPONENT;94i++) {95double input = Math.scalb(2, i);96failures += testHypotCase(input, 0.0, input);97}9899100// Test Pythagorean triples101102// Small ones103for(int m = 1; m < 10; m++) {104for(int n = m+1; n < 11; n++) {105long [] result = pythagoreanTriple(m, n);106failures += testHypotCase(result[0], result[1], result[2]);107}108}109110// Big ones111for(int m = 100000; m < 100100; m++) {112for(int n = m+100000; n < 200200; n++) {113long [] result = pythagoreanTriple(m, n);114failures += testHypotCase(result[0], result[1], result[2]);115}116}117118// Approaching overflow tests119120/*121* Create a random value r with an large-ish exponent. The122* result of hypot(3*r, 4*r) should be approximately 5*r. (The123* computation of 4*r is exact since it just changes the124* exponent). While the exponent of r is less than or equal125* to (MAX_EXPONENT - 3), the computation should not overflow.126*/127java.util.Random rand = RandomFactory.getRandom();128for(int i = 0; i < 1000; i++) {129double d = rand.nextDouble();130// Scale d to have an exponent equal to MAX_EXPONENT -15131d = Math.scalb(d, Double.MAX_EXPONENT132-15 - Tests.ilogb(d));133for(int j = 0; j <= 13; j += 1) {134failures += testHypotCase(3*d, 4*d, 5*d, 2.5);135d *= 2.0; // increase exponent by 1136}137}138139// Test for monotonicity failures. Fix one argument and test140// two numbers before and two numbers after each chosen value;141// i.e.142//143// pcNeighbors[] =144// {nextDown(nextDown(pc)),145// nextDown(pc),146// pc,147// nextUp(pc),148// nextUp(nextUp(pc))}149//150// and we test that hypot(pcNeighbors[i]) <= hypot(pcNeighbors[i+1])151{152double pcNeighbors[] = new double[5];153double pcNeighborsHypot[] = new double[5];154double pcNeighborsStrictHypot[] = new double[5];155156157for(int i = -18; i <= 18; i++) {158double pc = Math.scalb(1.0, i);159160pcNeighbors[2] = pc;161pcNeighbors[1] = Math.nextDown(pc);162pcNeighbors[0] = Math.nextDown(pcNeighbors[1]);163pcNeighbors[3] = Math.nextUp(pc);164pcNeighbors[4] = Math.nextUp(pcNeighbors[3]);165166for(int j = 0; j < pcNeighbors.length; j++) {167pcNeighborsHypot[j] = Math.hypot(2.0, pcNeighbors[j]);168pcNeighborsStrictHypot[j] = StrictMath.hypot(2.0, pcNeighbors[j]);169}170171for(int j = 0; j < pcNeighborsHypot.length-1; j++) {172if(pcNeighborsHypot[j] > pcNeighborsHypot[j+1] ) {173failures++;174System.err.println("Monotonicity failure for Math.hypot on " +175pcNeighbors[j] + " and " +176pcNeighbors[j+1] + "\n\treturned " +177pcNeighborsHypot[j] + " and " +178pcNeighborsHypot[j+1] );179}180181if(pcNeighborsStrictHypot[j] > pcNeighborsStrictHypot[j+1] ) {182failures++;183System.err.println("Monotonicity failure for StrictMath.hypot on " +184pcNeighbors[j] + " and " +185pcNeighbors[j+1] + "\n\treturned " +186pcNeighborsStrictHypot[j] + " and " +187pcNeighborsStrictHypot[j+1] );188}189190191}192193}194}195196197return failures;198}199200/**201* Verify +0.0 is returned if both arguments are zero.202*/203private static int testHypotZeros() {204return testHypotCase(0.0, 0.0, +0.0, 0.0);205}206207static int testHypotCase(double input1, double input2, double expected) {208return testHypotCase(input1,input2, expected, 1);209}210211static int testHypotCase(double input1, double input2, double expected,212double ulps) {213int failures = 0;214if (expected < 0.0) {215throw new AssertionError("Result of hypot must be greater than " +216"or equal to zero");217}218219// Test Math and StrictMath methods with no inputs negated,220// each input negated singly, and both inputs negated. Also221// test inputs in reversed order.222223for(int i = -1; i <= 1; i+=2) {224for(int j = -1; j <= 1; j+=2) {225double x = i * input1;226double y = j * input2;227failures += Tests.testUlpDiff("Math.hypot", x, y,228Math.hypot(x, y), expected, ulps);229failures += Tests.testUlpDiff("Math.hypot", y, x,230Math.hypot(y, x ), expected, ulps);231232failures += Tests.testUlpDiff("StrictMath.hypot", x, y,233StrictMath.hypot(x, y), expected, ulps);234failures += Tests.testUlpDiff("StrictMath.hypot", y, x,235StrictMath.hypot(y, x), expected, ulps);236}237}238239return failures;240}241242public static void main(String argv[]) {243int failures = 0;244245failures += testHypot();246failures += testHypotZeros();247248if (failures > 0) {249System.err.println("Testing the hypot incurred "250+ failures + " failures.");251throw new RuntimeException();252}253}254255}256257258