[libc-commits] [libc] 00bd8e9 - [libc] Add a str() method to FPBits which returns a string representation.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Thu May 18 23:20:49 PDT 2023


Author: Siva Chandra Reddy
Date: 2023-05-19T06:20:41Z
New Revision: 00bd8e90116d99499f9161914fa5e00eed14a5ff

URL: https://github.com/llvm/llvm-project/commit/00bd8e90116d99499f9161914fa5e00eed14a5ff
DIFF: https://github.com/llvm/llvm-project/commit/00bd8e90116d99499f9161914fa5e00eed14a5ff.diff

LOG: [libc] Add a str() method to FPBits which returns a string representation.

Unit tests for the str() method have also been added.

Previously, a separate test only helper function was being used by the
test matchers which has regressed over many cleanups. Moreover, being a
test only utility, it was not tested separately (and hence the
regression).

Reviewed By: michaelrj

Differential Revision: https://reviews.llvm.org/D150906

Added: 
    libc/test/src/__support/FPUtil/fpbits_test.cpp

Modified: 
    libc/src/__support/FPUtil/CMakeLists.txt
    libc/src/__support/FPUtil/FPBits.h
    libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
    libc/test/UnitTest/FPMatcher.h
    libc/test/src/__support/FPUtil/CMakeLists.txt
    libc/utils/MPFRWrapper/MPFRUtils.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index b737aad1093d0..4452655d5708a 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -36,7 +36,9 @@ add_header_library(
     .platform_defs
     .float_properties
     libc.src.__support.builtin_wrappers
+    libc.src.__support.integer_to_string
     libc.src.__support.CPP.bit
+    libc.src.__support.CPP.string
     libc.src.__support.CPP.type_traits
     libc.src.__support.common
 )

diff  --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 49285527305ab..ddeb7c0f97ed2 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -12,9 +12,11 @@
 #include "PlatformDefs.h"
 
 #include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/string.h"
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/builtin_wrappers.h"
 #include "src/__support/common.h"
+#include "src/__support/integer_to_string.h"
 
 #include "FloatProperties.h"
 #include <stdint.h>
@@ -213,6 +215,47 @@ template <typename T> struct FPBits {
     result.set_mantissa(mantissa);
     return result;
   }
+
+  // Converts the bits to a string in the following format:
+  //    "0x<NNN...N> = S: N, E: 0xNNNN, M:0xNNN...N"
+  // 1. N is a hexadecimal digit.
+  // 2. The hexadecimal number on the LHS is the raw numerical representation
+  //    of the bits.
+  // 3. The exponent is always 16 bits wide irrespective of the type of the
+  //    floating encoding.
+  LIBC_INLINE cpp::string str() const {
+    if (is_nan())
+      return "(NaN)";
+    if (is_inf())
+      return get_sign() ? "(-Infinity)" : "(+Infinity)";
+
+    auto zerofill = [](char *arr, size_t n) {
+      for (size_t i = 0; i < n; ++i)
+        arr[i] = '0';
+    };
+
+    cpp::string s("0x");
+    char bitsbuf[IntegerToString::hex_bufsize<UIntType>()];
+    zerofill(bitsbuf, sizeof(bitsbuf));
+    IntegerToString::hex(bits, bitsbuf, false);
+    s += cpp::string(bitsbuf, sizeof(bitsbuf));
+
+    s += " = (";
+    s += cpp::string("S: ") + (get_sign() ? "1" : "0");
+
+    char expbuf[IntegerToString::hex_bufsize<uint16_t>()];
+    zerofill(expbuf, sizeof(expbuf));
+    IntegerToString::hex(get_unbiased_exponent(), expbuf, false);
+    s += cpp::string(", E: 0x") + cpp::string(expbuf, sizeof(expbuf));
+
+    char mantbuf[IntegerToString::hex_bufsize<UIntType>()] = {'0'};
+    zerofill(mantbuf, sizeof(mantbuf));
+    IntegerToString::hex(get_mantissa(), mantbuf, false);
+    s += cpp::string(", M: 0x") + cpp::string(mantbuf, sizeof(mantbuf));
+
+    s += ")";
+    return s;
+  }
 };
 
 } // namespace fputil

