added ExtendedFloat::fromHalfPrecision
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 17 Aug 2017 21:46:09 +0000 (14:46 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 17 Aug 2017 21:46:09 +0000 (14:46 -0700)
src/util/soft_float.cpp
src/util/soft_float.h

index 7f4d402584b463e37f5efafa0a58e718035db9ec..0a581f3bbdd04cf5d1be646b0b70ebb5077a8f65 100644 (file)
@@ -35,7 +35,7 @@
 namespace
 {
 using namespace vulkan_cpu::util::soft_float;
-std::string hexValue(const ExtendedFloat &v)
+[[gnu::unused]] std::string hexValue(const ExtendedFloat &v)
 {
     if(v.isNaN())
     {
@@ -387,6 +387,14 @@ void mainFn()
     {
         return log10(ExtendedFloat(a));
     };
+    auto fromHalf_1 = [](std::uint16_t a, long double b) -> ExtendedFloat
+    {
+        return ExtendedFloat::fromHalfPrecision(a);
+    };
+    auto fromHalf_2 = [](std::uint16_t a, long double b) -> ExtendedFloat
+    {
+        return ExtendedFloat(b);
+    };
     const long double NaN = std::numeric_limits<long double>::quiet_NaN();
     const long double Infinity = std::numeric_limits<long double>::infinity();
     testCase("add", add1, add2, +0.0L, +0.0L);
@@ -526,6 +534,21 @@ void mainFn()
     testCase("log2", log2_1, log2_2, static_cast<long double>(ExtendedFloat::LogOf2()));
     testCase("log10", log10_1, log10_2, 1e1001L);
     testCase("log10", log10_1, log10_2, 1.5L);
+    testCase("fromHalf",
+             fromHalf_1,
+             fromHalf_2,
+             static_cast<std::uint64_t>(0x1U),
+             5.9604644775390625e-8L);
+    testCase("fromHalf",
+             fromHalf_1,
+             fromHalf_2,
+             static_cast<std::uint64_t>(0x8001U),
+             -5.9604644775390625e-8L);
+    testCase("fromHalf", fromHalf_1, fromHalf_2, static_cast<std::uint64_t>(0x3C00U), 1.0L);
+    testCase("fromHalf", fromHalf_1, fromHalf_2, static_cast<std::uint64_t>(0xBC00U), -1.0L);
+    testCase("fromHalf", fromHalf_1, fromHalf_2, static_cast<std::uint64_t>(0x7C00U), Infinity);
+    testCase("fromHalf", fromHalf_1, fromHalf_2, static_cast<std::uint64_t>(0xFC00U), -Infinity);
+    testCase("fromHalf", fromHalf_1, fromHalf_2, static_cast<std::uint64_t>(0x7C01U), NaN);
 }
 struct Init
 {
index e8b7efbf9831f8cf4cc120f9e7c4c821f5779fd3..b0ca4de3d09f74557e9e0ac3d42daa63ca806979 100644 (file)
@@ -561,6 +561,23 @@ struct ExtendedFloat final // modeled after IEEE754 standard
         value = std::scalbn(value, 63 - static_cast<long>(exponent) + exponentBias());
         mantissa = value;
     }
+    static constexpr ExtendedFloat fromHalfPrecision(std::uint16_t value) noexcept
+    {
+        bool sign = (value & 0x8000U) != 0;
+        std::uint16_t exponentField = (value & 0x7C00U) >> 10;
+        std::uint16_t mantissaField = value & 0x3FFU;
+        if(exponentField == 0x1FU)
+        {
+            if(mantissaField != 0)
+                return NaN();
+            return Infinity(sign);
+        }
+        if(exponentField != 0)
+            mantissaField |= 0x400U; // add in implicit 1
+        else
+            exponentField = 1;
+        return ExtendedFloat(mantissaField, static_cast<int>(exponentField) - 15 - 10 + exponentBias() + 63, sign);
+    }
     explicit operator long double() const noexcept
     {
         if(exponent == infinityNaNExponent())