xref: /aosp_15_r20/bionic/tests/math_data_test.h (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <math.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <fenv.h>
21*8d67ca89SAndroid Build Coastguard Worker 
22*8d67ca89SAndroid Build Coastguard Worker template <typename RT, typename T1>
23*8d67ca89SAndroid Build Coastguard Worker struct data_1_1_t {
24*8d67ca89SAndroid Build Coastguard Worker   RT expected;
25*8d67ca89SAndroid Build Coastguard Worker   T1 input;
26*8d67ca89SAndroid Build Coastguard Worker };
27*8d67ca89SAndroid Build Coastguard Worker 
28*8d67ca89SAndroid Build Coastguard Worker template <typename T1>
29*8d67ca89SAndroid Build Coastguard Worker struct data_int_1_t {
30*8d67ca89SAndroid Build Coastguard Worker   int expected;
31*8d67ca89SAndroid Build Coastguard Worker   T1 input;
32*8d67ca89SAndroid Build Coastguard Worker };
33*8d67ca89SAndroid Build Coastguard Worker 
34*8d67ca89SAndroid Build Coastguard Worker template <typename T1>
35*8d67ca89SAndroid Build Coastguard Worker struct data_long_1_t {
36*8d67ca89SAndroid Build Coastguard Worker   long expected;
37*8d67ca89SAndroid Build Coastguard Worker   T1 input;
38*8d67ca89SAndroid Build Coastguard Worker };
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker template <typename T1>
41*8d67ca89SAndroid Build Coastguard Worker struct data_llong_1_t {
42*8d67ca89SAndroid Build Coastguard Worker   long long expected;
43*8d67ca89SAndroid Build Coastguard Worker   T1 input;
44*8d67ca89SAndroid Build Coastguard Worker };
45*8d67ca89SAndroid Build Coastguard Worker 
46*8d67ca89SAndroid Build Coastguard Worker template <typename RT, typename T1, typename T2>
47*8d67ca89SAndroid Build Coastguard Worker struct data_1_2_t {
48*8d67ca89SAndroid Build Coastguard Worker   RT expected;
49*8d67ca89SAndroid Build Coastguard Worker   T1 input1;
50*8d67ca89SAndroid Build Coastguard Worker   T2 input2;
51*8d67ca89SAndroid Build Coastguard Worker };
52*8d67ca89SAndroid Build Coastguard Worker 
53*8d67ca89SAndroid Build Coastguard Worker template <typename RT1, typename RT2, typename T>
54*8d67ca89SAndroid Build Coastguard Worker struct data_2_1_t {
55*8d67ca89SAndroid Build Coastguard Worker   RT1 expected1;
56*8d67ca89SAndroid Build Coastguard Worker   RT2 expected2;
57*8d67ca89SAndroid Build Coastguard Worker   T input;
58*8d67ca89SAndroid Build Coastguard Worker };
59*8d67ca89SAndroid Build Coastguard Worker 
60*8d67ca89SAndroid Build Coastguard Worker template <typename RT1, typename T>
61*8d67ca89SAndroid Build Coastguard Worker struct data_1_int_1_t {
62*8d67ca89SAndroid Build Coastguard Worker   RT1 expected1;
63*8d67ca89SAndroid Build Coastguard Worker   int expected2;
64*8d67ca89SAndroid Build Coastguard Worker   T input;
65*8d67ca89SAndroid Build Coastguard Worker };
66*8d67ca89SAndroid Build Coastguard Worker 
67*8d67ca89SAndroid Build Coastguard Worker template <typename RT1, typename T1, typename T2>
68*8d67ca89SAndroid Build Coastguard Worker struct data_1_int_2_t {
69*8d67ca89SAndroid Build Coastguard Worker   RT1 expected1;
70*8d67ca89SAndroid Build Coastguard Worker   int expected2;
71*8d67ca89SAndroid Build Coastguard Worker   T1 input1;
72*8d67ca89SAndroid Build Coastguard Worker   T2 input2;
73*8d67ca89SAndroid Build Coastguard Worker };
74*8d67ca89SAndroid Build Coastguard Worker 
75*8d67ca89SAndroid Build Coastguard Worker template <typename RT, typename T1, typename T2, typename T3>
76*8d67ca89SAndroid Build Coastguard Worker struct data_1_3_t {
77*8d67ca89SAndroid Build Coastguard Worker   RT expected;
78*8d67ca89SAndroid Build Coastguard Worker   T1 input1;
79*8d67ca89SAndroid Build Coastguard Worker   T2 input2;
80*8d67ca89SAndroid Build Coastguard Worker   T3 input3;
81*8d67ca89SAndroid Build Coastguard Worker };
82*8d67ca89SAndroid Build Coastguard Worker 
83*8d67ca89SAndroid Build Coastguard Worker template <typename T> union fp_u;
84*8d67ca89SAndroid Build Coastguard Worker 
85*8d67ca89SAndroid Build Coastguard Worker template <> union fp_u<float> {
86*8d67ca89SAndroid Build Coastguard Worker   float value;
87*8d67ca89SAndroid Build Coastguard Worker   struct {
88*8d67ca89SAndroid Build Coastguard Worker     unsigned frac:23;
89*8d67ca89SAndroid Build Coastguard Worker     unsigned exp:8;
90*8d67ca89SAndroid Build Coastguard Worker     unsigned sign:1;
91*8d67ca89SAndroid Build Coastguard Worker   } bits;
92*8d67ca89SAndroid Build Coastguard Worker   uint32_t sign_magnitude;
93*8d67ca89SAndroid Build Coastguard Worker };
94*8d67ca89SAndroid Build Coastguard Worker 
95*8d67ca89SAndroid Build Coastguard Worker template <> union fp_u<double> {
96*8d67ca89SAndroid Build Coastguard Worker   double value;
97*8d67ca89SAndroid Build Coastguard Worker   struct {
98*8d67ca89SAndroid Build Coastguard Worker     unsigned fracl;
99*8d67ca89SAndroid Build Coastguard Worker     unsigned frach:20;
100*8d67ca89SAndroid Build Coastguard Worker     unsigned exp:11;
101*8d67ca89SAndroid Build Coastguard Worker     unsigned sign:1;
102*8d67ca89SAndroid Build Coastguard Worker   } bits;
103*8d67ca89SAndroid Build Coastguard Worker   uint64_t sign_magnitude;
104*8d67ca89SAndroid Build Coastguard Worker };
105*8d67ca89SAndroid Build Coastguard Worker 
106*8d67ca89SAndroid Build Coastguard Worker template <> union fp_u<long double> {
107*8d67ca89SAndroid Build Coastguard Worker   long double value;
108*8d67ca89SAndroid Build Coastguard Worker #if defined(__LP64__)
109*8d67ca89SAndroid Build Coastguard Worker   struct {
110*8d67ca89SAndroid Build Coastguard Worker     unsigned fracl;
111*8d67ca89SAndroid Build Coastguard Worker     unsigned fraclm;
112*8d67ca89SAndroid Build Coastguard Worker     unsigned frachm;
113*8d67ca89SAndroid Build Coastguard Worker     unsigned frach:16;
114*8d67ca89SAndroid Build Coastguard Worker     unsigned exp:15;
115*8d67ca89SAndroid Build Coastguard Worker     unsigned sign:1;
116*8d67ca89SAndroid Build Coastguard Worker   } bits;
117*8d67ca89SAndroid Build Coastguard Worker   __int128_t sign_magnitude;
118*8d67ca89SAndroid Build Coastguard Worker #else
119*8d67ca89SAndroid Build Coastguard Worker   struct {
120*8d67ca89SAndroid Build Coastguard Worker       unsigned fracl;
121*8d67ca89SAndroid Build Coastguard Worker       unsigned frach:20;
122*8d67ca89SAndroid Build Coastguard Worker       unsigned exp:11;
123*8d67ca89SAndroid Build Coastguard Worker       unsigned sign:1;
124*8d67ca89SAndroid Build Coastguard Worker   } bits;
125*8d67ca89SAndroid Build Coastguard Worker   uint64_t sign_magnitude;
126*8d67ca89SAndroid Build Coastguard Worker #endif
127*8d67ca89SAndroid Build Coastguard Worker };
128*8d67ca89SAndroid Build Coastguard Worker 
129*8d67ca89SAndroid Build Coastguard Worker template <typename T>
130*8d67ca89SAndroid Build Coastguard Worker static inline auto SignAndMagnitudeToBiased(const T& value) -> decltype(fp_u<T>::sign_magnitude) {
131*8d67ca89SAndroid Build Coastguard Worker   fp_u<T> u;
132*8d67ca89SAndroid Build Coastguard Worker   u.value = value;
133*8d67ca89SAndroid Build Coastguard Worker   if (u.bits.sign) {
134*8d67ca89SAndroid Build Coastguard Worker     return ~u.sign_magnitude + 1;
135*8d67ca89SAndroid Build Coastguard Worker   } else {
136*8d67ca89SAndroid Build Coastguard Worker     u.bits.sign = 1;
137*8d67ca89SAndroid Build Coastguard Worker     return u.sign_magnitude;
138*8d67ca89SAndroid Build Coastguard Worker   }
139*8d67ca89SAndroid Build Coastguard Worker }
140*8d67ca89SAndroid Build Coastguard Worker 
141*8d67ca89SAndroid Build Coastguard Worker // Based on the existing googletest implementation, which uses a fixed 4 ulp bound.
142*8d67ca89SAndroid Build Coastguard Worker template <typename T>
143*8d67ca89SAndroid Build Coastguard Worker size_t UlpDistance(T lhs, T rhs) {
144*8d67ca89SAndroid Build Coastguard Worker   const auto biased1 = SignAndMagnitudeToBiased(lhs);
145*8d67ca89SAndroid Build Coastguard Worker   const auto biased2 = SignAndMagnitudeToBiased(rhs);
146*8d67ca89SAndroid Build Coastguard Worker   return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
147*8d67ca89SAndroid Build Coastguard Worker }
148*8d67ca89SAndroid Build Coastguard Worker 
149*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename T>
150*8d67ca89SAndroid Build Coastguard Worker struct FpUlpEq {
151*8d67ca89SAndroid Build Coastguard Worker   ::testing::AssertionResult operator()(const char* /* expected_expression */,
152*8d67ca89SAndroid Build Coastguard Worker                                         const char* /* actual_expression */,
153*8d67ca89SAndroid Build Coastguard Worker                                         T expected,
154*8d67ca89SAndroid Build Coastguard Worker                                         T actual) {
155*8d67ca89SAndroid Build Coastguard Worker     if (!isnan(expected) && !isnan(actual) && UlpDistance(expected, actual) <= ULP) {
156*8d67ca89SAndroid Build Coastguard Worker       return ::testing::AssertionSuccess();
157*8d67ca89SAndroid Build Coastguard Worker     }
158*8d67ca89SAndroid Build Coastguard Worker 
159*8d67ca89SAndroid Build Coastguard Worker     return ::testing::AssertionFailure()
160*8d67ca89SAndroid Build Coastguard Worker         << "expected (" << std::hexfloat << expected << ") != actual (" << actual << ")";
161*8d67ca89SAndroid Build Coastguard Worker   }
162*8d67ca89SAndroid Build Coastguard Worker };
163*8d67ca89SAndroid Build Coastguard Worker 
164*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
165*8d67ca89SAndroid Build Coastguard Worker // and asserting that the result is within ULP ulps of the expected value.
166*8d67ca89SAndroid Build Coastguard Worker // For testing a (double) -> double function like sin(3).
167*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename RT, typename T, size_t N>
168*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_1_1_t<RT, T> (&data)[N], RT f(T)) {
169*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
170*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT> predicate;
171*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
172*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate,
173*8d67ca89SAndroid Build Coastguard Worker                         data[i].expected, f(data[i].input)) << "Failed on element " << i;
174*8d67ca89SAndroid Build Coastguard Worker   }
175*8d67ca89SAndroid Build Coastguard Worker }
176*8d67ca89SAndroid Build Coastguard Worker 
177*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
178*8d67ca89SAndroid Build Coastguard Worker // and asserting that the result is within ULP ulps of the expected value.
179*8d67ca89SAndroid Build Coastguard Worker // For testing a (double) -> int function like ilogb(3).
180*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename T, size_t N>
181*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_int_1_t<T> (&data)[N], int f(T)) {
182*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
183*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
184*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(data[i].expected, f(data[i].input)) << "Failed on element " << i;
185*8d67ca89SAndroid Build Coastguard Worker   }
186*8d67ca89SAndroid Build Coastguard Worker }
187*8d67ca89SAndroid Build Coastguard Worker 
188*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
189*8d67ca89SAndroid Build Coastguard Worker // and asserting that the result is within ULP ulps of the expected value.
190*8d67ca89SAndroid Build Coastguard Worker // For testing a (double) -> long int function like lrint(3).
191*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename T, size_t N>
192*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_long_1_t<T> (&data)[N], long f(T)) {
193*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
194*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
195*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(data[i].expected, f(data[i].input)) << "Failed on element " << i;
196*8d67ca89SAndroid Build Coastguard Worker   }
197*8d67ca89SAndroid Build Coastguard Worker }
198*8d67ca89SAndroid Build Coastguard Worker 
199*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
200*8d67ca89SAndroid Build Coastguard Worker // and asserting that the result is within ULP ulps of the expected value.
201*8d67ca89SAndroid Build Coastguard Worker // For testing a (double) -> long long int function like llrint(3).
202*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename T, size_t N>
203*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_llong_1_t<T> (&data)[N], long long f(T)) {
204*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
205*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
206*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(data[i].expected, f(data[i].input)) << "Failed on element " << i;
207*8d67ca89SAndroid Build Coastguard Worker   }
208*8d67ca89SAndroid Build Coastguard Worker }
209*8d67ca89SAndroid Build Coastguard Worker 
210*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the pairs of input values
211*8d67ca89SAndroid Build Coastguard Worker // and asserting that the result is within ULP ulps of the expected value.
212*8d67ca89SAndroid Build Coastguard Worker // For testing a (double, double) -> double function like pow(3).
213*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename RT, typename T1, typename T2, size_t N>
214*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_1_2_t<RT, T1, T2> (&data)[N], RT f(T1, T2)) {
215*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
216*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT> predicate;
217*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
218*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate,
219*8d67ca89SAndroid Build Coastguard Worker                         data[i].expected, f(data[i].input1, data[i].input2)) << "Failed on element " << i;
220*8d67ca89SAndroid Build Coastguard Worker   }
221*8d67ca89SAndroid Build Coastguard Worker }
222*8d67ca89SAndroid Build Coastguard Worker 
223*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
224*8d67ca89SAndroid Build Coastguard Worker // and asserting that the results are within ULP ulps of the expected values.
225*8d67ca89SAndroid Build Coastguard Worker // For testing a (double, double*, double*) -> void function like sincos(3).
226*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename RT1, typename RT2, typename T1, size_t N>
227*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_2_1_t<RT1, RT2, T1> (&data)[N], void f(T1, RT1*, RT2*)) {
228*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
229*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT1> predicate1;
230*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT2> predicate2;
231*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
232*8d67ca89SAndroid Build Coastguard Worker     RT1 out1;
233*8d67ca89SAndroid Build Coastguard Worker     RT2 out2;
234*8d67ca89SAndroid Build Coastguard Worker     f(data[i].input, &out1, &out2);
235*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i;
236*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate2, data[i].expected2, out2) << "Failed on element " << i;
237*8d67ca89SAndroid Build Coastguard Worker   }
238*8d67ca89SAndroid Build Coastguard Worker }
239*8d67ca89SAndroid Build Coastguard Worker 
240*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
241*8d67ca89SAndroid Build Coastguard Worker // and asserting that the results are within ULP ulps of the expected values.
242*8d67ca89SAndroid Build Coastguard Worker // For testing a (double, double*) -> double function like modf(3).
243*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename RT1, typename RT2, typename T1, size_t N>
244*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_2_1_t<RT1, RT2, T1> (&data)[N], RT1 f(T1, RT2*)) {
245*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
246*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT1> predicate1;
247*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT2> predicate2;
248*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
249*8d67ca89SAndroid Build Coastguard Worker     RT1 out1;
250*8d67ca89SAndroid Build Coastguard Worker     RT2 out2;
251*8d67ca89SAndroid Build Coastguard Worker     out1 = f(data[i].input, &out2);
252*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i;
253*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate2, data[i].expected2, out2) << "Failed on element " << i;
254*8d67ca89SAndroid Build Coastguard Worker   }
255*8d67ca89SAndroid Build Coastguard Worker }
256*8d67ca89SAndroid Build Coastguard Worker 
257*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
258*8d67ca89SAndroid Build Coastguard Worker // and asserting that the results are within ULP ulps of the expected values.
259*8d67ca89SAndroid Build Coastguard Worker // For testing a (double, int*) -> double function like frexp(3).
260*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename RT1, typename T1, size_t N>
261*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_1_int_1_t<RT1, T1> (&data)[N], RT1 f(T1, int*)) {
262*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
263*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT1> predicate1;
264*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
265*8d67ca89SAndroid Build Coastguard Worker     RT1 out1;
266*8d67ca89SAndroid Build Coastguard Worker     int out2;
267*8d67ca89SAndroid Build Coastguard Worker     out1 = f(data[i].input, &out2);
268*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i;
269*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(data[i].expected2, out2) << "Failed on element " << i;
270*8d67ca89SAndroid Build Coastguard Worker   }
271*8d67ca89SAndroid Build Coastguard Worker }
272*8d67ca89SAndroid Build Coastguard Worker 
273*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the input values
274*8d67ca89SAndroid Build Coastguard Worker // and asserting that the results are within ULP ulps of the expected values.
275*8d67ca89SAndroid Build Coastguard Worker // For testing a (double, double, int*) -> double function like remquo(3).
276*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename RT1, typename T1, typename T2, size_t N>
277*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_1_int_2_t<RT1, T1, T2> (&data)[N], RT1 f(T1, T2, int*)) {
278*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
279*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT1> predicate1;
280*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
281*8d67ca89SAndroid Build Coastguard Worker     RT1 out1;
282*8d67ca89SAndroid Build Coastguard Worker     int out2;
283*8d67ca89SAndroid Build Coastguard Worker     out1 = f(data[i].input1, data[i].input2, &out2);
284*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i;
285*8d67ca89SAndroid Build Coastguard Worker     EXPECT_EQ(data[i].expected2, out2) << "Failed on element " << i;
286*8d67ca89SAndroid Build Coastguard Worker   }
287*8d67ca89SAndroid Build Coastguard Worker }
288*8d67ca89SAndroid Build Coastguard Worker 
289*8d67ca89SAndroid Build Coastguard Worker // Runs through the array 'data' applying 'f' to each of the pairs of input values
290*8d67ca89SAndroid Build Coastguard Worker // and asserting that the result is within ULP ulps of the expected value.
291*8d67ca89SAndroid Build Coastguard Worker // For testing a (double, double, double) -> double function like fma(3).
292*8d67ca89SAndroid Build Coastguard Worker template <size_t ULP, typename RT, typename T1, typename T2, typename T3, size_t N>
293*8d67ca89SAndroid Build Coastguard Worker void DoMathDataTest(data_1_3_t<RT, T1, T2, T3> (&data)[N], RT f(T1, T2, T3)) {
294*8d67ca89SAndroid Build Coastguard Worker   fesetenv(FE_DFL_ENV);
295*8d67ca89SAndroid Build Coastguard Worker   FpUlpEq<ULP, RT> predicate;
296*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < N; ++i) {
297*8d67ca89SAndroid Build Coastguard Worker     EXPECT_PRED_FORMAT2(predicate,
298*8d67ca89SAndroid Build Coastguard Worker                         data[i].expected, f(data[i].input1, data[i].input2, data[i].input3)) << "Failed on element " << i;
299*8d67ca89SAndroid Build Coastguard Worker   }
300*8d67ca89SAndroid Build Coastguard Worker }
301