diff options
-rw-r--r-- | vespalib/src/tests/util/brain_float16/brain_float16_test.cpp | 37 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/objects/nbostream.h | 3 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/brain_float16.h | 8 |
3 files changed, 46 insertions, 2 deletions
diff --git a/vespalib/src/tests/util/brain_float16/brain_float16_test.cpp b/vespalib/src/tests/util/brain_float16/brain_float16_test.cpp index 6de41b3e038..9222b01b000 100644 --- a/vespalib/src/tests/util/brain_float16/brain_float16_test.cpp +++ b/vespalib/src/tests/util/brain_float16/brain_float16_test.cpp @@ -1,16 +1,52 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/vespalib/util/brain_float16.h> +#include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/gtest/gtest.h> #include <stdio.h> #include <cmath> #include <cmath> #include <cfenv> +#include <vector> using namespace vespalib; using Limits = std::numeric_limits<BrainFloat16>; +static std::vector<float> simple_values = { + 0.0, 1.0, -1.0, -0.0, 1.75, 0x1.02p20, -0x1.02p-20, 0x3.0p-100, 0x7.0p100 +}; + +TEST(BrainFloat16Test, normal_usage) { + EXPECT_EQ(sizeof(float), 4); + EXPECT_EQ(sizeof(BrainFloat16), 2); + BrainFloat16 answer = 42; + double fortytwo = answer; + EXPECT_EQ(fortytwo, 42); + std::vector<BrainFloat16> vec; + for (float value : simple_values) { + BrainFloat16 b = value; + float recover = b; + EXPECT_EQ(value, recover); + } + BrainFloat16 b1 = 0x101; + EXPECT_EQ(float(b1), 0x100); + BrainFloat16 b2 = 0x111; + EXPECT_EQ(float(b2), 0x110); +} + +TEST(BrainFloat16Test, with_nbostream) { + nbostream buf; + for (BrainFloat16 value : simple_values) { + buf << value; + } + for (float value : simple_values) { + BrainFloat16 stored; + buf >> stored; + EXPECT_EQ(float(stored), value); + } +} + TEST(BrainFloat16Test, constants_check) { EXPECT_EQ(0x1.0p-7, (1.0/128.0)); @@ -95,7 +131,6 @@ TEST(BrainFloat16Test, check_special_values) { BrainFloat16 b_from_f_neg = f_neg; BrainFloat16 b_from_f_qnan = f_qnan; BrainFloat16 b_from_f_snan = f_snan; - EXPECT_EQ(sizeof(b_inf), 2); EXPECT_EQ(memcmp(&b_inf, &b_from_f_inf, sizeof(BrainFloat16)), 0); EXPECT_EQ(memcmp(&b_qnan, &b_from_f_qnan, sizeof(BrainFloat16)), 0); EXPECT_EQ(memcmp(&b_snan, &b_from_f_snan, sizeof(BrainFloat16)), 0); diff --git a/vespalib/src/vespa/vespalib/objects/nbostream.h b/vespalib/src/vespa/vespalib/objects/nbostream.h index b0823f76d71..2462bcebf5d 100644 --- a/vespalib/src/vespa/vespalib/objects/nbostream.h +++ b/vespalib/src/vespa/vespalib/objects/nbostream.h @@ -5,6 +5,7 @@ #include <vespa/vespalib/stllike/string.h> #include <vespa/vespalib/util/array.h> #include <vespa/vespalib/util/buffer.h> +#include <vespa/vespalib/util/brain_float16.h> #include "nbo.h" namespace vespalib { @@ -38,6 +39,8 @@ public: nbostream & operator >> (double & v) { double n; read8(&n); v = nbo::n2h(n); return *this; } nbostream & operator << (float v) { float n(nbo::n2h(v)); write4(&n); return *this; } nbostream & operator >> (float & v) { float n; read4(&n); v = nbo::n2h(n); return *this; } + nbostream & operator << (BrainFloat16 v) { uint16_t n(nbo::n2h(v.get_bits())); write2(&n); return *this; } + nbostream & operator >> (BrainFloat16 & v) { uint16_t n; read2(&n); v.assign_bits(nbo::n2h(n)); return *this; } nbostream & operator << (int64_t v) { int64_t n(nbo::n2h(v)); write8(&n); return *this; } nbostream & operator >> (int64_t & v) { int64_t n; read8(&n); v = nbo::n2h(n); return *this; } nbostream & operator << (uint64_t v) { uint64_t n(nbo::n2h(v)); write8(&n); return *this; } diff --git a/vespalib/src/vespa/vespalib/util/brain_float16.h b/vespalib/src/vespa/vespalib/util/brain_float16.h index 85ac7dce107..25f25801790 100644 --- a/vespalib/src/vespa/vespalib/util/brain_float16.h +++ b/vespalib/src/vespa/vespalib/util/brain_float16.h @@ -23,13 +23,19 @@ public: constexpr BrainFloat16(BrainFloat16 &&other) noexcept = default; constexpr BrainFloat16& operator=(const BrainFloat16 &other) noexcept = default; constexpr BrainFloat16& operator=(BrainFloat16 &&other) noexcept = default; + constexpr BrainFloat16& operator=(float value) noexcept { + _bits = float_to_bits(value); + return *this; + } constexpr operator float () const noexcept { return bits_to_float(_bits); } constexpr float to_float() const noexcept { return bits_to_float(_bits); } - constexpr void assign(float value) noexcept { _bits = float_to_bits(value); } + constexpr uint16_t get_bits() const { return _bits; } + constexpr void assign_bits(uint16_t value) noexcept { _bits = value; } + static constexpr uint16_t float_to_bits(float value) noexcept { TwoU16 both{0,0}; static_assert(sizeof(TwoU16) == sizeof(float)); |