1 /* 2 * Copyright (c) 2016, 2021, 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 4851642 8253409 27 * @summary Tests for Math.fusedMac and StrictMath.fusedMac. 28 * @build Tests 29 * @build FusedMultiplyAddTests 30 * @run main FusedMultiplyAddTests 31 * @run main/othervm -XX:-UseFMA FusedMultiplyAddTests 32 */ 33 package test.java.lang.Math; 34 35 import org.testng.annotations.Test; 36 import org.testng.Assert; 37 38 /** 39 * The specifications for both Math.fusedMac and StrictMath.fusedMac are the same and both are 40 * exactly specified. Therefore, both methods are tested in this file. 41 */ 42 43 public class FusedMultiplyAddTests { 44 FusedMultiplyAddTests()45 private FusedMultiplyAddTests() { 46 } 47 48 private static final double Infinity = Double.POSITIVE_INFINITY; 49 private static final float InfinityF = Float.POSITIVE_INFINITY; 50 private static final double NaN = Double.NaN; 51 private static final float NaNf = Float.NaN; 52 53 @Test testNonFiniteD()54 public void testNonFiniteD() { 55 double[][] testCases = { 56 {Infinity, Infinity, Infinity, 57 Infinity, 58 }, 59 60 {-Infinity, Infinity, -Infinity, 61 -Infinity, 62 }, 63 64 {-Infinity, Infinity, Infinity, 65 NaN, 66 }, 67 68 {Infinity, Infinity, -Infinity, 69 NaN, 70 }, 71 72 {1.0, Infinity, 2.0, 73 Infinity, 74 }, 75 76 {1.0, 2.0, Infinity, 77 Infinity, 78 }, 79 80 {Infinity, 1.0, Infinity, 81 Infinity, 82 }, 83 84 {Double.MAX_VALUE, 2.0, -Infinity, 85 -Infinity}, 86 87 {Infinity, 1.0, -Infinity, 88 NaN, 89 }, 90 91 {-Infinity, 1.0, Infinity, 92 NaN, 93 }, 94 95 {1.0, NaN, 2.0, 96 NaN, 97 }, 98 99 {1.0, 2.0, NaN, 100 NaN, 101 }, 102 103 {Infinity, 2.0, NaN, 104 NaN, 105 }, 106 107 {NaN, 2.0, Infinity, 108 NaN, 109 }, 110 }; 111 112 for (double[] testCase : testCases) { 113 testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]); 114 } 115 } 116 117 @Test testZeroesD()118 public void testZeroesD() { 119 double[][] testCases = { 120 {+0.0, +0.0, +0.0, 121 +0.0, 122 }, 123 124 {-0.0, +0.0, +0.0, 125 +0.0, 126 }, 127 128 {+0.0, +0.0, -0.0, 129 +0.0, 130 }, 131 132 {+0.0, +0.0, -0.0, 133 +0.0, 134 }, 135 136 {-0.0, +0.0, -0.0, 137 -0.0, 138 }, 139 140 {-0.0, -0.0, -0.0, 141 +0.0, 142 }, 143 144 {-1.0, +0.0, -0.0, 145 -0.0, 146 }, 147 148 {-1.0, +0.0, +0.0, 149 +0.0, 150 }, 151 152 {-2.0, +0.0, -0.0, 153 -0.0, 154 }, 155 156 {-2.0, +0.0, +0.0, 157 +0.0, 158 }, 159 }; 160 161 for (double[] testCase : testCases) { 162 testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]); 163 } 164 } 165 166 @Test testSimpleD()167 public void testSimpleD() { 168 double[][] testCases = { 169 {1.0, 2.0, 3.0, 170 5.0,}, 171 172 {1.0, 2.0, -2.0, 173 0.0,}, 174 175 {5.0, 5.0, -25.0, 176 0.0,}, 177 178 {Double.MAX_VALUE, 2.0, -Double.MAX_VALUE, 179 Double.MAX_VALUE}, 180 181 {Double.MAX_VALUE, 2.0, 1.0, 182 Infinity}, 183 184 {Double.MIN_VALUE, -Double.MIN_VALUE, +0.0, 185 -0.0}, 186 187 {Double.MIN_VALUE, -Double.MIN_VALUE, -0.0, 188 -0.0}, 189 190 {Double.MIN_VALUE, Double.MIN_VALUE, +0.0, 191 +0.0}, 192 193 {Double.MIN_VALUE, Double.MIN_VALUE, -0.0, 194 +0.0}, 195 196 {Double.MIN_VALUE, +0.0, -0.0, 197 +0.0}, 198 199 {Double.MIN_VALUE, -0.0, -0.0, 200 -0.0}, 201 202 {Double.MIN_VALUE, +0.0, +0.0, 203 +0.0}, 204 205 {Double.MIN_VALUE, -0.0, +0.0, 206 +0.0}, 207 208 {1.0 + Math.ulp(1.0), 1.0 + Math.ulp(1.0), -1.0 - 2.0 * Math.ulp(1.0), 209 Math.ulp(1.0) * Math.ulp(1.0)}, 210 }; 211 212 for (double[] testCase : testCases) { 213 testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]); 214 } 215 } 216 217 @Test testNonFiniteF()218 public void testNonFiniteF() { 219 float[][] testCases = { 220 {1.0f, InfinityF, 2.0f, 221 InfinityF, 222 }, 223 224 {1.0f, 2.0f, InfinityF, 225 InfinityF, 226 }, 227 228 {InfinityF, 1.0f, InfinityF, 229 InfinityF, 230 }, 231 232 {Float.MAX_VALUE, 2.0f, -InfinityF, 233 -InfinityF}, 234 235 {InfinityF, 1.0f, -InfinityF, 236 NaNf, 237 }, 238 239 {-InfinityF, 1.0f, InfinityF, 240 NaNf, 241 }, 242 243 {1.0f, NaNf, 2.0f, 244 NaNf, 245 }, 246 247 {1.0f, 2.0f, NaNf, 248 NaNf, 249 }, 250 251 {InfinityF, 2.0f, NaNf, 252 NaNf, 253 }, 254 255 {NaNf, 2.0f, InfinityF, 256 NaNf, 257 }, 258 }; 259 260 for (float[] testCase : testCases) { 261 testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]); 262 } 263 } 264 265 @Test testZeroesF()266 public void testZeroesF() { 267 float[][] testCases = { 268 {+0.0f, +0.0f, +0.0f, 269 +0.0f, 270 }, 271 272 {-0.0f, +0.0f, +0.0f, 273 +0.0f, 274 }, 275 276 {+0.0f, +0.0f, -0.0f, 277 +0.0f, 278 }, 279 280 {+0.0f, +0.0f, -0.0f, 281 +0.0f, 282 }, 283 284 {-0.0f, +0.0f, -0.0f, 285 -0.0f, 286 }, 287 288 {-0.0f, -0.0f, -0.0f, 289 +0.0f, 290 }, 291 292 {-1.0f, +0.0f, -0.0f, 293 -0.0f, 294 }, 295 296 {-1.0f, +0.0f, +0.0f, 297 +0.0f, 298 }, 299 300 {-2.0f, +0.0f, -0.0f, 301 -0.0f, 302 }, 303 }; 304 305 for (float[] testCase : testCases) { 306 testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]); 307 } 308 } 309 310 @Test testSimpleF()311 public void testSimpleF() { 312 float[][] testCases = { 313 {1.0f, 2.0f, 3.0f, 314 5.0f,}, 315 316 {1.0f, 2.0f, -2.0f, 317 0.0f,}, 318 319 {5.0f, 5.0f, -25.0f, 320 0.0f,}, 321 322 {Float.MAX_VALUE, 2.0f, -Float.MAX_VALUE, 323 Float.MAX_VALUE}, 324 325 {Float.MAX_VALUE, 2.0f, 1.0f, 326 InfinityF}, 327 328 {1.0f + Math.ulp(1.0f), 1.0f + Math.ulp(1.0f), -1.0f - 2.0f * Math.ulp(1.0f), 329 Math.ulp(1.0f) * Math.ulp(1.0f)}, 330 331 // Double-rounding if done in double precision 332 {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f} 333 }; 334 335 for (float[] testCase : testCases) { 336 testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]); 337 } 338 } 339 340 testFusedMacCase(double input1, double input2, double input3, double expected)341 private static void testFusedMacCase(double input1, double input2, double input3, 342 double expected) { 343 Tests.test("Math.fma(double)", input1, input2, input3, 344 Math.fma(input1, input2, input3), expected); 345 Tests.test("StrictMath.fma(double)", input1, input2, input3, 346 StrictMath.fma(input1, input2, input3), expected); 347 348 // Permute first two inputs 349 Tests.test("Math.fma(double)", input2, input1, input3, 350 Math.fma(input2, input1, input3), expected); 351 Tests.test("StrictMath.fma(double)", input2, input1, input3, 352 StrictMath.fma(input2, input1, input3), expected); 353 } 354 testFusedMacCase(float input1, float input2, float input3, float expected)355 private static void testFusedMacCase(float input1, float input2, float input3, float expected) { 356 Tests.test("Math.fma(float)", input1, input2, input3, 357 Math.fma(input1, input2, input3), expected); 358 Tests.test("StrictMath.fma(float)", input1, input2, input3, 359 StrictMath.fma(input1, input2, input3), expected); 360 361 // Permute first two inputs 362 Tests.test("Math.fma(float)", input2, input1, input3, 363 Math.fma(input2, input1, input3), expected); 364 Tests.test("StrictMath.fma(float)", input2, input1, input3, 365 StrictMath.fma(input2, input1, input3), expected); 366 } 367 } 368