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