diff --git a/test/source/scwx/util/float.test.cpp b/test/source/scwx/util/float.test.cpp new file mode 100644 index 00000000..f91fe4bf --- /dev/null +++ b/test/source/scwx/util/float.test.cpp @@ -0,0 +1,50 @@ +#include + +#include + +namespace scwx +{ +namespace util +{ + +TEST(FloatTest, Decode32Positive1) +{ + uint16_t msw = 0x3f80; + uint16_t lsw = 0x0000; + + float x = DecodeFloat32(msw, lsw); + + EXPECT_FLOAT_EQ(x, 1.0f); +} + +TEST(FloatTest, Decode32Negative1) +{ + uint16_t msw = 0xbf80; + uint16_t lsw = 0x0000; + + float x = DecodeFloat32(msw, lsw); + + EXPECT_FLOAT_EQ(x, -1.0f); +} + +TEST(FloatTest, Decode32Positive12345678) +{ + uint16_t msw = 0x4b3c; + uint16_t lsw = 0x614e; + + float x = DecodeFloat32(msw, lsw); + + EXPECT_FLOAT_EQ(x, 12345678.0f); +} + +TEST(FloatTest, Decode16h0x5bb4) +{ + uint16_t hex = 0x5bb4; + + float x = DecodeFloat16(hex); + + EXPECT_FLOAT_EQ(x, 123.25f); +} + +} // namespace util +} // namespace scwx diff --git a/test/test.cmake b/test/test.cmake index d86dee48..2820dc09 100644 --- a/test/test.cmake +++ b/test/test.cmake @@ -15,7 +15,8 @@ set(SRC_AWIPS_TESTS source/scwx/awips/coded_location.test.cpp set(SRC_COMMON_TESTS source/scwx/common/color_table.test.cpp) set(SRC_QT_CONFIG_TESTS source/scwx/qt/config/radar_site.test.cpp) set(SRC_QT_MANAGER_TESTS source/scwx/qt/manager/settings_manager.test.cpp) -set(SRC_UTIL_TESTS source/scwx/util/rangebuf.test.cpp +set(SRC_UTIL_TESTS source/scwx/util/float.test.cpp + source/scwx/util/rangebuf.test.cpp source/scwx/util/streams.test.cpp source/scwx/util/vectorbuf.test.cpp) set(SRC_WSR88D_TESTS source/scwx/wsr88d/ar2v_file.test.cpp diff --git a/wxdata/include/scwx/util/float.hpp b/wxdata/include/scwx/util/float.hpp new file mode 100644 index 00000000..2e04e5b3 --- /dev/null +++ b/wxdata/include/scwx/util/float.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace scwx +{ +namespace util +{ + +float DecodeFloat16(uint16_t hex); +float DecodeFloat32(uint16_t msw, uint16_t lsw); + +} // namespace util +} // namespace scwx diff --git a/wxdata/source/scwx/util/float.cpp b/wxdata/source/scwx/util/float.cpp new file mode 100644 index 00000000..c837aeba --- /dev/null +++ b/wxdata/source/scwx/util/float.cpp @@ -0,0 +1,62 @@ +#include + +#include + +#ifdef WIN32 +# include +#else +# include +#endif + +namespace scwx +{ +namespace util +{ + +float DecodeFloat16(uint16_t hex) +{ + static constexpr uint16_t S_MASK = 0x8000; + static constexpr uint16_t S_LSB = 0; + static constexpr uint16_t S_SHIFT = 15 - S_LSB; + static constexpr uint16_t E_MASK = 0x7a00; + static constexpr uint16_t E_LSB = 5; + static constexpr uint16_t E_SHIFT = 15 - E_LSB; + static constexpr uint16_t F_MASK = 0x03ff; + static constexpr uint16_t F_LSB = 15; + static constexpr uint16_t F_SHIFT = 15 - F_LSB; + + uint16_t sHex = (hex & S_MASK) >> S_SHIFT; + uint16_t eHex = (hex & E_MASK) >> E_SHIFT; + uint16_t fHex = (hex & F_MASK) >> F_SHIFT; + + float value; + + float s = std::pow(-1.0f, static_cast(sHex)); + float e; + float f; + + if (eHex == 0) + { + e = 2.0f; + f = (fHex / std::pow(2.0f, 10.0f)); + } + else + { + e = std::pow(2.0f, eHex - 16.0f); + f = (1 + fHex / std::pow(2.0f, 10.0f)); + } + + value = s * e * f; + + return value; +} + +float DecodeFloat32(uint16_t msw, uint16_t lsw) +{ + uint32_t value = msw << 16 | lsw; + + return reinterpret_cast(value); +} + +} // namespace util +} // namespace scwx diff --git a/wxdata/wxdata.cmake b/wxdata/wxdata.cmake index 6bae5576..ad2f5c52 100644 --- a/wxdata/wxdata.cmake +++ b/wxdata/wxdata.cmake @@ -32,13 +32,15 @@ set(SRC_COMMON source/scwx/common/color_table.cpp source/scwx/common/products.cpp source/scwx/common/sites.cpp source/scwx/common/vcp.cpp) -set(HDR_UTIL include/scwx/util/iterator.hpp +set(HDR_UTIL include/scwx/util/float.hpp + include/scwx/util/iterator.hpp include/scwx/util/rangebuf.hpp include/scwx/util/streams.hpp include/scwx/util/threads.hpp include/scwx/util/time.hpp include/scwx/util/vectorbuf.hpp) -set(SRC_UTIL source/scwx/util/rangebuf.cpp +set(SRC_UTIL source/scwx/util/float.cpp + source/scwx/util/rangebuf.cpp source/scwx/util/streams.cpp source/scwx/util/time.cpp source/scwx/util/vectorbuf.cpp)