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