================
@@ -9860,6 +9923,342 @@ TEST(APFloatTest, ConvertDoubleToE8M0FNU) {
   EXPECT_EQ(status, APFloat::opUnderflow | APFloat::opInexact);
 }
 
+TEST(APFloatTest, Float8E5M3FNUValues) {
+  // High end of the range
+  auto test = APFloat(APFloat::Float8E5M3FNU(), "0x1.c0p16");
+  EXPECT_EQ(0x1.c0p16, test.convertToDouble());
+
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.c0p15");
+  EXPECT_EQ(0x1.cp15, test.convertToDouble());
+
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p14");
+  EXPECT_EQ(0x1.0p14, test.convertToDouble());
+
+  // tests the fix in makeLargest()
+  test = APFloat::getLargest(APFloat::Float8E5M3FNU());
+  EXPECT_EQ(0x1.cp16, test.convertToDouble());
+
+  // tests overflow to nan
+  APFloat nan = APFloat(APFloat::Float8E5M3FNU(), "nan");
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.e0p+16");
+  EXPECT_TRUE(test.bitwiseIsEqual(nan));
+
+  // Mid of the range
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p0");
+  EXPECT_EQ(1.0, test.convertToDouble());
+
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p1");
+  EXPECT_EQ(2.0, test.convertToDouble());
+
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p2");
+  EXPECT_EQ(4.0, test.convertToDouble());
+
+  // Low end of the range
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-12");
+  EXPECT_EQ(0x1.0p-12, test.convertToDouble());
+
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-13");
+  EXPECT_EQ(0x1.0p-13, test.convertToDouble());
+
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-14");
+  EXPECT_EQ(0x1.0p-14, test.convertToDouble());
+  EXPECT_TRUE(test.isSmallestNormalized());
+
+  // Smallest value
+  test = APFloat::getSmallest(APFloat::Float8E5M3FNU());
+  EXPECT_EQ(0x1.0p-17, test.convertToDouble());
+
+  // Value below the smallest, but clamped to the smallest
+  test = APFloat(APFloat::Float8E5M3FNU(), "0x1.0p-18");
+  EXPECT_EQ(0, test.convertToDouble());
+}
+
+TEST(APFloatTest, Float8E5M3FNUFromString) {
+  // Exactly representable
+  EXPECT_EQ(64, APFloat(APFloat::Float8E5M3FNU(), "64").convertToDouble());
+  // Overflow to NaN
+  EXPECT_TRUE(APFloat(APFloat::Float8E5M3FNU(), "0x1.0p17").isNaN());
+  // Inf converted to NaN
+  EXPECT_TRUE(APFloat(APFloat::Float8E5M3FNU(), "inf").isNaN());
+  // NaN converted to NaN
+  EXPECT_TRUE(APFloat(APFloat::Float8E5M3FNU(), "nan").isNaN());
+}
+
+TEST(APFloatTest, Float8E5M3FNUDivideByZero) {
+  APFloat x(APFloat::Float8E5M3FNU(), "1");
+  APFloat zero(APFloat::Float8E5M3FNU(), "0");
+  EXPECT_EQ(x.divide(zero, APFloat::rmNearestTiesToEven), 
APFloat::opDivByZero);
+  EXPECT_TRUE(x.isNaN());
+}
+
+TEST(APFloatTest, Float8E5M3FNUGetSignedValues) {
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+  EXPECT_DEATH(APFloat(APFloat::Float8E5M3FNU(), "-64"),
+               "This floating point format does not support signed values");
+  EXPECT_DEATH(APFloat(APFloat::Float8E5M3FNU(), "-0x1.0p17"),
+               "This floating point format does not support signed values");
+  EXPECT_DEATH(APFloat(APFloat::Float8E5M3FNU(), "-inf"),
+               "This floating point format does not support signed values");
+  EXPECT_DEATH(APFloat::getNaN(APFloat::Float8E5M3FNU(), true),
+               "This floating point format does not support signed values");
+  EXPECT_DEATH(APFloat::getInf(APFloat::Float8E5M3FNU(), true),
+               "This floating point format does not support signed values");
+  EXPECT_DEATH(APFloat::getSmallest(APFloat::Float8E5M3FNU(), true),
+               "This floating point format does not support signed values");
+  EXPECT_DEATH(APFloat::getSmallestNormalized(APFloat::Float8E5M3FNU(), true),
+               "This floating point format does not support signed values");
+  EXPECT_DEATH(APFloat::getLargest(APFloat::Float8E5M3FNU(), true),
+               "This floating point format does not support signed values");
+  APFloat x = APFloat(APFloat::Float8E5M3FNU(), "4");
+  APFloat y = APFloat(APFloat::Float8E5M3FNU(), "8");
+  EXPECT_DEATH(x.subtract(y, APFloat::rmNearestTiesToEven),
+               "This floating point format does not support signed values");
+#endif // NDEBUG
+#endif // GTEST_HAS_DEATH_TEST
+}
+
+TEST(APFloatTest, Float8E5M3FNUGetInf) {
+  // The Float8E5M3FNU format does not support infinity and the all ones
+  // representation is treated as NaN.
+  APFloat t = APFloat::getInf(APFloat::Float8E5M3FNU());
+  EXPECT_TRUE(t.isNaN());
+  EXPECT_FALSE(t.isInfinity());
+}
+
+TEST(APFloatTest, Float8E5M3FNUSmallest) {
+  APFloat test(APFloat::getSmallest(APFloat::Float8E5M3FNU()));
+  EXPECT_EQ(0x1.0p-17, test.convertToDouble());
+
+  EXPECT_TRUE(test.isSmallest());
+  EXPECT_EQ(fcPosSubnormal, test.classify());
+
+  test = APFloat::getAllOnesValue(APFloat::Float8E5M3FNU());
+  EXPECT_TRUE(test.isNaN());
+}
+
+TEST(APFloatTest, Float8E5M3FNUExhaustivePair) {
+  // Test each pair of 8-bit values for Float8E5M3FNU format.
+  // This format is unsigned, so subtraction is only tested when the result
+  // is non-negative (which corresponds to i >= j since the bit-pattern
+  // ordering matches the value ordering). IEEE remainder can produce
+  // negative results, so it is only tested when the reference result is
+  // non-negative.
+  APFloat::Semantics Sem = APFloat::S_Float8E5M3FNU;
+  const llvm::fltSemantics &S = APFloat::EnumToSemantics(Sem);
+  for (int i = 0; i < 256; ++i) {
+    for (int j = 0; j < 256; ++j) {
+      SCOPED_TRACE("sem=" + std::to_string(Sem) + ",i=" + std::to_string(i) +
+                   ",j=" + std::to_string(j));
+      APFloat x(S, APInt(8, i));
+      APFloat y(S, APInt(8, j));
+
+      bool losesInfo;
+      APFloat xd = x;
+      xd.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
+                 &losesInfo);
+      EXPECT_FALSE(losesInfo);
+      APFloat yd = y;
+      yd.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
+                 &losesInfo);
+      EXPECT_FALSE(losesInfo);
+
+      // Add
+      APFloat z = x;
+      z.add(y, APFloat::rmNearestTiesToEven);
+      APFloat zd = xd;
+      zd.add(yd, APFloat::rmNearestTiesToEven);
+      zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo);
+      EXPECT_TRUE(z.bitwiseIsEqual(zd))
+          << "sem=" << Sem << ", i=" << i << ", j=" << j;
+
+      // Subtract
+      if (i >= j) {
+        z = x;
+        z.subtract(y, APFloat::rmNearestTiesToEven);
+        zd = xd;
+        zd.subtract(yd, APFloat::rmNearestTiesToEven);
+        zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo);
+        EXPECT_TRUE(z.bitwiseIsEqual(zd))
+            << "sem=" << Sem << ", i=" << i << ", j=" << j;
+      }
+
+      // Multiply
+      z = x;
+      z.multiply(y, APFloat::rmNearestTiesToEven);
+      zd = xd;
+      zd.multiply(yd, APFloat::rmNearestTiesToEven);
+      zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo);
+      EXPECT_TRUE(z.bitwiseIsEqual(zd))
+          << "sem=" << Sem << ", i=" << i << ", j=" << j;
+
+      // Divide
+      z = x;
+      z.divide(y, APFloat::rmNearestTiesToEven);
+      zd = xd;
+      zd.divide(yd, APFloat::rmNearestTiesToEven);
+      zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo);
+      EXPECT_TRUE(z.bitwiseIsEqual(zd))
+          << "sem=" << Sem << ", i=" << i << ", j=" << j;
+
+      // Mod
+      z = x;
+      z.mod(y);
+      zd = xd;
+      zd.mod(yd);
+      zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo);
+      EXPECT_TRUE(z.bitwiseIsEqual(zd))
+          << "sem=" << Sem << ", i=" << i << ", j=" << j;
+
+      // Remainder: IEEE remainder can produce negative results, which this
+      // unsigned format cannot represent. Only test when the reference
+      // result is non-negative.
+      zd = xd;
+      zd.remainder(yd);
+      if (!zd.isNegative()) {
+        z = x;
+        z.remainder(y);
+        zd.convert(S, APFloat::rmNearestTiesToEven, &losesInfo);
+        EXPECT_TRUE(z.bitwiseIsEqual(zd))
+            << "sem=" << Sem << ", i=" << i << ", j=" << j;
+      }
+    }
+  }
+}
+
+TEST(APFloatTest, Float8E5M3FNUExhaustive) {
+  // Test each of the 256 Float8E5M3FNU values.
+  // Layout: 5 exponent bits + 3 mantissa bits, bias = 15, NaN = 0xFF
+  // (all-ones).
+  for (int i = 0; i < 256; i++) {
+    APFloat test(APFloat::Float8E5M3FNU(), APInt(8, i));
+    SCOPED_TRACE("i=" + std::to_string(i));
+
+    // bitcastToAPInt
+    EXPECT_EQ(i, test.bitcastToAPInt());
+
+    // isLargest
+    if (i == 254) {
+      EXPECT_TRUE(test.isLargest());
+      EXPECT_EQ(test.convertToDouble(), 0x1.cp16);
+    } else {
+      EXPECT_FALSE(test.isLargest());
+    }
+
+    // isSmallest (smallest positive subnormal: bit pattern 0x01 = 2^-17)
+    if (i == 1) {
+      EXPECT_TRUE(test.isSmallest());
+      EXPECT_EQ(test.convertToDouble(), 0x1.0p-17);
+    } else {
+      EXPECT_FALSE(test.isSmallest());
+    }
+
+    // NaN is the all-ones bit pattern.
+    if (i == 255) {
+      EXPECT_TRUE(test.isNaN());
+      continue;
+    }
+
+    // convert to Double
+    bool losesInfo;
+    APFloat::opStatus status = test.convert(
+        APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo);
+    EXPECT_EQ(status, APFloat::opOK);
+    EXPECT_FALSE(losesInfo);
+
+    // Expected value:
+    //   i == 0      -> +0
+    //   1..7        -> subnormal: i * 2^-17
+    //   8..254      -> normal:    (1 + (i & 7)/8) * 2^((i >> 3) - 15)
+    double expected;
+    if (i == 0)
+      expected = 0.0;
+    else if (i < 8)
+      expected = std::ldexp(static_cast<double>(i), -17);
+    else
+      expected = std::ldexp(1.0 + (i & 7) / 8.0, (i >> 3) - 15);
+    EXPECT_EQ(test.convertToDouble(), expected);
+  }
+}
+
+TEST(APFloatTest, Float8E5M3FNUGetExactLog2) {
+  const fltSemantics &Semantics = APFloat::Float8E5M3FNU();
+  APFloat One(Semantics, "1.0");
+  EXPECT_EQ(0, One.getExactLog2());
+
+  // 3.0 is exactly representable (1.5 * 2^1) but not a power of two.
+  EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2());
+
+  // Exact power-of-two value.
+  EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2());
+  EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2Abs());
----------------
schwarzschild-radius wrote:

I added it earlier but I noticed that the existing test itself can be updated. 
I have removed the standalone test for UE5M3

https://github.com/llvm/llvm-project/pull/210720
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to