//===-- Utils which wrap MPFR ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "MPFRUtils.h" #include "MPCommon.h" #include "src/__support/CPP/array.h" #include "src/__support/CPP/stringstream.h" #include "src/__support/FPUtil/fpbits_str.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/types.h" namespace LIBC_NAMESPACE_DECL { namespace testing { namespace mpfr { namespace internal { template cpp::enable_if_t, MPFRNumber> unary_operation(Operation op, InputType input, unsigned int precision, RoundingMode rounding) { MPFRNumber mpfrInput(input, precision, rounding); switch (op) { case Operation::Abs: return mpfrInput.abs(); case Operation::Acos: return mpfrInput.acos(); case Operation::Acosh: return mpfrInput.acosh(); case Operation::Asin: return mpfrInput.asin(); case Operation::Asinh: return mpfrInput.asinh(); case Operation::Atan: return mpfrInput.atan(); case Operation::Atanh: return mpfrInput.atanh(); case Operation::Cbrt: return mpfrInput.cbrt(); case Operation::Ceil: return mpfrInput.ceil(); case Operation::Cos: return mpfrInput.cos(); case Operation::Cosh: return mpfrInput.cosh(); case Operation::Cospi: return mpfrInput.cospi(); case Operation::Erf: return mpfrInput.erf(); case Operation::Exp: return mpfrInput.exp(); case Operation::Exp2: return mpfrInput.exp2(); case Operation::Exp2m1: return mpfrInput.exp2m1(); case Operation::Exp10: return mpfrInput.exp10(); case Operation::Exp10m1: return mpfrInput.exp10m1(); case Operation::Expm1: return mpfrInput.expm1(); case Operation::Floor: return mpfrInput.floor(); case Operation::Log: return mpfrInput.log(); case Operation::Log2: return mpfrInput.log2(); case Operation::Log10: return mpfrInput.log10(); case Operation::Log1p: return mpfrInput.log1p(); case Operation::Mod2PI: return mpfrInput.mod_2pi(); case Operation::ModPIOver2: return mpfrInput.mod_pi_over_2(); case Operation::ModPIOver4: return mpfrInput.mod_pi_over_4(); case Operation::Round: return mpfrInput.round(); case Operation::RoundEven: return mpfrInput.roundeven(); case Operation::Sin: return mpfrInput.sin(); case Operation::Sinpi: return mpfrInput.sinpi(); case Operation::Sinh: return mpfrInput.sinh(); case Operation::Sqrt: return mpfrInput.sqrt(); case Operation::Tan: return mpfrInput.tan(); case Operation::Tanh: return mpfrInput.tanh(); case Operation::Tanpi: return mpfrInput.tanpi(); case Operation::Trunc: return mpfrInput.trunc(); default: __builtin_unreachable(); } } template cpp::enable_if_t, MPFRNumber> unary_operation_two_outputs(Operation op, InputType input, int &output, unsigned int precision, RoundingMode rounding) { MPFRNumber mpfrInput(input, precision, rounding); switch (op) { case Operation::Frexp: return mpfrInput.frexp(output); default: __builtin_unreachable(); } } template cpp::enable_if_t, MPFRNumber> binary_operation_one_output(Operation op, InputType x, InputType y, unsigned int precision, RoundingMode rounding) { MPFRNumber inputX(x, precision, rounding); MPFRNumber inputY(y, precision, rounding); switch (op) { case Operation::Add: return inputX.add(inputY); case Operation::Atan2: return inputX.atan2(inputY); case Operation::Div: return inputX.div(inputY); case Operation::Fmod: return inputX.fmod(inputY); case Operation::Hypot: return inputX.hypot(inputY); case Operation::Mul: return inputX.mul(inputY); case Operation::Pow: return inputX.pow(inputY); case Operation::Sub: return inputX.sub(inputY); default: __builtin_unreachable(); } } template cpp::enable_if_t, MPFRNumber> binary_operation_two_outputs(Operation op, InputType x, InputType y, int &output, unsigned int precision, RoundingMode rounding) { MPFRNumber inputX(x, precision, rounding); MPFRNumber inputY(y, precision, rounding); switch (op) { case Operation::RemQuo: return inputX.remquo(inputY, output); default: __builtin_unreachable(); } } template cpp::enable_if_t, MPFRNumber> ternary_operation_one_output(Operation op, InputType x, InputType y, InputType z, unsigned int precision, RoundingMode rounding) { // For FMA function, we just need to compare with the mpfr_fma with the same // precision as InputType. Using higher precision as the intermediate results // to compare might incorrectly fail due to double-rounding errors. MPFRNumber inputX(x, precision, rounding); MPFRNumber inputY(y, precision, rounding); MPFRNumber inputZ(z, precision, rounding); switch (op) { case Operation::Fma: return inputX.fma(inputY, inputZ); default: __builtin_unreachable(); } } // Remark: For all the explain_*_error functions, we will use std::stringstream // to build the complete error messages before sending it to the outstream `OS` // once at the end. This will stop the error messages from interleaving when // the tests are running concurrently. template void explain_unary_operation_single_output_error(Operation op, InputType input, OutputType matchValue, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrInput(input, precision); MPFRNumber mpfr_result; mpfr_result = unary_operation(op, input, precision, rounding); MPFRNumber mpfrMatchValue(matchValue); cpp::array msg_buf; cpp::StringStream msg(msg_buf); msg << "Match value not within tolerance value of MPFR result:\n" << " Input decimal: " << mpfrInput.str() << '\n'; msg << " Input bits: " << str(FPBits(input)) << '\n'; msg << '\n' << " Match decimal: " << mpfrMatchValue.str() << '\n'; msg << " Match bits: " << str(FPBits(matchValue)) << '\n'; msg << '\n' << " MPFR result: " << mpfr_result.str() << '\n'; msg << " MPFR rounded: " << str(FPBits(mpfr_result.as())) << '\n'; msg << '\n'; msg << " ULP error: " << mpfr_result.ulp_as_mpfr_number(matchValue).str() << '\n'; if (msg.overflow()) __builtin_unreachable(); tlog << msg.str(); } template void explain_unary_operation_single_output_error(Operation op, float, float, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, double, double, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, long double, long double, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, double, float, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, long double, float, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, long double, double, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 template void explain_unary_operation_single_output_error(Operation op, float16, float16, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, float, float16, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, double, float16, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, long double, float16, double, RoundingMode); #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template void explain_unary_operation_single_output_error(Operation op, float128, float16, double, RoundingMode); #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE #endif // LIBC_TYPES_HAS_FLOAT16 #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template void explain_unary_operation_single_output_error(Operation op, float128, float128, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, float128, float, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, float128, double, double, RoundingMode); template void explain_unary_operation_single_output_error(Operation op, float128, long double, double, RoundingMode); #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template void explain_unary_operation_two_outputs_error( Operation op, T input, const BinaryOutput &libc_result, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrInput(input, precision); int mpfrIntResult; MPFRNumber mpfr_result = unary_operation_two_outputs(op, input, mpfrIntResult, precision, rounding); if (mpfrIntResult != libc_result.i) { tlog << "MPFR integral result: " << mpfrIntResult << '\n' << "Libc integral result: " << libc_result.i << '\n'; } else { tlog << "Integral result from libc matches integral result from MPFR.\n"; } MPFRNumber mpfrMatchValue(libc_result.f); tlog << "Libc floating point result is not within tolerance value of the MPFR " << "result.\n\n"; tlog << " Input decimal: " << mpfrInput.str() << "\n\n"; tlog << "Libc floating point value: " << mpfrMatchValue.str() << '\n'; tlog << " Libc floating point bits: " << str(FPBits(libc_result.f)) << '\n'; tlog << "\n\n"; tlog << " MPFR result: " << mpfr_result.str() << '\n'; tlog << " MPFR rounded: " << str(FPBits(mpfr_result.as())) << '\n'; tlog << '\n' << " ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result.f).str() << '\n'; } template void explain_unary_operation_two_outputs_error( Operation, float, const BinaryOutput &, double, RoundingMode); template void explain_unary_operation_two_outputs_error( Operation, double, const BinaryOutput &, double, RoundingMode); template void explain_unary_operation_two_outputs_error( Operation, long double, const BinaryOutput &, double, RoundingMode); template void explain_binary_operation_two_outputs_error( Operation op, const BinaryInput &input, const BinaryOutput &libc_result, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrX(input.x, precision); MPFRNumber mpfrY(input.y, precision); int mpfrIntResult; MPFRNumber mpfr_result = binary_operation_two_outputs( op, input.x, input.y, mpfrIntResult, precision, rounding); MPFRNumber mpfrMatchValue(libc_result.f); tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n' << "MPFR integral result: " << mpfrIntResult << '\n' << "Libc integral result: " << libc_result.i << '\n' << "Libc floating point result: " << mpfrMatchValue.str() << '\n' << " MPFR result: " << mpfr_result.str() << '\n'; tlog << "Libc floating point result bits: " << str(FPBits(libc_result.f)) << '\n'; tlog << " MPFR rounded bits: " << str(FPBits(mpfr_result.as())) << '\n'; tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result.f).str() << '\n'; } template void explain_binary_operation_two_outputs_error( Operation, const BinaryInput &, const BinaryOutput &, double, RoundingMode); template void explain_binary_operation_two_outputs_error( Operation, const BinaryInput &, const BinaryOutput &, double, RoundingMode); template void explain_binary_operation_two_outputs_error( Operation, const BinaryInput &, const BinaryOutput &, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation op, const BinaryInput &input, OutputType libc_result, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrX(input.x, precision); MPFRNumber mpfrY(input.y, precision); FPBits xbits(input.x); FPBits ybits(input.y); MPFRNumber mpfr_result = binary_operation_one_output(op, input.x, input.y, precision, rounding); MPFRNumber mpfrMatchValue(libc_result); tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n'; tlog << "First input bits: " << str(FPBits(input.x)) << '\n'; tlog << "Second input bits: " << str(FPBits(input.y)) << '\n'; tlog << "Libc result: " << mpfrMatchValue.str() << '\n' << "MPFR result: " << mpfr_result.str() << '\n'; tlog << "Libc floating point result bits: " << str(FPBits(libc_result)) << '\n'; tlog << " MPFR rounded bits: " << str(FPBits(mpfr_result.as())) << '\n'; tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str() << '\n'; } template void explain_binary_operation_one_output_error(Operation, const BinaryInput &, float, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, float, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, double, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, float, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, double, double, RoundingMode); template void explain_binary_operation_one_output_error(Operation, const BinaryInput &, long double, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, float16, double, RoundingMode); template void explain_binary_operation_one_output_error(Operation, const BinaryInput &, float16, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, float16, double, RoundingMode); template void explain_binary_operation_one_output_error( Operation, const BinaryInput &, float16, double, RoundingMode); #endif template void explain_ternary_operation_one_output_error( Operation op, const TernaryInput &input, OutputType libc_result, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfrX(input.x, precision); MPFRNumber mpfrY(input.y, precision); MPFRNumber mpfrZ(input.z, precision); FPBits xbits(input.x); FPBits ybits(input.y); FPBits zbits(input.z); MPFRNumber mpfr_result = ternary_operation_one_output( op, input.x, input.y, input.z, precision, rounding); MPFRNumber mpfrMatchValue(libc_result); tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << " z: " << mpfrZ.str() << '\n'; tlog << " First input bits: " << str(FPBits(input.x)) << '\n'; tlog << "Second input bits: " << str(FPBits(input.y)) << '\n'; tlog << " Third input bits: " << str(FPBits(input.z)) << '\n'; tlog << "Libc result: " << mpfrMatchValue.str() << '\n' << "MPFR result: " << mpfr_result.str() << '\n'; tlog << "Libc floating point result bits: " << str(FPBits(libc_result)) << '\n'; tlog << " MPFR rounded bits: " << str(FPBits(mpfr_result.as())) << '\n'; tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str() << '\n'; } template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, float, double, RoundingMode); template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, float, double, RoundingMode); template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, double, double, RoundingMode); template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, float, double, RoundingMode); template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, double, double, RoundingMode); template void explain_ternary_operation_one_output_error(Operation, const TernaryInput &, long double, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, float16, double, RoundingMode); template void explain_ternary_operation_one_output_error( Operation, const TernaryInput &, float16, double, RoundingMode); template void explain_ternary_operation_one_output_error(Operation, const TernaryInput &, float16, double, RoundingMode); #endif template bool compare_unary_operation_single_output(Operation op, InputType input, OutputType libc_result, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfr_result; mpfr_result = unary_operation(op, input, precision, rounding); double ulp = mpfr_result.ulp(libc_result); return (ulp <= ulp_tolerance); } template bool compare_unary_operation_single_output(Operation, float, float, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, double, double, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, long double, long double, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, double, float, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, long double, float, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, long double, double, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 template bool compare_unary_operation_single_output(Operation, float16, float16, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, float, float16, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, double, float16, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, long double, float16, double, RoundingMode); #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template bool compare_unary_operation_single_output(Operation, float128, float16, double, RoundingMode); #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE #endif // LIBC_TYPES_HAS_FLOAT16 #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template bool compare_unary_operation_single_output(Operation, float128, float128, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, float128, float, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, float128, double, double, RoundingMode); template bool compare_unary_operation_single_output(Operation, float128, long double, double, RoundingMode); #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template bool compare_unary_operation_two_outputs(Operation op, T input, const BinaryOutput &libc_result, double ulp_tolerance, RoundingMode rounding) { int mpfrIntResult; unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfr_result = unary_operation_two_outputs(op, input, mpfrIntResult, precision, rounding); double ulp = mpfr_result.ulp(libc_result.f); if (mpfrIntResult != libc_result.i) return false; return (ulp <= ulp_tolerance); } template bool compare_unary_operation_two_outputs( Operation, float, const BinaryOutput &, double, RoundingMode); template bool compare_unary_operation_two_outputs( Operation, double, const BinaryOutput &, double, RoundingMode); template bool compare_unary_operation_two_outputs( Operation, long double, const BinaryOutput &, double, RoundingMode); template bool compare_binary_operation_two_outputs(Operation op, const BinaryInput &input, const BinaryOutput &libc_result, double ulp_tolerance, RoundingMode rounding) { int mpfrIntResult; unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfr_result = binary_operation_two_outputs( op, input.x, input.y, mpfrIntResult, precision, rounding); double ulp = mpfr_result.ulp(libc_result.f); if (mpfrIntResult != libc_result.i) { if (op == Operation::RemQuo) { if ((0x7 & mpfrIntResult) != (0x7 & libc_result.i)) return false; } else { return false; } } return (ulp <= ulp_tolerance); } template bool compare_binary_operation_two_outputs( Operation, const BinaryInput &, const BinaryOutput &, double, RoundingMode); template bool compare_binary_operation_two_outputs( Operation, const BinaryInput &, const BinaryOutput &, double, RoundingMode); template bool compare_binary_operation_two_outputs( Operation, const BinaryInput &, const BinaryOutput &, double, RoundingMode); template bool compare_binary_operation_one_output(Operation op, const BinaryInput &input, OutputType libc_result, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfr_result = binary_operation_one_output(op, input.x, input.y, precision, rounding); double ulp = mpfr_result.ulp(libc_result); return (ulp <= ulp_tolerance); } template bool compare_binary_operation_one_output(Operation, const BinaryInput &, float, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, double, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, float, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, double, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, long double, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, float, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 template bool compare_binary_operation_one_output(Operation, const BinaryInput &, float16, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, float16, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, float16, double, RoundingMode); template bool compare_binary_operation_one_output(Operation, const BinaryInput &, float16, double, RoundingMode); #endif template bool compare_ternary_operation_one_output(Operation op, const TernaryInput &input, OutputType libc_result, double ulp_tolerance, RoundingMode rounding) { unsigned int precision = get_precision(ulp_tolerance); MPFRNumber mpfr_result = ternary_operation_one_output( op, input.x, input.y, input.z, precision, rounding); double ulp = mpfr_result.ulp(libc_result); return (ulp <= ulp_tolerance); } template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, float, double, RoundingMode); template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, float, double, RoundingMode); template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, double, double, RoundingMode); template bool compare_ternary_operation_one_output( Operation, const TernaryInput &, float, double, RoundingMode); template bool compare_ternary_operation_one_output( Operation, const TernaryInput &, double, double, RoundingMode); template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, long double, double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, float16, double, RoundingMode); template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, float16, double, RoundingMode); template bool compare_ternary_operation_one_output(Operation, const TernaryInput &, float16, double, RoundingMode); #endif } // namespace internal template bool round_to_long(T x, long &result) { MPFRNumber mpfr(x); return mpfr.round_to_long(result); } template bool round_to_long(float, long &); template bool round_to_long(double, long &); template bool round_to_long(long double, long &); #ifdef LIBC_TYPES_HAS_FLOAT16 template bool round_to_long(float16, long &); #endif // LIBC_TYPES_HAS_FLOAT16 #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template bool round_to_long(float128, long &); #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template bool round_to_long(T x, RoundingMode mode, long &result) { MPFRNumber mpfr(x); return mpfr.round_to_long(get_mpfr_rounding_mode(mode), result); } template bool round_to_long(float, RoundingMode, long &); template bool round_to_long(double, RoundingMode, long &); template bool round_to_long(long double, RoundingMode, long &); #ifdef LIBC_TYPES_HAS_FLOAT16 template bool round_to_long(float16, RoundingMode, long &); #endif // LIBC_TYPES_HAS_FLOAT16 #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template bool round_to_long(float128, RoundingMode, long &); #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template T round(T x, RoundingMode mode) { MPFRNumber mpfr(x); MPFRNumber result = mpfr.rint(get_mpfr_rounding_mode(mode)); return result.as(); } template float round(float, RoundingMode); template double round(double, RoundingMode); template long double round(long double, RoundingMode); #ifdef LIBC_TYPES_HAS_FLOAT16 template float16 round(float16, RoundingMode); #endif // LIBC_TYPES_HAS_FLOAT16 #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE template float128 round(float128, RoundingMode); #endif // LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE } // namespace mpfr } // namespace testing } // namespace LIBC_NAMESPACE_DECL