11b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes/* 21b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * Copyright (C) 2014 The Android Open Source Project 31b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * 41b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 51b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * you may not use this file except in compliance with the License. 61b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * You may obtain a copy of the License at 71b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * 81b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 91b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * 101b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * Unless required by applicable law or agreed to in writing, software 111b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 121b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * See the License for the specific language governing permissions and 141b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes * limitations under the License. 151b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes */ 161b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 171b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes#include <gtest/gtest.h> 181b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 191b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes#include <fenv.h> 201b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 211b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <typename RT, typename T1> 221b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesstruct data_1_1_t { 231b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes RT expected; 241b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes T1 input; 251b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes}; 261b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 2756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <typename T1> 2856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangstruct data_int_1_t { 2956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang int expected; 3056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang T1 input; 3156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang}; 3256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 33fe88d4270b6ab5358b8e28decc848c496f67988cjzhatemplate <typename T1> 34fe88d4270b6ab5358b8e28decc848c496f67988cjzhastruct data_long_1_t { 35fe88d4270b6ab5358b8e28decc848c496f67988cjzha long expected; 36fe88d4270b6ab5358b8e28decc848c496f67988cjzha T1 input; 37fe88d4270b6ab5358b8e28decc848c496f67988cjzha}; 38fe88d4270b6ab5358b8e28decc848c496f67988cjzha 39fe88d4270b6ab5358b8e28decc848c496f67988cjzhatemplate <typename T1> 40fe88d4270b6ab5358b8e28decc848c496f67988cjzhastruct data_llong_1_t { 41fe88d4270b6ab5358b8e28decc848c496f67988cjzha long long expected; 42fe88d4270b6ab5358b8e28decc848c496f67988cjzha T1 input; 43fe88d4270b6ab5358b8e28decc848c496f67988cjzha}; 44fe88d4270b6ab5358b8e28decc848c496f67988cjzha 451b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <typename RT, typename T1, typename T2> 461b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesstruct data_1_2_t { 471b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes RT expected; 481b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes T1 input1; 491b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes T2 input2; 501b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes}; 511b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 521b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <typename RT1, typename RT2, typename T> 531b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesstruct data_2_1_t { 541b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes RT1 expected1; 551b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes RT2 expected2; 561b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes T input; 571b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes}; 581b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 5956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <typename RT1, typename T> 6056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangstruct data_1_int_1_t { 6156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang RT1 expected1; 6256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang int expected2; 6356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang T input; 6456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang}; 6556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 6656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <typename RT1, typename T1, typename T2> 6756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangstruct data_1_int_2_t { 6856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang RT1 expected1; 6956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang int expected2; 7056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang T1 input1; 7156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang T2 input2; 7256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang}; 7356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 7456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <typename RT, typename T1, typename T2, typename T3> 7556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangstruct data_1_3_t { 7656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang RT expected; 7756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang T1 input1; 7856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang T2 input2; 7956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang T3 input3; 8056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang}; 8156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 821b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <typename T> union fp_u; 831b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 841b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <> union fp_u<float> { 851b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes float value; 861b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes struct { 871b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes unsigned frac:23; 881b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes unsigned exp:8; 891b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes unsigned sign:1; 901b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } bits; 911b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes uint32_t sign_magnitude; 921b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes}; 931b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 941b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <> union fp_u<double> { 951b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes double value; 961b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes struct { 971b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes unsigned fracl; 981b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes unsigned frach:20; 991b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes unsigned exp:11; 1001b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes unsigned sign:1; 1011b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } bits; 1021b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes uint64_t sign_magnitude; 1031b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes}; 1041b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 1051b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// TODO: long double. 1061b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 1071b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <typename T> 1081b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesstatic inline auto SignAndMagnitudeToBiased(const T& value) -> decltype(fp_u<T>::sign_magnitude) { 1091b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes fp_u<T> u; 1101b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes u.value = value; 1111b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes if (u.bits.sign) { 1121b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes return ~u.sign_magnitude + 1; 1131b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } else { 1141b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes u.bits.sign = 1; 1151b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes return u.sign_magnitude; 1161b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } 1171b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes} 1181b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 1191b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// Based on the existing googletest implementation, which uses a fixed 4 ulp bound. 1201b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <typename T> 1211b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughessize_t UlpDistance(T lhs, T rhs) { 1221b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes const auto biased1 = SignAndMagnitudeToBiased(lhs); 1231b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes const auto biased2 = SignAndMagnitudeToBiased(rhs); 1241b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); 1251b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes} 1261b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 1271b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <size_t ULP, typename T> 1281b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesstruct FpUlpEq { 1291b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes ::testing::AssertionResult operator()(const char* /* expected_expression */, 1301b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes const char* /* actual_expression */, 1311b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes T expected, 1321b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes T actual) { 1331b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes if (!isnan(expected) && !isnan(actual) && UlpDistance(expected, actual) <= ULP) { 1341b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes return ::testing::AssertionSuccess(); 1351b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } 1361b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 1371b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes // Output the actual and expected values as hex floating point. 1381b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes char expected_str[64]; 1391b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes char actual_str[64]; 1401b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes snprintf(expected_str, sizeof(expected_str), "%a", expected); 1411b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes snprintf(actual_str, sizeof(actual_str), "%a", actual); 1421b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 1431b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes return ::testing::AssertionFailure() 1441b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes << "expected (" << expected_str << ") != actual (" << actual_str << ")"; 1451b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } 1461b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes}; 1471b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 1481b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// Runs through the array 'data' applying 'f' to each of the input values 1491b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// and asserting that the result is within ULP ulps of the expected value. 1501b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// For testing a (double) -> double function like sin(3). 1511b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <size_t ULP, typename RT, typename T, size_t N> 1521b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesvoid DoMathDataTest(data_1_1_t<RT, T> (&data)[N], RT f(T)) { 1531b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes fesetenv(FE_DFL_ENV); 1541b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes FpUlpEq<ULP, RT> predicate; 1551b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes for (size_t i = 0; i < N; ++i) { 1561b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes EXPECT_PRED_FORMAT2(predicate, 1571b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes data[i].expected, f(data[i].input)) << "Failed on element " << i; 1581b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } 1591b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes} 1601b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 16156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// Runs through the array 'data' applying 'f' to each of the input values 16256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// and asserting that the result is within ULP ulps of the expected value. 16356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// For testing a (double) -> int function like ilogb(3). 16456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <size_t ULP, typename T, size_t N> 16556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangvoid DoMathDataTest(data_int_1_t<T> (&data)[N], int f(T)) { 16656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang fesetenv(FE_DFL_ENV); 16756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang for (size_t i = 0; i < N; ++i) { 16856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_EQ(data[i].expected, f(data[i].input)) << "Failed on element " << i; 16956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang } 17056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang} 17156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 172fe88d4270b6ab5358b8e28decc848c496f67988cjzha// Runs through the array 'data' applying 'f' to each of the input values 173fe88d4270b6ab5358b8e28decc848c496f67988cjzha// and asserting that the result is within ULP ulps of the expected value. 174fe88d4270b6ab5358b8e28decc848c496f67988cjzha// For testing a (double) -> long int function like lrint(3). 175fe88d4270b6ab5358b8e28decc848c496f67988cjzhatemplate <size_t ULP, typename T, size_t N> 176fe88d4270b6ab5358b8e28decc848c496f67988cjzhavoid DoMathDataTest(data_long_1_t<T> (&data)[N], long f(T)) { 177fe88d4270b6ab5358b8e28decc848c496f67988cjzha fesetenv(FE_DFL_ENV); 178fe88d4270b6ab5358b8e28decc848c496f67988cjzha for (size_t i = 0; i < N; ++i) { 179fe88d4270b6ab5358b8e28decc848c496f67988cjzha EXPECT_EQ(data[i].expected, f(data[i].input)) << "Failed on element " << i; 180fe88d4270b6ab5358b8e28decc848c496f67988cjzha } 181fe88d4270b6ab5358b8e28decc848c496f67988cjzha} 182fe88d4270b6ab5358b8e28decc848c496f67988cjzha 183fe88d4270b6ab5358b8e28decc848c496f67988cjzha// Runs through the array 'data' applying 'f' to each of the input values 184fe88d4270b6ab5358b8e28decc848c496f67988cjzha// and asserting that the result is within ULP ulps of the expected value. 185fe88d4270b6ab5358b8e28decc848c496f67988cjzha// For testing a (double) -> long long int function like llrint(3). 186fe88d4270b6ab5358b8e28decc848c496f67988cjzhatemplate <size_t ULP, typename T, size_t N> 187fe88d4270b6ab5358b8e28decc848c496f67988cjzhavoid DoMathDataTest(data_llong_1_t<T> (&data)[N], long long f(T)) { 188fe88d4270b6ab5358b8e28decc848c496f67988cjzha fesetenv(FE_DFL_ENV); 189fe88d4270b6ab5358b8e28decc848c496f67988cjzha for (size_t i = 0; i < N; ++i) { 190fe88d4270b6ab5358b8e28decc848c496f67988cjzha EXPECT_EQ(data[i].expected, f(data[i].input)) << "Failed on element " << i; 191fe88d4270b6ab5358b8e28decc848c496f67988cjzha } 192fe88d4270b6ab5358b8e28decc848c496f67988cjzha} 193fe88d4270b6ab5358b8e28decc848c496f67988cjzha 1941b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// Runs through the array 'data' applying 'f' to each of the pairs of input values 1951b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// and asserting that the result is within ULP ulps of the expected value. 1961b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// For testing a (double, double) -> double function like pow(3). 1971b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <size_t ULP, typename RT, typename T1, typename T2, size_t N> 1981b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesvoid DoMathDataTest(data_1_2_t<RT, T1, T2> (&data)[N], RT f(T1, T2)) { 1991b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes fesetenv(FE_DFL_ENV); 2001b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes FpUlpEq<ULP, RT> predicate; 2011b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes for (size_t i = 0; i < N; ++i) { 2021b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes EXPECT_PRED_FORMAT2(predicate, 2031b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes data[i].expected, f(data[i].input1, data[i].input2)) << "Failed on element " << i; 2041b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } 2051b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes} 2061b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes 2071b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// Runs through the array 'data' applying 'f' to each of the input values 2081b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// and asserting that the results are within ULP ulps of the expected values. 2091b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes// For testing a (double, double*, double*) -> void function like sincos(3). 2101b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughestemplate <size_t ULP, typename RT1, typename RT2, typename T1, size_t N> 2111b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughesvoid DoMathDataTest(data_2_1_t<RT1, RT2, T1> (&data)[N], void f(T1, RT1*, RT2*)) { 2121b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes fesetenv(FE_DFL_ENV); 2131b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes FpUlpEq<ULP, RT1> predicate1; 2141b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes FpUlpEq<ULP, RT2> predicate2; 2151b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes for (size_t i = 0; i < N; ++i) { 2161b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes RT1 out1; 2171b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes RT2 out2; 2181b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes f(data[i].input, &out1, &out2); 2191b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i; 2201b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes EXPECT_PRED_FORMAT2(predicate2, data[i].expected2, out2) << "Failed on element " << i; 2211b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes } 2221b37ba2178d618221905e17436f38e0c5a8397f3Elliott Hughes} 22356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 22456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// Runs through the array 'data' applying 'f' to each of the input values 22556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// and asserting that the results are within ULP ulps of the expected values. 22656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// For testing a (double, double*) -> double function like modf(3). 22756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <size_t ULP, typename RT1, typename RT2, typename T1, size_t N> 22856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangvoid DoMathDataTest(data_2_1_t<RT1, RT2, T1> (&data)[N], RT1 f(T1, RT2*)) { 22956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang fesetenv(FE_DFL_ENV); 23056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang FpUlpEq<ULP, RT1> predicate1; 23156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang FpUlpEq<ULP, RT2> predicate2; 23256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang for (size_t i = 0; i < N; ++i) { 23356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang RT1 out1; 23456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang RT2 out2; 23556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang out1 = f(data[i].input, &out2); 23656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i; 23756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_PRED_FORMAT2(predicate2, data[i].expected2, out2) << "Failed on element " << i; 23856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang } 23956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang} 24056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 24156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// Runs through the array 'data' applying 'f' to each of the input values 24256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// and asserting that the results are within ULP ulps of the expected values. 24356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// For testing a (double, int*) -> double function like frexp(3). 24456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <size_t ULP, typename RT1, typename T1, size_t N> 24556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangvoid DoMathDataTest(data_1_int_1_t<RT1, T1> (&data)[N], RT1 f(T1, int*)) { 24656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang fesetenv(FE_DFL_ENV); 24756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang FpUlpEq<ULP, RT1> predicate1; 24856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang for (size_t i = 0; i < N; ++i) { 24956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang RT1 out1; 25056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang int out2; 25156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang out1 = f(data[i].input, &out2); 25256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i; 25356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_EQ(data[i].expected2, out2) << "Failed on element " << i; 25456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang } 25556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang} 25656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 25756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// Runs through the array 'data' applying 'f' to each of the input values 25856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// and asserting that the results are within ULP ulps of the expected values. 25956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// For testing a (double, double, int*) -> double function like remquo(3). 26056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <size_t ULP, typename RT1, typename T1, typename T2, size_t N> 26156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangvoid DoMathDataTest(data_1_int_2_t<RT1, T1, T2> (&data)[N], RT1 f(T1, T2, int*)) { 26256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang fesetenv(FE_DFL_ENV); 26356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang FpUlpEq<ULP, RT1> predicate1; 26456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang for (size_t i = 0; i < N; ++i) { 26556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang RT1 out1; 26656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang int out2; 26756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang out1 = f(data[i].input1, data[i].input2, &out2); 26856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_PRED_FORMAT2(predicate1, data[i].expected1, out1) << "Failed on element " << i; 26956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_EQ(data[i].expected2, out2) << "Failed on element " << i; 27056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang } 27156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang} 27256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 27356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// Runs through the array 'data' applying 'f' to each of the pairs of input values 27456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// and asserting that the result is within ULP ulps of the expected value. 27556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang// For testing a (double, double, double) -> double function like fma(3). 27656b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangtemplate <size_t ULP, typename RT, typename T1, typename T2, typename T3, size_t N> 27756b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhangvoid DoMathDataTest(data_1_3_t<RT, T1, T2, T3> (&data)[N], RT f(T1, T2, T3)) { 27856b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang fesetenv(FE_DFL_ENV); 27956b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang FpUlpEq<ULP, RT> predicate; 28056b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang for (size_t i = 0; i < N; ++i) { 28156b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang EXPECT_PRED_FORMAT2(predicate, 28256b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang data[i].expected, f(data[i].input1, data[i].input2, data[i].input3)) << "Failed on element " << i; 28356b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang } 28456b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang} 28556b2b2916b72eb21352c7aed529e0deeb5582072Jingwei Zhang 286