diff  --git a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
index ba2fddb2a6fed..1ef588fba54ac 100644
--- a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
+++ b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
@@ -10,8 +10,10 @@
 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_LONG_DOUBLE_BITS_H
 
 #include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/string.h"
 #include "src/__support/UInt128.h"
 #include "src/__support/common.h"
+#include "src/__support/integer_to_string.h"
 #include "src/__support/macros/properties/architectures.h"
 
 #if !defined(LIBC_TARGET_ARCH_IS_X86)
@@ -207,6 +209,50 @@ template <> struct FPBits<long double> {
     result.set_mantissa(mantissa);
     return result;
   }
+
+  // Converts the bits to a string in the following format:
+  //    "0x<NNN...N> = S: N, E: 0xNNNN, I: N, M:0xNNN...N"
+  // 1. N is a hexadecimal digit.
+  // 2. "I" denotes the implicit bit.
+  // 3. The hexadecimal number on the LHS is the raw numerical representation
+  //    of the bits.
+  // 4. The exponent is always 16 bits wide irrespective of the type of the
+  //    floating encoding.
+  LIBC_INLINE cpp::string str() const {
+    if (is_nan())
+      return "(NaN)";
+    if (is_inf())
+      return get_sign() ? "(-Infinity)" : "(+Infinity)";
+
+    auto zerofill = [](char *arr, size_t n) {
+      for (size_t i = 0; i < n; ++i)
+        arr[i] = '0';
+    };
+
+    cpp::string s("0x");
+    char bitsbuf[IntegerToString::hex_bufsize<UIntType>()] = {'0'};
+    zerofill(bitsbuf, sizeof(bitsbuf));
+    IntegerToString::hex(bits, bitsbuf, false);
+    s += cpp::string(bitsbuf, sizeof(bitsbuf));
+
+    s += " = (";
+    s += cpp::string("S: ") + (get_sign() ? "1" : "0");
+
+    char expbuf[IntegerToString::hex_bufsize<uint16_t>()] = {'0'};
+    zerofill(expbuf, sizeof(expbuf));
+    IntegerToString::hex(get_unbiased_exponent(), expbuf, false);
+    s += cpp::string(", E: 0x") + cpp::string(expbuf, sizeof(expbuf));
+
+    s += cpp::string(", I: ") + (get_implicit_bit() ? "1" : "0");
+
+    char mantbuf[IntegerToString::hex_bufsize<UIntType>()] = {'0'};
+    zerofill(mantbuf, sizeof(mantbuf));
+    IntegerToString::hex(get_mantissa(), mantbuf, false);
+    s += cpp::string(", M: 0x") + cpp::string(mantbuf, sizeof(mantbuf));
+
+    s += ")";
+    return s;
+  }
 };
 
 static_assert(

diff  --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h
index d9234c3dc328f..d3e83384ba1ce 100644
--- a/libc/test/UnitTest/FPMatcher.h
+++ b/libc/test/UnitTest/FPMatcher.h
@@ -21,43 +21,6 @@ namespace __llvm_libc {
 namespace fputil {
 namespace testing {
 
-template <typename ValType>
-cpp::enable_if_t<cpp::is_floating_point_v<ValType>, void>
-describeValue(const char *label, ValType value) {
-  __llvm_libc::testing::tlog << label;
-
-  FPBits<ValType> bits(value);
-  if (bits.is_nan()) {
-    __llvm_libc::testing::tlog << "(NaN)";
-  } else if (bits.is_inf()) {
-    if (bits.get_sign())
-      __llvm_libc::testing::tlog << "(-Infinity)";
-    else
-      __llvm_libc::testing::tlog << "(+Infinity)";
-  } else {
-    constexpr int exponentWidthInHex =
-        (fputil::ExponentWidth<ValType>::VALUE - 1) / 4 + 1;
-    constexpr int mantissaWidthInHex =
-        (fputil::MantissaWidth<ValType>::VALUE - 1) / 4 + 1;
-    constexpr int bitsWidthInHex =
-        sizeof(typename fputil::FPBits<ValType>::UIntType) * 2;
-
-    __llvm_libc::testing::tlog
-        << "0x"
-        << int_to_hex<typename fputil::FPBits<ValType>::UIntType>(
-               bits.uintval(), bitsWidthInHex)
-        << ", (S | E | M) = (" << (bits.get_sign() ? '1' : '0') << " | 0x"
-        << int_to_hex<uint16_t>(bits.get_unbiased_exponent(),
-                                exponentWidthInHex)
-        << " | 0x"
-        << int_to_hex<typename fputil::FPBits<ValType>::UIntType>(
-               bits.get_mantissa(), mantissaWidthInHex)
-        << ")";
-  }
-
-  __llvm_libc::testing::tlog << '\n';
-}
-
 template <typename T, __llvm_libc::testing::TestCondition Condition>
 class FPMatcher : public __llvm_libc::testing::Matcher<T> {
   static_assert(__llvm_libc::cpp::is_floating_point_v<T>,
@@ -87,8 +50,11 @@ class FPMatcher : public __llvm_libc::testing::Matcher<T> {
   }
 
   void explainError() override {
-    describeValue("Expected floating point value: ", expected);
-    describeValue("  Actual floating point value: ", actual);
+    __llvm_libc::testing::tlog
+        << "Expected floating point value: " << FPBits<T>(expected).str()
+        << '\n';
+    __llvm_libc::testing::tlog
+        << "Actual floating point value: " << FPBits<T>(actual).str() << '\n';
   }
 };
 

diff  --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 2e4f7f897773f..f421e7c584bfc 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -10,3 +10,13 @@ add_fp_unittest(
   DEPENDS
     libc.src.__support.FPUtil.dyadic_float
 )
+
+add_libc_test(
+  fpbits_test
+  SUITE
+    libc-fputil-tests
+  SRCS
+    fpbits_test.cpp
+  DEPENDS
+    libc.src.__support.FPUtil.fp_bits
+)

diff  --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
new file mode 100644
index 0000000000000..ba8aef77b8340
--- /dev/null
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -0,0 +1,266 @@
+//===-- Unittests for the DyadicFloat class -------------------------------===//
+//
+// 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 "src/__support/FPUtil/FPBits.h"
+#include "test/UnitTest/Test.h"
+
+using __llvm_libc::fputil::FPBits;
+
+TEST(LlvmLibcFPBitsTest, FloatType) {
+  EXPECT_STREQ(FPBits<float>::inf().str().c_str(), "(+Infinity)");
+  EXPECT_STREQ(FPBits<float>::neg_inf().str().c_str(), "(-Infinity)");
+  EXPECT_STREQ(FPBits<float>(FPBits<float>::build_nan(1)).str().c_str(),
+               "(NaN)");
+
+  FPBits<float> zero(0.0f);
+  EXPECT_EQ(zero.get_sign(), false);
+  EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0));
+  EXPECT_EQ(zero.get_mantissa(), static_cast<uint32_t>(0));
+  EXPECT_EQ(zero.uintval(), static_cast<uint32_t>(0x00000000));
+  EXPECT_STREQ(zero.str().c_str(),
+               "0x00000000 = (S: 0, E: 0x0000, M: 0x00000000)");
+
+  FPBits<float> negzero(-0.0f);
+  EXPECT_EQ(negzero.get_sign(), true);
+  EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0));
+  EXPECT_EQ(negzero.get_mantissa(), static_cast<uint32_t>(0));
+  EXPECT_EQ(negzero.uintval(), static_cast<uint32_t>(0x80000000));
+  EXPECT_STREQ(negzero.str().c_str(),
+               "0x80000000 = (S: 1, E: 0x0000, M: 0x00000000)");
+
+  FPBits<float> one(1.0f);
+  EXPECT_EQ(one.get_sign(), false);
+  EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
+  EXPECT_EQ(one.get_mantissa(), static_cast<uint32_t>(0));
+  EXPECT_EQ(one.uintval(), static_cast<uint32_t>(0x3F800000));
+  EXPECT_STREQ(one.str().c_str(),
+               "0x3F800000 = (S: 0, E: 0x007F, M: 0x00000000)");
+
+  FPBits<float> negone(-1.0f);
+  EXPECT_EQ(negone.get_sign(), true);
+  EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
+  EXPECT_EQ(negone.get_mantissa(), static_cast<uint32_t>(0));
+  EXPECT_EQ(negone.uintval(), static_cast<uint32_t>(0xBF800000));
+  EXPECT_STREQ(negone.str().c_str(),
+               "0xBF800000 = (S: 1, E: 0x007F, M: 0x00000000)");
+
+  FPBits<float> num(1.125f);
+  EXPECT_EQ(num.get_sign(), false);
+  EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
+  EXPECT_EQ(num.get_mantissa(), static_cast<uint32_t>(0x00100000));
+  EXPECT_EQ(num.uintval(), static_cast<uint32_t>(0x3F900000));
+  EXPECT_STREQ(num.str().c_str(),
+               "0x3F900000 = (S: 0, E: 0x007F, M: 0x00100000)");
+
+  FPBits<float> negnum(-1.125f);
+  EXPECT_EQ(negnum.get_sign(), true);
+  EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x7F));
+  EXPECT_EQ(negnum.get_mantissa(), static_cast<uint32_t>(0x00100000));
+  EXPECT_EQ(negnum.uintval(), static_cast<uint32_t>(0xBF900000));
+  EXPECT_STREQ(negnum.str().c_str(),
+               "0xBF900000 = (S: 1, E: 0x007F, M: 0x00100000)");
+}
+
+TEST(LlvmLibcFPBitsTest, DoubleType) {
+  EXPECT_STREQ(FPBits<double>::inf().str().c_str(), "(+Infinity)");
+  EXPECT_STREQ(FPBits<double>::neg_inf().str().c_str(), "(-Infinity)");
+  EXPECT_STREQ(FPBits<double>(FPBits<double>::build_nan(1)).str().c_str(),
+               "(NaN)");
+
+  FPBits<double> zero(0.0);
+  EXPECT_EQ(zero.get_sign(), false);
+  EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(zero.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
+  EXPECT_EQ(zero.uintval(), static_cast<uint64_t>(0x0000000000000000));
+  EXPECT_STREQ(zero.str().c_str(),
+               "0x0000000000000000 = (S: 0, E: 0x0000, M: 0x0000000000000000)");
+
+  FPBits<double> negzero(-0.0);
+  EXPECT_EQ(negzero.get_sign(), true);
+  EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(negzero.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
+  EXPECT_EQ(negzero.uintval(), static_cast<uint64_t>(0x8000000000000000));
+  EXPECT_STREQ(negzero.str().c_str(),
+               "0x8000000000000000 = (S: 1, E: 0x0000, M: 0x0000000000000000)");
+
+  FPBits<double> one(1.0);
+  EXPECT_EQ(one.get_sign(), false);
+  EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
+  EXPECT_EQ(one.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
+  EXPECT_EQ(one.uintval(), static_cast<uint64_t>(0x3FF0000000000000));
+  EXPECT_STREQ(one.str().c_str(),
+               "0x3FF0000000000000 = (S: 0, E: 0x03FF, M: 0x0000000000000000)");
+
+  FPBits<double> negone(-1.0);
+  EXPECT_EQ(negone.get_sign(), true);
+  EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
+  EXPECT_EQ(negone.get_mantissa(), static_cast<uint64_t>(0x0000000000000000));
+  EXPECT_EQ(negone.uintval(), static_cast<uint64_t>(0xBFF0000000000000));
+  EXPECT_STREQ(negone.str().c_str(),
+               "0xBFF0000000000000 = (S: 1, E: 0x03FF, M: 0x0000000000000000)");
+
+  FPBits<double> num(1.125);
+  EXPECT_EQ(num.get_sign(), false);
+  EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
+  EXPECT_EQ(num.get_mantissa(), static_cast<uint64_t>(0x0002000000000000));
+  EXPECT_EQ(num.uintval(), static_cast<uint64_t>(0x3FF2000000000000));
+  EXPECT_STREQ(num.str().c_str(),
+               "0x3FF2000000000000 = (S: 0, E: 0x03FF, M: 0x0002000000000000)");
+
+  FPBits<double> negnum(-1.125);
+  EXPECT_EQ(negnum.get_sign(), true);
+  EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x03FF));
+  EXPECT_EQ(negnum.get_mantissa(), static_cast<uint64_t>(0x0002000000000000));
+  EXPECT_EQ(negnum.uintval(), static_cast<uint64_t>(0xBFF2000000000000));
+  EXPECT_STREQ(negnum.str().c_str(),
+               "0xBFF2000000000000 = (S: 1, E: 0x03FF, M: 0x0002000000000000)");
+}
+
+#ifdef LIBC_TARGET_ARCH_IS_X86
+TEST(LlvmLibcFPBitsTest, X86LongDoubleType) {
+  if constexpr (sizeof(long double) == sizeof(double))
+    return; // The tests for the "double" type cover for this case.
+
+  EXPECT_STREQ(FPBits<long double>::inf().str().c_str(), "(+Infinity)");
+  EXPECT_STREQ(FPBits<long double>::neg_inf().str().c_str(), "(-Infinity)");
+  EXPECT_STREQ(
+      FPBits<long double>(FPBits<long double>::build_nan(1)).str().c_str(),
+      "(NaN)");
+
+  FPBits<long double> zero(0.0l);
+  EXPECT_EQ(zero.get_sign(), false);
+  EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(zero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                     << 64);
+  EXPECT_EQ(zero.uintval(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_STREQ(
+      zero.str().c_str(),
+      "0x00000000000000000000000000000000 = "
+      "(S: 0, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> negzero(-0.0l);
+  EXPECT_EQ(negzero.get_sign(), true);
+  EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(negzero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                        << 64);
+  EXPECT_EQ(negzero.uintval(), static_cast<UInt128>(0x1) << 79);
+  EXPECT_STREQ(
+      negzero.str().c_str(),
+      "0x00000000000080000000000000000000 = "
+      "(S: 1, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> one(1.0l);
+  EXPECT_EQ(one.get_sign(), false);
+  EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(one.get_mantissa(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_EQ(one.uintval(), static_cast<UInt128>(0x3FFF8) << 60);
+  EXPECT_STREQ(
+      one.str().c_str(),
+      "0x0000000000003FFF8000000000000000 = "
+      "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> negone(-1.0l);
+  EXPECT_EQ(negone.get_sign(), true);
+  EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negone.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                       << 64);
+  EXPECT_EQ(negone.uintval(), static_cast<UInt128>(0xBFFF8) << 60);
+  EXPECT_STREQ(
+      negone.str().c_str(),
+      "0x000000000000BFFF8000000000000000 = "
+      "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> num(1.125l);
+  EXPECT_EQ(num.get_sign(), false);
+  EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(num.get_mantissa(), static_cast<UInt128>(0x1) << 60);
+  EXPECT_EQ(num.uintval(), static_cast<UInt128>(0x3FFF9) << 60);
+  EXPECT_STREQ(
+      num.str().c_str(),
+      "0x0000000000003FFF9000000000000000 = "
+      "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)");
+
+  FPBits<long double> negnum(-1.125l);
+  EXPECT_EQ(negnum.get_sign(), true);
+  EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negnum.get_mantissa(), static_cast<UInt128>(0x1) << 60);
+  EXPECT_EQ(negnum.uintval(), static_cast<UInt128>(0xBFFF9) << 60);
+  EXPECT_STREQ(
+      negnum.str().c_str(),
+      "0x000000000000BFFF9000000000000000 = "
+      "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)");
+}
+#else
+TEST(LlvmLibcFPBitsTest, LongDoubleType) {
+  if constexpr (sizeof(long double) == sizeof(double))
+    return; // The tests for the "double" type cover for this case.
+
+  EXPECT_STREQ(FPBits<long double>::inf().str().c_str(), "(+Infinity)");
+  EXPECT_STREQ(FPBits<long double>::neg_inf().str().c_str(), "(-Infinity)");
+  EXPECT_STREQ(
+      FPBits<long double>(FPBits<long double>::build_nan(1)).str().c_str(),
+      "(NaN)");
+
+  FPBits<long double> zero(0.0l);
+  EXPECT_EQ(zero.get_sign(), false);
+  EXPECT_EQ(zero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(zero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                     << 64);
+  EXPECT_EQ(zero.uintval(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_STREQ(zero.str().c_str(),
+               "0x00000000000000000000000000000000 = "
+               "(S: 0, E: 0x0000, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> negzero(-0.0l);
+  EXPECT_EQ(negzero.get_sign(), true);
+  EXPECT_EQ(negzero.get_unbiased_exponent(), static_cast<uint16_t>(0x0000));
+  EXPECT_EQ(negzero.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                        << 64);
+  EXPECT_EQ(negzero.uintval(), static_cast<UInt128>(0x1) << 127);
+  EXPECT_STREQ(negzero.str().c_str(),
+               "0x80000000000000000000000000000000 = "
+               "(S: 1, E: 0x0000, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> one(1.0l);
+  EXPECT_EQ(one.get_sign(), false);
+  EXPECT_EQ(one.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(one.get_mantissa(), static_cast<UInt128>(0x0000000000000000) << 64);
+  EXPECT_EQ(one.uintval(), static_cast<UInt128>(0x3FFF) << 112);
+  EXPECT_STREQ(one.str().c_str(),
+               "0x3FFF0000000000000000000000000000 = "
+               "(S: 0, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> negone(-1.0l);
+  EXPECT_EQ(negone.get_sign(), true);
+  EXPECT_EQ(negone.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negone.get_mantissa(), static_cast<UInt128>(0x0000000000000000)
+                                       << 64);
+  EXPECT_EQ(negone.uintval(), static_cast<UInt128>(0xBFFF) << 112);
+  EXPECT_STREQ(negone.str().c_str(),
+               "0xBFFF0000000000000000000000000000 = "
+               "(S: 1, E: 0x3FFF, M: 0x00000000000000000000000000000000)");
+
+  FPBits<long double> num(1.125l);
+  EXPECT_EQ(num.get_sign(), false);
+  EXPECT_EQ(num.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(num.get_mantissa(), static_cast<UInt128>(0x2) << 108);
+  EXPECT_EQ(num.uintval(), static_cast<UInt128>(0x3FFF2) << 108);
+  EXPECT_STREQ(num.str().c_str(),
+               "0x3FFF2000000000000000000000000000 = "
+               "(S: 0, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
+
+  FPBits<long double> negnum(-1.125l);
+  EXPECT_EQ(negnum.get_sign(), true);
+  EXPECT_EQ(negnum.get_unbiased_exponent(), static_cast<uint16_t>(0x3FFF));
+  EXPECT_EQ(negnum.get_mantissa(), static_cast<UInt128>(0x2) << 108);
+  EXPECT_EQ(negnum.uintval(), static_cast<UInt128>(0xBFFF2) << 108);
+  EXPECT_STREQ(negnum.str().c_str(),
+               "0xBFFF2000000000000000000000000000 = "
+               "(S: 1, E: 0x3FFF, M: 0x00002000000000000000000000000000)");
+}
+#endif

diff  --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index e2a273b6aa98e..f19899c3098fd 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -703,12 +703,11 @@ void explain_unary_operation_single_output_error(Operation op, T input,
   MPFRNumber mpfrMatchValue(matchValue);
   tlog << "Match value not within tolerance value of MPFR result:\n"
        << "  Input decimal: " << mpfrInput.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue("     Input bits: ", input);
+  tlog << "     Input bits: " << FPBits<T>(input).str() << '\n';
   tlog << '\n' << "  Match decimal: " << mpfrMatchValue.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue("     Match bits: ", matchValue);
+  tlog << "     Match bits: " << FPBits<T>(matchValue).str() << '\n';
   tlog << '\n' << "    MPFR result: " << mpfr_result.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue("   MPFR rounded: ",
-                                              mpfr_result.as<T>());
+  tlog << "   MPFR rounded: " << FPBits<T>(mpfr_result.as<T>()).str() << '\n';
   tlog << '\n';
   tlog << "      ULP error: "
        << mpfr_result.ulp_as_mpfr_number(matchValue).str() << '\n';
@@ -748,13 +747,13 @@ void explain_unary_operation_two_outputs_error(
   tlog << "            Input decimal: " << mpfrInput.str() << "\n\n";
 
   tlog << "Libc floating point value: " << mpfrMatchValue.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue(" Libc floating point bits: ",
-                                              libc_result.f);
+  tlog << " Libc floating point bits: " << FPBits<T>(libc_result.f).str()
+       << '\n';
   tlog << "\n\n";
 
   tlog << "              MPFR result: " << mpfr_result.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue("             MPFR rounded: ",
-                                              mpfr_result.as<T>());
+  tlog << "             MPFR rounded: " << FPBits<T>(mpfr_result.as<T>()).str()
+       << '\n';
   tlog << '\n'
        << "                ULP error: "
        << mpfr_result.ulp_as_mpfr_number(libc_result.f).str() << '\n';
@@ -786,10 +785,10 @@ void explain_binary_operation_two_outputs_error(
        << "Libc integral result: " << libc_result.i << '\n'
        << "Libc floating point result: " << mpfrMatchValue.str() << '\n'
        << "               MPFR result: " << mpfr_result.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue(
-      "Libc floating point result bits: ", libc_result.f);
-  __llvm_libc::fputil::testing::describeValue(
-      "              MPFR rounded bits: ", mpfr_result.as<T>());
+  tlog << "Libc floating point result bits: " << FPBits<T>(libc_result.f).str()
+       << '\n';
+  tlog << "              MPFR rounded bits: "
+       << FPBits<T>(mpfr_result.as<T>()).str() << '\n';
   tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result.f).str()
        << '\n';
 }
@@ -820,15 +819,15 @@ void explain_binary_operation_one_output_error(Operation op,
   MPFRNumber mpfrMatchValue(libc_result);
 
   tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue("First input bits: ", input.x);
-  __llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y);
+  tlog << "First input bits: " << FPBits<T>(input.x).str() << '\n';
+  tlog << "Second input bits: " << FPBits<T>(input.y).str() << '\n';
 
   tlog << "Libc result: " << mpfrMatchValue.str() << '\n'
        << "MPFR result: " << mpfr_result.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue(
-      "Libc floating point result bits: ", libc_result);
-  __llvm_libc::fputil::testing::describeValue(
-      "              MPFR rounded bits: ", mpfr_result.as<T>());
+  tlog << "Libc floating point result bits: " << FPBits<T>(libc_result).str()
+       << '\n';
+  tlog << "              MPFR rounded bits: "
+       << FPBits<T>(mpfr_result.as<T>()).str() << '\n';
   tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str()
        << '\n';
 }
@@ -860,16 +859,16 @@ void explain_ternary_operation_one_output_error(Operation op,
 
   tlog << "Input decimal: x: " << mpfrX.str() << " y: " << mpfrY.str()
        << " z: " << mpfrZ.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue("First input bits: ", input.x);
-  __llvm_libc::fputil::testing::describeValue("Second input bits: ", input.y);
-  __llvm_libc::fputil::testing::describeValue("Third input bits: ", input.z);
+  tlog << " First input bits: " << FPBits<T>(input.x).str() << '\n';
+  tlog << "Second input bits: " << FPBits<T>(input.y).str() << '\n';
+  tlog << " Third input bits: " << FPBits<T>(input.z).str() << '\n';
 
   tlog << "Libc result: " << mpfrMatchValue.str() << '\n'
        << "MPFR result: " << mpfr_result.str() << '\n';
-  __llvm_libc::fputil::testing::describeValue(
-      "Libc floating point result bits: ", libc_result);
-  __llvm_libc::fputil::testing::describeValue(
-      "              MPFR rounded bits: ", mpfr_result.as<T>());
+  tlog << "Libc floating point result bits: " << FPBits<T>(libc_result).str()
+       << '\n';
+  tlog << "              MPFR rounded bits: "
+       << FPBits<T>(mpfr_result.as<T>()).str() << '\n';
   tlog << "ULP error: " << mpfr_result.ulp_as_mpfr_number(libc_result).str()
        << '\n';
 }


        


More information about the libc-commits mailing list