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