summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Juul <arnej@verizonmedia.com>2021-03-02 15:37:46 +0000
committerArne Juul <arnej@verizonmedia.com>2021-03-02 17:45:41 +0000
commit87d63e9c3e8004763d7c3eadb3145ea8262c9449 (patch)
tree931d235aa55659aad180ca486bae399462bee495
parent433fb61148345f8f187235f0875dbc10c0bfadeb (diff)
more BrainFloat16 functionality
* add assignment operator from float * add direct access to underlying representation * add handling in nbostream * unit test that show normal usage * unit test with nbostream
-rw-r--r--vespalib/src/tests/util/brain_float16/brain_float16_test.cpp37
-rw-r--r--vespalib/src/vespa/vespalib/objects/nbostream.h3
-rw-r--r--vespalib/src/vespa/vespalib/util/brain_float16.h8
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));