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