[libc-commits] [libc] [libc][test] make `str_to_float_comparison_test` independent of C++ headers. (PR #133978)

via libc-commits libc-commits at lists.llvm.org
Sat Apr 5 08:28:39 PDT 2025


================
@@ -54,80 +56,112 @@ static inline uint64_t fastHexToU64(const char *inStr) {
   return result;
 }
 
-int checkFile(char *inputFileName, int *totalFails, int *totalBitDiffs,
-              int *detailedBitDiffs, int *total) {
-  int32_t curFails = 0;    // Only counts actual failures, not bitdiffs.
-  int32_t curBitDiffs = 0; // A bitdiff is when the expected result and actual
-                           // result are off by +/- 1 bit.
-  std::string line;
-  std::string num;
+static void parseLine(char *line, int *total, int *detailedBitDiffs,
+                      int32_t &curFails, int32_t &curBitDiffs) {
 
-  std::ifstream fileStream(inputFileName, std::ifstream::in);
-
-  if (!fileStream.is_open()) {
-    std::cout << "file '" << inputFileName << "' failed to open. Exiting.\n";
-    return 1;
+  if (line[0] == '#') {
+    return;
   }
-  while (getline(fileStream, line)) {
-    if (line[0] == '#') {
-      continue;
-    }
-    *total = *total + 1;
-    uint32_t expectedFloatRaw;
-    uint64_t expectedDoubleRaw;
+  *total = *total + 1;
+  uint32_t expectedFloatRaw;
+  uint64_t expectedDoubleRaw;
 
-    expectedFloatRaw = fastHexToU32(line.c_str() + 5);
-    expectedDoubleRaw = fastHexToU64(line.c_str() + 14);
-    num = line.substr(31);
+  expectedFloatRaw = fastHexToU32(line + 5);
+  expectedDoubleRaw = fastHexToU64(line + 14);
 
-    float floatResult = strtof(num.c_str(), nullptr);
+  char *num = line + 31;
 
-    double doubleResult = strtod(num.c_str(), nullptr);
+  float floatResult = LIBC_NAMESPACE::strtof(num, nullptr);
 
-    uint32_t floatRaw = *(uint32_t *)(&floatResult);
+  double doubleResult = LIBC_NAMESPACE::strtod(num, nullptr);
 
-    uint64_t doubleRaw = *(uint64_t *)(&doubleResult);
+  uint32_t floatRaw = LIBC_NAMESPACE::cpp::bit_cast<uint32_t>(floatResult);
 
-    if (!(expectedFloatRaw == floatRaw)) {
-      if (expectedFloatRaw == floatRaw + 1 ||
-          expectedFloatRaw == floatRaw - 1) {
-        curBitDiffs++;
-        if (expectedFloatRaw == floatRaw + 1) {
-          detailedBitDiffs[0] = detailedBitDiffs[0] + 1; // float low
-        } else {
-          detailedBitDiffs[1] = detailedBitDiffs[1] + 1; // float high
-        }
+  uint64_t doubleRaw = LIBC_NAMESPACE::cpp::bit_cast<uint64_t>(doubleResult);
+
+  if (!(expectedFloatRaw == floatRaw)) {
+    if (expectedFloatRaw == floatRaw + 1 || expectedFloatRaw == floatRaw - 1) {
+      curBitDiffs++;
+      if (expectedFloatRaw == floatRaw + 1) {
+        detailedBitDiffs[0] = detailedBitDiffs[0] + 1; // float low
       } else {
-        curFails++;
-      }
-      if (curFails + curBitDiffs < 10) {
-        std::cout << "Float fail for '" << num << "'. Expected " << std::hex
-                  << expectedFloatRaw << " but got " << floatRaw << "\n"
-                  << std::dec;
+        detailedBitDiffs[1] = detailedBitDiffs[1] + 1; // float high
       }
+    } else {
+      curFails++;
+    }
+    if (curFails + curBitDiffs < 10) {
+      LIBC_NAMESPACE::printf("Float fail for '%s'. Expected %x but got %x\n",
+                             num, expectedFloatRaw, floatRaw);
     }
+  }
 
-    if (!(expectedDoubleRaw == doubleRaw)) {
-      if (expectedDoubleRaw == doubleRaw + 1 ||
-          expectedDoubleRaw == doubleRaw - 1) {
-        curBitDiffs++;
-        if (expectedDoubleRaw == doubleRaw + 1) {
-          detailedBitDiffs[2] = detailedBitDiffs[2] + 1; // double low
-        } else {
-          detailedBitDiffs[3] = detailedBitDiffs[3] + 1; // double high
-        }
+  if (!(expectedDoubleRaw == doubleRaw)) {
+    if (expectedDoubleRaw == doubleRaw + 1 ||
+        expectedDoubleRaw == doubleRaw - 1) {
+      curBitDiffs++;
+      if (expectedDoubleRaw == doubleRaw + 1) {
+        detailedBitDiffs[2] = detailedBitDiffs[2] + 1; // double low
       } else {
-        curFails++;
-      }
-      if (curFails + curBitDiffs < 10) {
-        std::cout << "Double fail for '" << num << "'. Expected " << std::hex
-                  << expectedDoubleRaw << " but got " << doubleRaw << "\n"
-                  << std::dec;
+        detailedBitDiffs[3] = detailedBitDiffs[3] + 1; // double high
       }
+    } else {
+      curFails++;
+    }
+    if (curFails + curBitDiffs < 10) {
+      LIBC_NAMESPACE::printf("Double fail for '%s'. Expected %lx but got %lx\n",
+                             num, expectedDoubleRaw, doubleRaw);
     }
   }
+}
+
+int checkBuffer(int *totalFails, int *totalBitDiffs, int *detailedBitDiffs,
+                int *total) {
+  const char *lines[6] = {"3C00 3F800000 3FF0000000000000 1",
+                          "3D00 3FA00000 3FF4000000000000 1.25",
+                          "3D9A 3FB33333 3FF6666666666666 1.4",
+                          "57B7 42F6E979 405EDD2F1A9FBE77 123.456",
+                          "622A 44454000 4088A80000000000 789",
+                          "7C00 7F800000 7FF0000000000000 123.456e789"};
+
+  int32_t curFails = 0;    // Only counts actual failures, not bitdiffs.
+  int32_t curBitDiffs = 0; // A bitdiff is when the expected result and actual
+  // result are off by +/- 1 bit.
+
+  for (uint8_t i = 0; i < 6; i++) {
+    auto line = const_cast<char *>(lines[i]);
+    parseLine(line, total, detailedBitDiffs, curFails, curBitDiffs);
+  }
+
+  *totalBitDiffs += curBitDiffs;
+  *totalFails += curFails;
+
+  if (curFails > 1 || curBitDiffs > 1) {
+    return 2;
+  }
+  return 0;
+}
 
-  fileStream.close();
+int checkFile(char *inputFileName, int *totalFails, int *totalBitDiffs,
----------------
lntue wrote:

@mikhailramalho @RossComputerGuy  I think the purpose of this test according to @michaelrj-google is to manually run it against large files containing many interesting cases.  Before this PR, the test build was set up manually, and didn't respect the dependency or entrypoint lists that we normally have.  With this change, this test will be build using our normal testing infra as other tests, respecting the dependency (skipped if they are not available), and will not automatically run with `ninja check-libc`.  I hope that would be enough to make it non-blocking when we try to build on new targets?

https://github.com/llvm/llvm-project/pull/133978


More information about the libc-commits mailing list