一呼百應, "one call, a hundred responses"
Loading...
Searching...
No Matches
fp16.hpp
Go to the documentation of this file.
1#pragma once
2
11#include <bit>
12#include <compare>
13#include <cstdint>
14#include <limits>
16
17namespace ein {
18
19struct fp16 {
20 using underlying_type = _Float16;
21
22 _Float16 content;
23
25 constexpr fp16() noexcept = default;
26
28 constexpr fp16(ein_noescape fp16 const &) noexcept = default;
29
31 constexpr fp16(ein_noescape fp16 &&) noexcept = default;
32
34 constexpr fp16(float content) noexcept : content(content) {}
35
37 constexpr fp16(_Float16 content) noexcept : content(content) {}
38
40 constexpr operator float (this fp16 self) noexcept { return self.content; }
41
43 constexpr operator _Float16 (this fp16 self) noexcept { return self.content; }
44
46 constexpr fp16 & operator = (ein_noescape fp16 const &) noexcept
47 ein_lifetimebound = default;
48
50 constexpr fp16 & operator = (ein_noescape fp16 &&) noexcept
51 ein_lifetimebound = default;
52
54 friend constexpr bool operator == (fp16 x, fp16 y) noexcept {
55 return x.content == y.content;
56 }
57
59 friend constexpr bool operator != (fp16 x, fp16 y) noexcept {
60 return x.content != y.content;
61 }
62
64 friend constexpr std::partial_ordering operator <=> (fp16 x, fp16 y) noexcept {
65 return x.content <=> y.content;
66 }
67
69 friend constexpr bool operator < (fp16 x, fp16 y) noexcept {
70 return x.content < y.content;
71 }
72
74 friend constexpr bool operator <= (fp16 x, fp16 y) noexcept {
75 return x.content <= y.content;
76 }
78 friend constexpr bool operator > (fp16 x, fp16 y) noexcept {
79 return x.content > y.content;
80 }
81
83 friend constexpr bool operator >= (fp16 x, fp16 y) noexcept {
84 return x.content >= y.content;
85 }
86
88 friend constexpr void swap(
91 ) noexcept {
92 using std::swap;
93 swap(x.content,y.content);
94 }
95
97 static constexpr fp16 from_bits(uint16_t data) noexcept {
98 return std::bit_cast<fp16>(data);
99 }
100
102 constexpr uint16_t to_bits(this fp16 self) noexcept {
103 return std::bit_cast<uint16_t>(self.content);
104 }
105
106};
107
109constexpr fp16 operator""_fp16(long double v) noexcept {
110 return fp16(static_cast<float>(v));
111}
112
113} // namespace ein
114
115namespace std {
117 constexpr bool isnan(ein::fp16 x) noexcept {
118 // Sign doesn't matter, frac not zero (infinity)
119 return (x.to_bits() & 0x7FFF) > 0x7c00;
120 }
121
122 template <>
123 class numeric_limits<ein::fp16> {
124 public:
125 static constexpr bool is_specialized = true;
127 static constexpr ein::fp16 min() noexcept {
128 return ein::fp16::from_bits(0x0200);
129 }
131 static constexpr ein::fp16 max() noexcept {
132 return ein::fp16::from_bits(0x7BFF);
133 }
135 static constexpr ein::fp16 lowest() noexcept {
136 return ein::fp16::from_bits(0xFBFF);
137 }
138 static constexpr int digits = 11;
139 static constexpr int digits10 = 3;
140 static constexpr bool is_signed = true;
141 static constexpr bool is_integer = false;
142 static constexpr bool is_exact = false;
143 static constexpr int radix = 2;
145 static constexpr ein::fp16 epsilon() noexcept {
146 return ein::fp16::from_bits(0x1200);
147 }
149 static constexpr ein::fp16 round_error() noexcept {
150 return ein::fp16::from_bits(0x3C00);
151 }
152 static constexpr int min_exponent = -13;
153 static constexpr int min_exponent10 = -4;
154 static constexpr int max_exponent = 16;
155 static constexpr int max_exponent10 = 4;
156 static constexpr bool has_infinity = true;
157 static constexpr bool has_quiet_NaN = true;
158 static constexpr bool has_signaling_NaN = true;
159 static constexpr float_denorm_style has_denorm = denorm_absent;
160 static constexpr bool has_denorm_loss = false;
162 static constexpr ein::fp16 infinity() noexcept {
163 return ein::fp16::from_bits(0x7C00);
164 }
166 static constexpr ein::fp16 quiet_NaN() noexcept {
167 return ein::fp16::from_bits(0x7FFF);
168 }
170 static constexpr ein::fp16 signaling_NaN() noexcept {
171 return ein::fp16::from_bits(0x7DFF);
172 }
174 static constexpr ein::fp16 denorm_min() noexcept {
175 return ein::fp16::from_bits(0);
176 }
177 static constexpr bool is_iec559 = false;
178 static constexpr bool is_bounded = false;
179 static constexpr bool is_modulo = false;
180 static constexpr bool traps = false;
181 static constexpr bool tinyness_before = false;
182 static constexpr float_round_style round_style = round_to_nearest;
183 };
184
185 extern template class numeric_limits<ein::fp16>;
186
187} // namespace std
188
189#if defined(EIN_TESTING) || defined(EIN_TESTING_FP16)
190TEST_CASE("fp16","[fp16]") {
191 using namespace ein;
192 using Catch::Approx;
193
194 SECTION("fp16 default constructors and conversion") {
195 CHECK(fp16(0.5f).content == Approx(0.5f));
196 CHECK(0.25_fp16 .content == Approx(0.25f));
197 CHECK(static_cast<float>(1.0_fp16) == Approx(1.0f));
198 CHECK(static_cast<_Float16>(0.75_fp16) == Approx(_Float16(0.75f)));
199 }
200
201 SECTION("fp16 comparison operators") {
202 CHECK(0.5_fp16 == 0.5_fp16);
203 CHECK(0.1_fp16 < 0.2_fp16);
204 CHECK(0.3_fp16 > 0.2_fp16);
205 CHECK(0.2_fp16 <= 0.2_fp16);
206 CHECK(0.2_fp16 >= 0.2_fp16);
207 }
208
209 SECTION("fp16 swap function") {
210 fp16 x(1.0_fp16), y(2.0_fp16);
211 swap(x, y);
212 CHECK(x == fp16(2.0_fp16));
213 CHECK(y == fp16(1.0_fp16));
214 }
215
216 SECTION("fp16 bit operations") {
217 fp16 val = fp16::from_bits(0x3C00);
218 CHECK(val.to_bits() == 0x3C00);
219 CHECK(fp16::from_bits(0x7C00) == std::numeric_limits<fp16>::infinity());
220 }
221
222 SECTION("fp16 isnan function") {
223 CHECK(std::isnan(fp16::from_bits(0x7FFF)));
224 CHECK_FALSE(std::isnan(fp16(1.0_fp16)));
225 }
226
227 SECTION("fp16 numeric_limits") {
228 using nl = std::numeric_limits<fp16>;
229
230 CHECK(nl::is_specialized);
231 CHECK(nl::is_signed);
232 CHECK(nl::digits == 11);
233 CHECK(nl::epsilon() == fp16::from_bits(0x1200));
234 CHECK(nl::round_error() == fp16::from_bits(0x3C00));
235 CHECK(nl::min() == fp16::from_bits(0x0200));
236 CHECK(nl::max() == fp16::from_bits(0x7BFF));
237 CHECK(nl::lowest() == fp16::from_bits(0xFBFF));
238 CHECK(nl::infinity() == fp16::from_bits(0x7C00));
239 CHECK(std::isnan(nl::quiet_NaN()));
240 CHECK(std::isnan(nl::signaling_NaN()));
241 CHECK(nl::denorm_min() == fp16::from_bits(0));
242 }
243}
244#endif
static constexpr ein::fp16 infinity() noexcept
Definition fp16.hpp:162
static constexpr ein::fp16 quiet_NaN() noexcept
Definition fp16.hpp:166
static constexpr ein::fp16 min() noexcept
Definition fp16.hpp:127
static constexpr ein::fp16 lowest() noexcept
Definition fp16.hpp:135
static constexpr ein::fp16 signaling_NaN() noexcept
Definition fp16.hpp:170
static constexpr ein::fp16 round_error() noexcept
Definition fp16.hpp:149
static constexpr ein::fp16 denorm_min() noexcept
Definition fp16.hpp:174
static constexpr ein::fp16 epsilon() noexcept
Definition fp16.hpp:145
static constexpr ein::fp16 max() noexcept
Definition fp16.hpp:131
#define ein_reinitializes
[[clang::reinitializes]]
Definition common.hpp:418
#define ein_artificial
[[artificial]].
Definition common.hpp:220
#define ein_inline
inline [[always_inline]]
Definition common.hpp:188
#define ein_lifetimebound
[[lifetimebound]]
Definition common.hpp:137
#define ein_noescape
portable __attribute__((noescape))
Definition common.hpp:151
#define ein_nodiscard
C++17 [[nodiscard]].
Definition common.hpp:165
#define ein_const
[[const]] is not const
Definition common.hpp:84
Definition cpuid.cpp:16
Definition bf16.cpp:11
constexpr bool isnan(ein::bf16 x) noexcept
Definition bf16.hpp:131
_Float16 content
Definition fp16.hpp:22
friend constexpr std::partial_ordering operator<=>(fp16 x, fp16 y) noexcept
Definition fp16.hpp:64
friend constexpr bool operator<(fp16 x, fp16 y) noexcept
Definition fp16.hpp:69
static constexpr fp16 from_bits(uint16_t data) noexcept
Definition fp16.hpp:97
_Float16 underlying_type
Definition fp16.hpp:20
ein_reinitializes constexpr fp16 & operator=(fp16 const &) noexcept=default
friend constexpr bool operator<=(fp16 x, fp16 y) noexcept
Definition fp16.hpp:74
friend constexpr bool operator>=(fp16 x, fp16 y) noexcept
Definition fp16.hpp:83
friend constexpr bool operator!=(fp16 x, fp16 y) noexcept
Definition fp16.hpp:59
friend constexpr bool operator>(fp16 x, fp16 y) noexcept
Definition fp16.hpp:78
constexpr uint16_t to_bits(this fp16 self) noexcept
Definition fp16.hpp:102
friend constexpr void swap(fp16 &x, fp16 &y) noexcept
Definition fp16.hpp:88
constexpr fp16(_Float16 content) noexcept
Definition fp16.hpp:37
constexpr fp16() noexcept=default