brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.4 KiB · d4ab672 Raw
270 lines · c
1//===-- MPCUtils.h ----------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_UTILS_MPCWRAPPER_MPCUTILS_H10#define LLVM_LIBC_UTILS_MPCWRAPPER_MPCUTILS_H11 12#include "hdr/stdint_proxy.h"13#include "src/__support/CPP/type_traits.h"14#include "src/__support/complex_type.h"15#include "src/__support/macros/config.h"16#include "src/__support/macros/properties/complex_types.h"17#include "src/__support/macros/properties/types.h"18#include "test/UnitTest/RoundingModeUtils.h"19#include "test/UnitTest/Test.h"20 21namespace LIBC_NAMESPACE_DECL {22namespace testing {23namespace mpc {24 25enum class Operation {26  // Operations which take a single complex floating point number as input27  // and produce a single floating point number as output which has the same28  // floating point type as the real/imaginary part of the input.29  BeginUnaryOperationsSingleOutputDifferentOutputType,30  Carg,31  Cabs,32  EndUnaryOperationsSingleOutputDifferentOutputType,33 34  // Operations which take a single complex floating point number as input35  // and produce a single complex floating point number of the same kind36  // as output.37  BeginUnaryOperationsSingleOutputSameOutputType,38  Cproj,39  Csqrt,40  Clog,41  Cexp,42  Csinh,43  Ccosh,44  Ctanh,45  Casinh,46  Cacosh,47  Catanh,48  Csin,49  Ccos,50  Ctan,51  Casin,52  Cacos,53  Catan,54  EndUnaryOperationsSingleOutputSameOutputType,55 56  // Operations which take two complex floating point numbers as input57  // and produce a single complex floating point number of the same kind58  // as output.59  BeginBinaryOperationsSingleOutput,60  Cpow,61  EndBinaryOperationsSingleOutput,62};63 64using LIBC_NAMESPACE::fputil::testing::RoundingMode;65 66template <typename T> struct BinaryInput {67  static_assert(LIBC_NAMESPACE::cpp::is_complex_v<T>,68                "Template parameter of BinaryInput must be a complex floating "69                "point type.");70 71  using Type = T;72  T x, y;73};74 75namespace internal {76 77template <typename InputType, typename OutputType>78bool compare_unary_operation_single_output_same_type(Operation op,79                                                     InputType input,80                                                     OutputType libc_output,81                                                     double ulp_tolerance,82                                                     RoundingMode rounding);83 84template <typename InputType, typename OutputType>85bool compare_unary_operation_single_output_different_type(86    Operation op, InputType input, OutputType libc_output, double ulp_tolerance,87    RoundingMode rounding);88 89template <typename InputType, typename OutputType>90bool compare_binary_operation_one_output(Operation op,91                                         const BinaryInput<InputType> &input,92                                         OutputType libc_output,93                                         double ulp_tolerance,94                                         RoundingMode rounding);95 96template <typename InputType, typename OutputType>97void explain_unary_operation_single_output_same_type_error(98    Operation op, InputType input, OutputType match_value, double ulp_tolerance,99    RoundingMode rounding);100 101template <typename InputType, typename OutputType>102void explain_unary_operation_single_output_different_type_error(103    Operation op, InputType input, OutputType match_value, double ulp_tolerance,104    RoundingMode rounding);105 106template <typename InputType, typename OutputType>107void explain_binary_operation_one_output_error(108    Operation op, const BinaryInput<InputType> &input, OutputType match_value,109    double ulp_tolerance, RoundingMode rounding);110 111template <Operation op, typename InputType, typename OutputType>112class MPCMatcher : public testing::Matcher<OutputType> {113private:114  InputType input;115  OutputType match_value;116  double ulp_tolerance;117  RoundingMode rounding;118 119public:120  MPCMatcher(InputType testInput, double ulp_tolerance, RoundingMode rounding)121      : input(testInput), ulp_tolerance(ulp_tolerance), rounding(rounding) {}122 123  bool match(OutputType libcResult) {124    match_value = libcResult;125    return match(input, match_value);126  }127 128  void explainError() override { // NOLINT129    explain_error(input, match_value);130  }131 132private:133  template <typename InType, typename OutType>134  bool match(InType in, OutType out) {135    if (cpp::is_same_v<InType, OutType>) {136      return compare_unary_operation_single_output_same_type(137          op, in, out, ulp_tolerance, rounding);138    } else {139      return compare_unary_operation_single_output_different_type(140          op, in, out, ulp_tolerance, rounding);141    }142  }143 144  template <typename T, typename U>145  bool match(const BinaryInput<T> &in, U out) {146    return compare_binary_operation_one_output(op, in, out, ulp_tolerance,147                                               rounding);148  }149 150  template <typename InType, typename OutType>151  void explain_error(InType in, OutType out) {152    if (cpp::is_same_v<InType, OutType>) {153      explain_unary_operation_single_output_same_type_error(154          op, in, out, ulp_tolerance, rounding);155    } else {156      explain_unary_operation_single_output_different_type_error(157          op, in, out, ulp_tolerance, rounding);158    }159  }160 161  template <typename T, typename U>162  void explain_error(const BinaryInput<T> &in, U out) {163    explain_binary_operation_one_output_error(op, in, out, ulp_tolerance,164                                              rounding);165  }166};167 168} // namespace internal169 170// Return true if the input and ouput types for the operation op are valid171// types.172template <Operation op, typename InputType, typename OutputType>173constexpr bool is_valid_operation() {174  return (Operation::BeginBinaryOperationsSingleOutput < op &&175          op < Operation::EndBinaryOperationsSingleOutput &&176          cpp::is_complex_type_same<InputType, OutputType>() &&177          cpp::is_complex_v<InputType>) ||178         (Operation::BeginUnaryOperationsSingleOutputSameOutputType < op &&179          op < Operation::EndUnaryOperationsSingleOutputSameOutputType &&180          cpp::is_complex_type_same<InputType, OutputType>() &&181          cpp::is_complex_v<InputType>) ||182         (Operation::BeginUnaryOperationsSingleOutputDifferentOutputType < op &&183          op < Operation::EndUnaryOperationsSingleOutputDifferentOutputType &&184          cpp::is_same_v<make_real_t<InputType>, OutputType> &&185          cpp::is_complex_v<InputType>);186}187 188template <Operation op, typename InputType, typename OutputType>189cpp::enable_if_t<is_valid_operation<op, InputType, OutputType>(),190                 internal::MPCMatcher<op, InputType, OutputType>>191get_mpc_matcher(InputType input, [[maybe_unused]] OutputType output,192                double ulp_tolerance, RoundingMode rounding) {193  return internal::MPCMatcher<op, InputType, OutputType>(input, ulp_tolerance,194                                                         rounding);195}196 197} // namespace mpc198} // namespace testing199} // namespace LIBC_NAMESPACE_DECL200 201#define EXPECT_MPC_MATCH_DEFAULT(op, input, match_value, ulp_tolerance)        \202  EXPECT_THAT(match_value,                                                     \203              LIBC_NAMESPACE::testing::mpc::get_mpc_matcher<op>(               \204                  input, match_value, ulp_tolerance,                           \205                  LIBC_NAMESPACE::fputil::testing::RoundingMode::Nearest))206 207#define EXPECT_MPC_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,       \208                                  rounding)                                    \209  EXPECT_THAT(match_value, LIBC_NAMESPACE::testing::mpc::get_mpc_matcher<op>(  \210                               input, match_value, ulp_tolerance, rounding))211 212#define EXPECT_MPC_MATCH_ALL_ROUNDING_HELPER(op, input, match_value,           \213                                             ulp_tolerance, rounding)          \214  {                                                                            \215    MPCRND::ForceRoundingMode __r(rounding);                                   \216    if (__r.success) {                                                         \217      EXPECT_MPC_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,         \218                                rounding);                                     \219    }                                                                          \220  }221 222#define EXPECT_MPC_MATCH_ALL_ROUNDING(op, input, match_value, ulp_tolerance)   \223  {                                                                            \224    namespace MPCRND = LIBC_NAMESPACE::fputil::testing;                        \225    for (int i = 0; i < 4; i++) {                                              \226      MPCRND::RoundingMode r_mode = static_cast<MPCRND::RoundingMode>(i);      \227      EXPECT_MPC_MATCH_ALL_ROUNDING_HELPER(op, input, match_value,             \228                                           ulp_tolerance, r_mode);             \229    }                                                                          \230  }231 232#define TEST_MPC_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,         \233                                rounding)                                      \234  LIBC_NAMESPACE::testing::mpc::get_mpc_matcher<op>(input, match_value,        \235                                                    ulp_tolerance, rounding)   \236      .match(match_value)237 238#define ASSERT_MPC_MATCH_DEFAULT(op, input, match_value, ulp_tolerance)        \239  ASSERT_THAT(match_value,                                                     \240              LIBC_NAMESPACE::testing::mpc::get_mpc_matcher<op>(               \241                  input, match_value, ulp_tolerance,                           \242                  LIBC_NAMESPACE::fputil::testing::RoundingMode::Nearest))243 244#define ASSERT_MPC_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,       \245                                  rounding)                                    \246  ASSERT_THAT(match_value, LIBC_NAMESPACE::testing::mpc::get_mpc_matcher<op>(  \247                               input, match_value, ulp_tolerance, rounding))248 249#define ASSERT_MPC_MATCH_ALL_ROUNDING_HELPER(op, input, match_value,           \250                                             ulp_tolerance, rounding)          \251  {                                                                            \252    MPCRND::ForceRoundingMode __r(rounding);                                   \253    if (__r.success) {                                                         \254      ASSERT_MPC_MATCH_ROUNDING(op, input, match_value, ulp_tolerance,         \255                                rounding);                                     \256    }                                                                          \257  }258 259#define ASSERT_MPC_MATCH_ALL_ROUNDING(op, input, match_value, ulp_tolerance)   \260  {                                                                            \261    namespace MPCRND = LIBC_NAMESPACE::fputil::testing;                        \262    for (int i = 0; i < 4; i++) {                                              \263      MPCRND::RoundingMode r_mode = static_cast<MPCRND::RoundingMode>(i);      \264      ASSERT_MPC_MATCH_ALL_ROUNDING_HELPER(op, input, match_value,             \265                                           ulp_tolerance, r_mode);             \266    }                                                                          \267  }268 269#endif // LLVM_LIBC_UTILS_MPCWRAPPER_MPCUTILS_H270