brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.1 KiB · a7d307b Raw
849 lines · cpp
1//===-- Utils which wrap MPFR ---------------------------------------------===//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#include "MPFRUtils.h"10#include "MPCommon.h"11 12#include "src/__support/CPP/array.h"13#include "src/__support/CPP/stringstream.h"14#include "src/__support/FPUtil/bfloat16.h"15#include "src/__support/FPUtil/fpbits_str.h"16#include "src/__support/macros/config.h"17#include "src/__support/macros/properties/types.h"18 19namespace LIBC_NAMESPACE_DECL {20namespace testing {21namespace mpfr {22namespace internal {23 24template <typename InputType>25cpp::enable_if_t<cpp::is_floating_point_v<InputType>, MPFRNumber>26unary_operation(Operation op, InputType input, unsigned int precision,27                RoundingMode rounding) {28  MPFRNumber mpfrInput(input, precision, rounding);29  switch (op) {30  case Operation::Abs:31    return mpfrInput.abs();32  case Operation::Acos:33    return mpfrInput.acos();34  case Operation::Acosh:35    return mpfrInput.acosh();36  case Operation::Acospi:37    return mpfrInput.acospi();38  case Operation::Asin:39    return mpfrInput.asin();40  case Operation::Asinh:41    return mpfrInput.asinh();42  case Operation::Asinpi:43    return mpfrInput.asinpi();44  case Operation::Atan:45    return mpfrInput.atan();46  case Operation::Atanh:47    return mpfrInput.atanh();48  case Operation::Atanpi:49    return mpfrInput.atanpi();50  case Operation::Cbrt:51    return mpfrInput.cbrt();52  case Operation::Ceil:53    return mpfrInput.ceil();54  case Operation::Cos:55    return mpfrInput.cos();56  case Operation::Cosh:57    return mpfrInput.cosh();58  case Operation::Cospi:59    return mpfrInput.cospi();60  case Operation::Erf:61    return mpfrInput.erf();62  case Operation::Exp:63    return mpfrInput.exp();64  case Operation::Exp2:65    return mpfrInput.exp2();66  case Operation::Exp2m1:67    return mpfrInput.exp2m1();68  case Operation::Exp10:69    return mpfrInput.exp10();70  case Operation::Exp10m1:71    return mpfrInput.exp10m1();72  case Operation::Expm1:73    return mpfrInput.expm1();74  case Operation::Floor:75    return mpfrInput.floor();76  case Operation::Log:77    return mpfrInput.log();78  case Operation::Log2:79    return mpfrInput.log2();80  case Operation::Log10:81    return mpfrInput.log10();82  case Operation::Log1p:83    return mpfrInput.log1p();84  case Operation::Mod2PI:85    return mpfrInput.mod_2pi();86  case Operation::ModPIOver2:87    return mpfrInput.mod_pi_over_2();88  case Operation::ModPIOver4:89    return mpfrInput.mod_pi_over_4();90  case Operation::Round:91    return mpfrInput.round();92  case Operation::RoundEven:93    return mpfrInput.roundeven();94  case Operation::Rsqrt:95    return mpfrInput.rsqrt();96  case Operation::Sin:97    return mpfrInput.sin();98  case Operation::Sinpi:99    return mpfrInput.sinpi();100  case Operation::Sinh:101    return mpfrInput.sinh();102  case Operation::Sqrt:103    return mpfrInput.sqrt();104  case Operation::Tan:105    return mpfrInput.tan();106  case Operation::Tanh:107    return mpfrInput.tanh();108  case Operation::Tanpi:109    return mpfrInput.tanpi();110  case Operation::Trunc:111    return mpfrInput.trunc();112  default:113    __builtin_unreachable();114  }115}116 117template <typename InputType>118cpp::enable_if_t<cpp::is_floating_point_v<InputType>, MPFRNumber>119unary_operation_two_outputs(Operation op, InputType input, int &output,120                            unsigned int precision, RoundingMode rounding) {121  MPFRNumber mpfrInput(input, precision, rounding);122  switch (op) {123  case Operation::Frexp:124    return mpfrInput.frexp(output);125  default:126    __builtin_unreachable();127  }128}129 130template <typename InputType>131cpp::enable_if_t<cpp::is_floating_point_v<InputType>, MPFRNumber>132binary_operation_one_output(Operation op, InputType x, InputType y,133                            unsigned int precision, RoundingMode rounding) {134  MPFRNumber inputX(x, precision, rounding);135  MPFRNumber inputY(y, precision, rounding);136  switch (op) {137  case Operation::Add:138    return inputX.add(inputY);139  case Operation::Atan2:140    return inputX.atan2(inputY);141  case Operation::Div:142    return inputX.div(inputY);143  case Operation::Fmod:144    return inputX.fmod(inputY);145  case Operation::Hypot:146    return inputX.hypot(inputY);147  case Operation::Mul:148    return inputX.mul(inputY);149  case Operation::Pow:150    return inputX.pow(inputY);151  case Operation::Sub:152    return inputX.sub(inputY);153  default:154    __builtin_unreachable();155  }156}157 158template <typename InputType>159cpp::enable_if_t<cpp::is_floating_point_v<InputType>, MPFRNumber>160binary_operation_two_outputs(Operation op, InputType x, InputType y,161                             int &output, unsigned int precision,162                             RoundingMode rounding) {163  MPFRNumber inputX(x, precision, rounding);164  MPFRNumber inputY(y, precision, rounding);165  switch (op) {166  case Operation::RemQuo:167    return inputX.remquo(inputY, output);168  default:169    __builtin_unreachable();170  }171}172 173template <typename InputType>174cpp::enable_if_t<cpp::is_floating_point_v<InputType>, MPFRNumber>175ternary_operation_one_output(Operation op, InputType x, InputType y,176                             InputType z, unsigned int precision,177                             RoundingMode rounding) {178  // For FMA function, we just need to compare with the mpfr_fma with the same179  // precision as InputType.  Using higher precision as the intermediate results180  // to compare might incorrectly fail due to double-rounding errors.181  MPFRNumber inputX(x, precision, rounding);182  MPFRNumber inputY(y, precision, rounding);183  MPFRNumber inputZ(z, precision, rounding);184  switch (op) {185  case Operation::Fma:186    return inputX.fma(inputY, inputZ);187  default:188    __builtin_unreachable();189  }190}191 192// Remark: For all the explain_*_error functions, we will use std::stringstream193// to build the complete error messages before sending it to the outstream `OS`194// once at the end.  This will stop the error messages from interleaving when195// the tests are running concurrently.196template <typename InputType, typename OutputType>197void explain_unary_operation_single_output_error(Operation op, InputType input,198                                                 OutputType matchValue,199                                                 double ulp_tolerance,200                                                 RoundingMode rounding) {201  unsigned int precision = get_precision<InputType>(ulp_tolerance);202  MPFRNumber mpfrInput(input, precision);203  MPFRNumber mpfr_result;204  mpfr_result = unary_operation(op, input, precision, rounding);205  MPFRNumber mpfrMatchValue(matchValue);206  cpp::array<char, 1024> msg_buf;207  cpp::StringStream msg(msg_buf);208  msg << "Match value not within tolerance value of MPFR result:\n"209      << "  Input decimal: " << mpfrInput.str() << '\n';210  msg << "     Input bits: " << str(FPBits<InputType>(input)) << '\n';211  msg << '\n' << "  Match decimal: " << mpfrMatchValue.str() << '\n';212  msg << "     Match bits: " << str(FPBits<OutputType>(matchValue)) << '\n';213  msg << '\n' << "    MPFR result: " << mpfr_result.str() << '\n';214  msg << "   MPFR rounded: "215      << str(FPBits<OutputType>(mpfr_result.as<OutputType>())) << '\n';216  msg << '\n';217  msg << "      ULP error: " << mpfr_result.ulp_as_mpfr_number(matchValue).str()218      << '\n';219  if (msg.overflow())220    __builtin_unreachable();221  tlog << msg.str();222}223 224template void explain_unary_operation_single_output_error(Operation op, float,225                                                          float, double,226                                                          RoundingMode);227template void explain_unary_operation_single_output_error(Operation op, double,228                                                          double, double,229                                                          RoundingMode);230template void explain_unary_operation_single_output_error(Operation op,231                                                          long double,232                                                          long double, double,233                                                          RoundingMode);234template void explain_unary_operation_single_output_error(Operation op, double,235                                                          float, double,236                                                          RoundingMode);237template void explain_unary_operation_single_output_error(Operation op,238                                                          long double, float,239                                                          double, RoundingMode);240template void explain_unary_operation_single_output_error(Operation op,241                                                          long double, double,242                                                          double, RoundingMode);243 244#ifdef LIBC_TYPES_HAS_FLOAT16245template void explain_unary_operation_single_output_error(Operation op, float16,246                                                          float16, double,247                                                          RoundingMode);248template void explain_unary_operation_single_output_error(Operation op, float,249                                                          float16, double,250                                                          RoundingMode);251template void explain_unary_operation_single_output_error(Operation op, double,252                                                          float16, double,253                                                          RoundingMode);254template void explain_unary_operation_single_output_error(Operation op,255                                                          long double, float16,256                                                          double, RoundingMode);257#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE258template void explain_unary_operation_single_output_error(Operation op,259                                                          float128, float16,260                                                          double, RoundingMode);261#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE262#endif // LIBC_TYPES_HAS_FLOAT16263 264#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE265template void explain_unary_operation_single_output_error(Operation op,266                                                          float128, float128,267                                                          double, RoundingMode);268template void explain_unary_operation_single_output_error(Operation op,269                                                          float128, float,270                                                          double, RoundingMode);271template void explain_unary_operation_single_output_error(Operation op,272                                                          float128, double,273                                                          double, RoundingMode);274template void explain_unary_operation_single_output_error(Operation op,275                                                          float128, long double,276                                                          double, RoundingMode);277#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE278 279template void explain_unary_operation_single_output_error(Operation op,280                                                          bfloat16, bfloat16,281                                                          double, RoundingMode);282 283template <typename T>284void explain_unary_operation_two_outputs_error(285    Operation op, T input, const BinaryOutput<T> &libc_result,286    double ulp_tolerance, RoundingMode rounding) {287  unsigned int precision = get_precision<T>(ulp_tolerance);288  MPFRNumber mpfrInput(input, precision);289  int mpfrIntResult;290  MPFRNumber mpfr_result = unary_operation_two_outputs(op, input, mpfrIntResult,291                                                       precision, rounding);292 293  if (mpfrIntResult != libc_result.i) {294    tlog << "MPFR integral result: " << mpfrIntResult << '\n'295         << "Libc integral result: " << libc_result.i << '\n';296  } else {297    tlog << "Integral result from libc matches integral result from MPFR.\n";298  }299 300  MPFRNumber mpfrMatchValue(libc_result.f);301  tlog302      << "Libc floating point result is not within tolerance value of the MPFR "303      << "result.\n\n";304 305  tlog << "            Input decimal: " << mpfrInput.str() << "\n\n";306 307  tlog << "Libc floating point value: " << mpfrMatchValue.str() << '\n';308  tlog << " Libc floating point bits: " << str(FPBits<T>(libc_result.f))309       << '\n';310  tlog << "\n\n";311 312  tlog << "              MPFR result: " << mpfr_result.str() << '\n';313  tlog << "             MPFR rounded: " << str(FPBits<T>(mpfr_result.as<T>()))314       << '\n';315  tlog << '\n'316       << "                ULP error: "317       << mpfr_result.ulp_as_mpfr_number(libc_result.f).str() << '\n';318}319 320template void explain_unary_operation_two_outputs_error<float>(321    Operation, float, const BinaryOutput<float> &, double, RoundingMode);322template void explain_unary_operation_two_outputs_error<double>(323    Operation, double, const BinaryOutput<double> &, double, RoundingMode);324template void explain_unary_operation_two_outputs_error<long double>(325    Operation, long double, const BinaryOutput<long double> &, double,326    RoundingMode);327 328template <typename T>329void explain_binary_operation_two_outputs_error(330    Operation op, const BinaryInput<T> &input,331    const BinaryOutput<T> &libc_result, double ulp_tolerance,332    RoundingMode rounding) {333  unsigned int precision = get_precision<T>(ulp_tolerance);334  MPFRNumber mpfrX(input.x, precision);335  MPFRNumber mpfrY(input.y, precision);336  int mpfrIntResult;337  MPFRNumber mpfr_result = binary_operation_two_outputs(338      op, input.x, input.y, mpfrIntResult, precision, rounding);339  MPFRNumber mpfrMatchValue(libc_result.f);340 341  tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n'342       << "MPFR integral result: " << mpfrIntResult << '\n'343       << "Libc integral result: " << libc_result.i << '\n'344       << "Libc floating point result: " << mpfrMatchValue.str() << '\n'345       << "               MPFR result: " << mpfr_result.str() << '\n';346  tlog << "Libc floating point result bits: " << str(FPBits<T>(libc_result.f))347       << '\n';348  tlog << "              MPFR rounded bits: "349       << str(FPBits<T>(mpfr_result.as<T>())) << '\n';350  tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result.f).str()351       << '\n';352}353 354template void explain_binary_operation_two_outputs_error<float>(355    Operation, const BinaryInput<float> &, const BinaryOutput<float> &, double,356    RoundingMode);357template void explain_binary_operation_two_outputs_error<double>(358    Operation, const BinaryInput<double> &, const BinaryOutput<double> &,359    double, RoundingMode);360template void explain_binary_operation_two_outputs_error<long double>(361    Operation, const BinaryInput<long double> &,362    const BinaryOutput<long double> &, double, RoundingMode);363 364template <typename InputType, typename OutputType>365void explain_binary_operation_one_output_error(366    Operation op, const BinaryInput<InputType> &input, OutputType libc_result,367    double ulp_tolerance, RoundingMode rounding) {368  unsigned int precision = get_precision<InputType>(ulp_tolerance);369  MPFRNumber mpfrX(input.x, precision);370  MPFRNumber mpfrY(input.y, precision);371  FPBits<InputType> xbits(input.x);372  FPBits<InputType> ybits(input.y);373  MPFRNumber mpfr_result =374      binary_operation_one_output(op, input.x, input.y, precision, rounding);375  MPFRNumber mpfrMatchValue(libc_result);376 377  tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n';378  tlog << "First input bits: " << str(FPBits<InputType>(input.x)) << '\n';379  tlog << "Second input bits: " << str(FPBits<InputType>(input.y)) << '\n';380 381  tlog << "Libc result: " << mpfrMatchValue.str() << '\n'382       << "MPFR result: " << mpfr_result.str() << '\n';383  tlog << "Libc floating point result bits: "384       << str(FPBits<OutputType>(libc_result)) << '\n';385  tlog << "              MPFR rounded bits: "386       << str(FPBits<OutputType>(mpfr_result.as<OutputType>())) << '\n';387  tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str()388       << '\n';389}390 391template void392explain_binary_operation_one_output_error(Operation, const BinaryInput<float> &,393                                          float, double, RoundingMode);394template void explain_binary_operation_one_output_error(395    Operation, const BinaryInput<double> &, float, double, RoundingMode);396template void explain_binary_operation_one_output_error(397    Operation, const BinaryInput<double> &, double, double, RoundingMode);398template void explain_binary_operation_one_output_error(399    Operation, const BinaryInput<long double> &, float, double, RoundingMode);400template void explain_binary_operation_one_output_error(401    Operation, const BinaryInput<long double> &, double, double, RoundingMode);402template void403explain_binary_operation_one_output_error(Operation,404                                          const BinaryInput<long double> &,405                                          long double, double, RoundingMode);406#ifdef LIBC_TYPES_HAS_FLOAT16407template void explain_binary_operation_one_output_error(408    Operation, const BinaryInput<float16> &, float16, double, RoundingMode);409template void410explain_binary_operation_one_output_error(Operation, const BinaryInput<float> &,411                                          float16, double, RoundingMode);412template void explain_binary_operation_one_output_error(413    Operation, const BinaryInput<double> &, float16, double, RoundingMode);414template void explain_binary_operation_one_output_error(415    Operation, const BinaryInput<long double> &, float16, double, RoundingMode);416#endif417#if defined(LIBC_TYPES_HAS_FLOAT128) &&                                        \418    defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)419template void explain_binary_operation_one_output_error(420    Operation, const BinaryInput<float128> &, float128, double, RoundingMode);421#endif422template void explain_binary_operation_one_output_error(423    Operation, const BinaryInput<bfloat16> &, bfloat16, double, RoundingMode);424template void425explain_binary_operation_one_output_error(Operation, const BinaryInput<float> &,426                                          bfloat16, double, RoundingMode);427template void explain_binary_operation_one_output_error(428    Operation, const BinaryInput<double> &, bfloat16, double, RoundingMode);429template void430explain_binary_operation_one_output_error(Operation,431                                          const BinaryInput<long double> &,432                                          bfloat16, double, RoundingMode);433#if defined(LIBC_TYPES_HAS_FLOAT128) &&                                        \434    defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)435template void explain_binary_operation_one_output_error(436    Operation, const BinaryInput<float128> &, bfloat16, double, RoundingMode);437#endif // defined(LIBC_TYPES_HAS_FLOAT128) &&438       // defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)439 440template <typename InputType, typename OutputType>441void explain_ternary_operation_one_output_error(442    Operation op, const TernaryInput<InputType> &input, OutputType libc_result,443    double ulp_tolerance, RoundingMode rounding) {444  unsigned int precision = get_precision<InputType>(ulp_tolerance);445  MPFRNumber mpfrX(input.x, precision);446  MPFRNumber mpfrY(input.y, precision);447  MPFRNumber mpfrZ(input.z, precision);448  FPBits<InputType> xbits(input.x);449  FPBits<InputType> ybits(input.y);450  FPBits<InputType> zbits(input.z);451  MPFRNumber mpfr_result = ternary_operation_one_output(452      op, input.x, input.y, input.z, precision, rounding);453  MPFRNumber mpfrMatchValue(libc_result);454 455  tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str()456       << " z: " << mpfrZ.str() << '\n';457  tlog << " First input bits: " << str(FPBits<InputType>(input.x)) << '\n';458  tlog << "Second input bits: " << str(FPBits<InputType>(input.y)) << '\n';459  tlog << " Third input bits: " << str(FPBits<InputType>(input.z)) << '\n';460 461  tlog << "Libc result: " << mpfrMatchValue.str() << '\n'462       << "MPFR result: " << mpfr_result.str() << '\n';463  tlog << "Libc floating point result bits: "464       << str(FPBits<OutputType>(libc_result)) << '\n';465  tlog << "              MPFR rounded bits: "466       << str(FPBits<OutputType>(mpfr_result.as<OutputType>())) << '\n';467  tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str()468       << '\n';469}470 471template void explain_ternary_operation_one_output_error(472    Operation, const TernaryInput<float> &, float, double, RoundingMode);473template void explain_ternary_operation_one_output_error(474    Operation, const TernaryInput<double> &, float, double, RoundingMode);475template void explain_ternary_operation_one_output_error(476    Operation, const TernaryInput<double> &, double, double, RoundingMode);477template void explain_ternary_operation_one_output_error(478    Operation, const TernaryInput<long double> &, float, double, RoundingMode);479template void explain_ternary_operation_one_output_error(480    Operation, const TernaryInput<long double> &, double, double, RoundingMode);481template void482explain_ternary_operation_one_output_error(Operation,483                                           const TernaryInput<long double> &,484                                           long double, double, RoundingMode);485 486#ifdef LIBC_TYPES_HAS_FLOAT16487template void explain_ternary_operation_one_output_error(488    Operation, const TernaryInput<float16> &, float16, double, RoundingMode);489template void explain_ternary_operation_one_output_error(490    Operation, const TernaryInput<float> &, float16, double, RoundingMode);491template void explain_ternary_operation_one_output_error(492    Operation, const TernaryInput<double> &, float16, double, RoundingMode);493template void494explain_ternary_operation_one_output_error(Operation,495                                           const TernaryInput<long double> &,496                                           float16, double, RoundingMode);497#endif498 499template void explain_ternary_operation_one_output_error(500    Operation, const TernaryInput<float> &, bfloat16, double, RoundingMode);501template void explain_ternary_operation_one_output_error(502    Operation, const TernaryInput<double> &, bfloat16, double, RoundingMode);503template void504explain_ternary_operation_one_output_error(Operation,505                                           const TernaryInput<long double> &,506                                           bfloat16, double, RoundingMode);507#if defined(LIBC_TYPES_HAS_FLOAT128) &&                                        \508    defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)509template void explain_ternary_operation_one_output_error(510    Operation, const TernaryInput<float128> &, bfloat16, double, RoundingMode);511#endif // defined(LIBC_TYPES_HAS_FLOAT128) &&512       // defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)513 514template <typename InputType, typename OutputType>515bool compare_unary_operation_single_output(Operation op, InputType input,516                                           OutputType libc_result,517                                           double ulp_tolerance,518                                           RoundingMode rounding) {519  unsigned int precision = get_precision<InputType>(ulp_tolerance);520  MPFRNumber mpfr_result;521  mpfr_result = unary_operation(op, input, precision, rounding);522  double ulp = mpfr_result.ulp(libc_result);523  return (ulp <= ulp_tolerance);524}525 526template bool compare_unary_operation_single_output(Operation, float, float,527                                                    double, RoundingMode);528template bool compare_unary_operation_single_output(Operation, double, double,529                                                    double, RoundingMode);530template bool compare_unary_operation_single_output(Operation, long double,531                                                    long double, double,532                                                    RoundingMode);533template bool compare_unary_operation_single_output(Operation, double, float,534                                                    double, RoundingMode);535template bool compare_unary_operation_single_output(Operation, long double,536                                                    float, double,537                                                    RoundingMode);538template bool compare_unary_operation_single_output(Operation, long double,539                                                    double, double,540                                                    RoundingMode);541#ifdef LIBC_TYPES_HAS_FLOAT16542template bool compare_unary_operation_single_output(Operation, float16, float16,543                                                    double, RoundingMode);544template bool compare_unary_operation_single_output(Operation, float, float16,545                                                    double, RoundingMode);546template bool compare_unary_operation_single_output(Operation, double, float16,547                                                    double, RoundingMode);548template bool compare_unary_operation_single_output(Operation, long double,549                                                    float16, double,550                                                    RoundingMode);551#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE552template bool compare_unary_operation_single_output(Operation, float128,553                                                    float16, double,554                                                    RoundingMode);555#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE556#endif // LIBC_TYPES_HAS_FLOAT16557 558#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE559template bool compare_unary_operation_single_output(Operation, float128,560                                                    float128, double,561                                                    RoundingMode);562template bool compare_unary_operation_single_output(Operation, float128, float,563                                                    double, RoundingMode);564template bool compare_unary_operation_single_output(Operation, float128, double,565                                                    double, RoundingMode);566template bool compare_unary_operation_single_output(Operation, float128,567                                                    long double, double,568                                                    RoundingMode);569#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE570template bool compare_unary_operation_single_output(Operation, bfloat16,571                                                    bfloat16, double,572                                                    RoundingMode);573 574template <typename T>575bool compare_unary_operation_two_outputs(Operation op, T input,576                                         const BinaryOutput<T> &libc_result,577                                         double ulp_tolerance,578                                         RoundingMode rounding) {579  int mpfrIntResult;580  unsigned int precision = get_precision<T>(ulp_tolerance);581  MPFRNumber mpfr_result = unary_operation_two_outputs(op, input, mpfrIntResult,582                                                       precision, rounding);583  double ulp = mpfr_result.ulp(libc_result.f);584 585  if (mpfrIntResult != libc_result.i)586    return false;587 588  return (ulp <= ulp_tolerance);589}590 591template bool compare_unary_operation_two_outputs<float>(592    Operation, float, const BinaryOutput<float> &, double, RoundingMode);593template bool compare_unary_operation_two_outputs<double>(594    Operation, double, const BinaryOutput<double> &, double, RoundingMode);595template bool compare_unary_operation_two_outputs<long double>(596    Operation, long double, const BinaryOutput<long double> &, double,597    RoundingMode);598 599template <typename T>600bool compare_binary_operation_two_outputs(Operation op,601                                          const BinaryInput<T> &input,602                                          const BinaryOutput<T> &libc_result,603                                          double ulp_tolerance,604                                          RoundingMode rounding) {605  int mpfrIntResult;606  unsigned int precision = get_precision<T>(ulp_tolerance);607  MPFRNumber mpfr_result = binary_operation_two_outputs(608      op, input.x, input.y, mpfrIntResult, precision, rounding);609  double ulp = mpfr_result.ulp(libc_result.f);610 611  if (mpfrIntResult != libc_result.i) {612    if (op == Operation::RemQuo) {613      if ((0x7 & mpfrIntResult) != (0x7 & libc_result.i))614        return false;615    } else {616      return false;617    }618  }619 620  return (ulp <= ulp_tolerance);621}622 623template bool compare_binary_operation_two_outputs<float>(624    Operation, const BinaryInput<float> &, const BinaryOutput<float> &, double,625    RoundingMode);626template bool compare_binary_operation_two_outputs<double>(627    Operation, const BinaryInput<double> &, const BinaryOutput<double> &,628    double, RoundingMode);629template bool compare_binary_operation_two_outputs<long double>(630    Operation, const BinaryInput<long double> &,631    const BinaryOutput<long double> &, double, RoundingMode);632 633template <typename InputType, typename OutputType>634bool compare_binary_operation_one_output(Operation op,635                                         const BinaryInput<InputType> &input,636                                         OutputType libc_result,637                                         double ulp_tolerance,638                                         RoundingMode rounding) {639  unsigned int precision = get_precision<InputType>(ulp_tolerance);640  MPFRNumber mpfr_result =641      binary_operation_one_output(op, input.x, input.y, precision, rounding);642  double ulp = mpfr_result.ulp(libc_result);643 644  return (ulp <= ulp_tolerance);645}646 647template bool compare_binary_operation_one_output(Operation,648                                                  const BinaryInput<float> &,649                                                  float, double, RoundingMode);650template bool compare_binary_operation_one_output(Operation,651                                                  const BinaryInput<double> &,652                                                  double, double, RoundingMode);653template bool654compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,655                                    float, double, RoundingMode);656template bool657compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,658                                    double, double, RoundingMode);659template bool660compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,661                                    long double, double, RoundingMode);662 663template bool compare_binary_operation_one_output(Operation,664                                                  const BinaryInput<double> &,665                                                  float, double, RoundingMode);666#ifdef LIBC_TYPES_HAS_FLOAT16667template bool compare_binary_operation_one_output(Operation,668                                                  const BinaryInput<float16> &,669                                                  float16, double,670                                                  RoundingMode);671template bool compare_binary_operation_one_output(Operation,672                                                  const BinaryInput<float> &,673                                                  float16, double,674                                                  RoundingMode);675template bool compare_binary_operation_one_output(Operation,676                                                  const BinaryInput<double> &,677                                                  float16, double,678                                                  RoundingMode);679template bool680compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,681                                    float16, double, RoundingMode);682#endif683#if defined(LIBC_TYPES_HAS_FLOAT128) &&                                        \684    defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)685template bool compare_binary_operation_one_output(Operation,686                                                  const BinaryInput<float128> &,687                                                  float128, double,688                                                  RoundingMode);689#endif690template bool compare_binary_operation_one_output(Operation,691                                                  const BinaryInput<bfloat16> &,692                                                  bfloat16, double,693                                                  RoundingMode);694 695template bool compare_binary_operation_one_output(Operation,696                                                  const BinaryInput<float> &,697                                                  bfloat16, double,698                                                  RoundingMode);699template bool compare_binary_operation_one_output(Operation,700                                                  const BinaryInput<double> &,701                                                  bfloat16, double,702                                                  RoundingMode);703template bool704compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,705                                    bfloat16, double, RoundingMode);706#if defined(LIBC_TYPES_HAS_FLOAT128) &&                                        \707    defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)708template bool compare_binary_operation_one_output(Operation,709                                                  const BinaryInput<float128> &,710                                                  bfloat16, double,711                                                  RoundingMode);712#endif // defined(LIBC_TYPES_HAS_FLOAT128) &&713       // defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)714template <typename InputType, typename OutputType>715bool compare_ternary_operation_one_output(Operation op,716                                          const TernaryInput<InputType> &input,717                                          OutputType libc_result,718                                          double ulp_tolerance,719                                          RoundingMode rounding) {720  unsigned int precision = get_precision<InputType>(ulp_tolerance);721  MPFRNumber mpfr_result = ternary_operation_one_output(722      op, input.x, input.y, input.z, precision, rounding);723  double ulp = mpfr_result.ulp(libc_result);724 725  return (ulp <= ulp_tolerance);726}727 728template bool compare_ternary_operation_one_output(Operation,729                                                   const TernaryInput<float> &,730                                                   float, double, RoundingMode);731template bool compare_ternary_operation_one_output(Operation,732                                                   const TernaryInput<double> &,733                                                   float, double, RoundingMode);734template bool compare_ternary_operation_one_output(Operation,735                                                   const TernaryInput<double> &,736                                                   double, double,737                                                   RoundingMode);738template bool compare_ternary_operation_one_output(739    Operation, const TernaryInput<long double> &, float, double, RoundingMode);740template bool compare_ternary_operation_one_output(741    Operation, const TernaryInput<long double> &, double, double, RoundingMode);742template bool743compare_ternary_operation_one_output(Operation,744                                     const TernaryInput<long double> &,745                                     long double, double, RoundingMode);746 747#ifdef LIBC_TYPES_HAS_FLOAT16748template bool749compare_ternary_operation_one_output(Operation, const TernaryInput<float16> &,750                                     float16, double, RoundingMode);751template bool compare_ternary_operation_one_output(Operation,752                                                   const TernaryInput<float> &,753                                                   float16, double,754                                                   RoundingMode);755template bool compare_ternary_operation_one_output(Operation,756                                                   const TernaryInput<double> &,757                                                   float16, double,758                                                   RoundingMode);759template bool760compare_ternary_operation_one_output(Operation,761                                     const TernaryInput<long double> &, float16,762                                     double, RoundingMode);763#endif764 765template bool compare_ternary_operation_one_output(Operation,766                                                   const TernaryInput<float> &,767                                                   bfloat16, double,768                                                   RoundingMode);769template bool compare_ternary_operation_one_output(Operation,770                                                   const TernaryInput<double> &,771                                                   bfloat16, double,772                                                   RoundingMode);773template bool774compare_ternary_operation_one_output(Operation,775                                     const TernaryInput<long double> &,776                                     bfloat16, double, RoundingMode);777 778#if defined(LIBC_TYPES_HAS_FLOAT128) &&                                        \779    defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)780template bool781compare_ternary_operation_one_output(Operation, const TernaryInput<float128> &,782                                     bfloat16, double, RoundingMode);783#endif // defined(LIBC_TYPES_HAS_FLOAT128) &&784       // defined(LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE)785 786} // namespace internal787 788template <typename T> bool round_to_long(T x, long &result) {789  MPFRNumber mpfr(x);790  return mpfr.round_to_long(result);791}792 793template bool round_to_long<float>(float, long &);794template bool round_to_long<double>(double, long &);795template bool round_to_long<long double>(long double, long &);796 797#ifdef LIBC_TYPES_HAS_FLOAT16798template bool round_to_long<float16>(float16, long &);799#endif // LIBC_TYPES_HAS_FLOAT16800 801#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE802template bool round_to_long<float128>(float128, long &);803#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE804 805template bool round_to_long<bfloat16>(bfloat16, long &);806 807template <typename T> bool round_to_long(T x, RoundingMode mode, long &result) {808  MPFRNumber mpfr(x);809  return mpfr.round_to_long(get_mpfr_rounding_mode(mode), result);810}811 812template bool round_to_long<float>(float, RoundingMode, long &);813template bool round_to_long<double>(double, RoundingMode, long &);814template bool round_to_long<long double>(long double, RoundingMode, long &);815 816#ifdef LIBC_TYPES_HAS_FLOAT16817template bool round_to_long<float16>(float16, RoundingMode, long &);818#endif // LIBC_TYPES_HAS_FLOAT16819 820#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE821template bool round_to_long<float128>(float128, RoundingMode, long &);822#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE823 824template bool round_to_long<bfloat16>(bfloat16, RoundingMode, long &);825 826template <typename T> T round(T x, RoundingMode mode) {827  MPFRNumber mpfr(x);828  MPFRNumber result = mpfr.rint(get_mpfr_rounding_mode(mode));829  return result.as<T>();830}831 832template float round<float>(float, RoundingMode);833template double round<double>(double, RoundingMode);834template long double round<long double>(long double, RoundingMode);835 836#ifdef LIBC_TYPES_HAS_FLOAT16837template float16 round<float16>(float16, RoundingMode);838#endif // LIBC_TYPES_HAS_FLOAT16839 840#ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE841template float128 round<float128>(float128, RoundingMode);842#endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE843 844template bfloat16 round<bfloat16>(bfloat16, RoundingMode);845 846} // namespace mpfr847} // namespace testing848} // namespace LIBC_NAMESPACE_DECL849