HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
half.hpp
1// Copyright Take Vos 2020-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "macros.hpp"
8#include "half_to_float.hpp"
9#include "float_to_half.hpp"
10#include <cstdint>
11#include <type_traits>
12#include <bit>
13#include <algorithm>
14#include <numeric>
15#include <format>
16
17hi_export_module(hikocpu : half);
18
19hi_warning_push();
20// C26472: Don't use static_cast for arithmetic conversions, Use brace initialization, gsl::narrow_cast or gsl::narrow (type.1).
21// static_cast here is used to extract bits and cause sign-extension.
22hi_warning_ignore_msvc(26472);
23
24hi_export namespace hi {
25inline namespace v1 {
26
27struct half {
28 uint16_t v = 0;
29
30 constexpr half() noexcept = default;
31 constexpr half(half const&) noexcept = default;
32 constexpr half(half&&) noexcept = default;
33 constexpr half& operator=(half const&) noexcept = default;
34 constexpr half& operator=(half&&) noexcept = default;
35 constexpr half(std::in_place_t, uint16_t v) noexcept : v(v) {}
36
37 constexpr explicit half(float other) noexcept : v(float_to_half(other)) {}
38
39 constexpr operator float() const noexcept
40 {
41 return half_to_float(v);
42 }
43
44 [[nodiscard]] constexpr uint16_t const& intrinsic() const noexcept
45 {
46 return v;
47 }
48
49 [[nodiscard]] constexpr uint16_t& intrinsic() noexcept
50 {
51 return v;
52 }
53
54 constexpr half& operator=(float other) noexcept
55 {
56 v = float_to_half(other);
57 return *this;
58 }
59
60 [[nodiscard]] std::size_t hash() const noexcept
61 {
62 return std::hash<uint16_t>{}(v);
63 }
64
65 template<typename LHS, typename RHS>
66 [[nodiscard]] constexpr friend bool operator==(LHS lhs, RHS rhs) noexcept requires requires {
67 static_cast<float>(lhs);
68 static_cast<float>(rhs);
69 }
70 {
71 return static_cast<float>(lhs) == static_cast<float>(rhs);
72 }
73
74 template<typename LHS, typename RHS>
75 [[nodiscard]] constexpr friend auto operator<=>(LHS lhs, RHS rhs) noexcept requires requires {
76 static_cast<float>(lhs);
77 static_cast<float>(rhs);
78 }
79 {
80 return static_cast<float>(lhs) <=> static_cast<float>(rhs);
81 }
82
83#define HI_X_binary_math_op(op) \
84 template<typename LHS, typename RHS> \
85 [[nodiscard]] constexpr friend float operator op(LHS lhs, RHS rhs) noexcept requires requires { \
86 static_cast<float>(lhs); \
87 static_cast<float>(rhs); \
88 } \
89 { \
90 return half{static_cast<float>(lhs) op static_cast<float>(rhs)}; \
91 }
92
93 // clang-format off
94 HI_X_binary_math_op(+)
95 HI_X_binary_math_op(-)
96 HI_X_binary_math_op(*)
97 HI_X_binary_math_op(/)
98 // clang-format on
99#undef HI_X_binary_math_op
100
101 //[[nodiscard]] constexpr friend half operator%(half const& lhs, half const& rhs) noexcept
102 //{
103 // auto const lhs_ = static_cast<float>(lhs);
104 // auto const rhs_ = static_cast<float>(rhs);
105 // auto const div_result = std::floor(lhs_ / rhs_);
106 // return half{lhs_ - (div_result * rhs_)};
107 //}
108
109#define HI_X_binary_bit_op(op) \
110 [[nodiscard]] constexpr friend half operator op(half const& lhs, half const& rhs) noexcept \
111 { \
112 return half(std::in_place, lhs.v op rhs.v); \
113 }
114
115 // clang-format off
116 HI_X_binary_bit_op(|)
117 HI_X_binary_bit_op(&)
118 HI_X_binary_bit_op(^)
119 // clang-format on
120#undef HI_X_binary_bit_op
121};
122
123// Check if half can be std::bit_cast<uint16_t>().
124static_assert(sizeof(half) == sizeof(uint16_t));
125static_assert(std::is_trivially_copy_constructible_v<half>);
126static_assert(std::is_trivially_move_constructible_v<half>);
127static_assert(std::is_trivially_copy_assignable_v<half>);
128static_assert(std::is_trivially_move_assignable_v<half>);
129static_assert(std::is_trivially_destructible_v<half>);
130
131static_assert(requires(half a) { std::bit_cast<uint16_t>(a); });
132static_assert(requires(uint16_t a) { std::bit_cast<half>(a); });
133
134} // namespace v1
135} // namespace hi::inline v1
136
137hi_export namespace std {
138template<>
139struct hash<::hi::half> {
140 size_t operator()(::hi::half const& rhs) noexcept
141 {
142 return rhs.hash();
143 }
144};
145
146// XXX #617 MSVC bug does not handle partial specialization in modules.
147template<>
148struct formatter<::hi::half, char> : formatter<float, char> {
149 constexpr auto format(::hi::half const& t, auto& fc) const
150 {
151 return formatter<float, char>::format(static_cast<float>(t), fc);
152 }
153};
154
155template<>
157 using value_type = ::hi::half;
158
159 constexpr static bool is_specialized = true;
160 constexpr static bool is_signed = true;
161 constexpr static bool is_integer = false;
162 constexpr static bool is_exact = false;
163 constexpr static bool has_infinity = true;
164 constexpr static bool has_quiet_NaN = true;
165 constexpr static bool has_signaling_NaN = false;
166 constexpr static float_round_style round_style = round_to_nearest;
167 constexpr static bool is_iec559 = true;
168 constexpr static bool is_bounded = true;
169 constexpr static bool is_modulo = false;
170 constexpr static int digits = 10;
171 constexpr static int digits10 = 4;
172 constexpr static int max_digits10 = 4;
173 constexpr static int min_exponent = -14;
174 constexpr static int min_exponent10 = -3;
175 constexpr static int max_exponent = 15;
176 constexpr static int max_exponent10 = 3;
177 constexpr static bool traps = false;
178 constexpr static bool tinyness_before = false;
179
180 constexpr static value_type min() noexcept
181 {
182 return ::hi::half(std::in_place, 0x0400);
183 }
184
185 constexpr static value_type lowest() noexcept
186 {
187 return ::hi::half(std::in_place, 0xfbff);
188 }
189
190 constexpr static value_type max() noexcept
191 {
192 return ::hi::half(std::in_place, 0x7bff);
193 }
194
195 constexpr static value_type epsilon() noexcept
196 {
197 return ::hi::half(std::in_place, 0xfbff);
198 }
199
200 constexpr static value_type round_error() noexcept
201 {
202 return ::hi::half(std::in_place, 0x3800); // 0.5
203 }
204
205 constexpr static value_type infinity() noexcept
206 {
207 return ::hi::half(std::in_place, 0x7c00);
208 }
209
210 constexpr static value_type quiet_NaN() noexcept
211 {
212 return ::hi::half(std::in_place, 0x7c01);
213 }
214
215 constexpr static value_type signaling_NaN() noexcept
216 {
217 return ::hi::half(std::in_place, 0x7e01);
218 }
219
220 constexpr static value_type denorm_min() noexcept
221 {
222 return ::hi::half(std::in_place, 0x0001);
223 }
224};
225}
226
227hi_warning_pop();
@ other
The gui_event does not have associated data.
STL namespace.
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition half.hpp:27
T denorm_min(T... args)
T epsilon(T... args)
T infinity(T... args)
T lowest(T... args)
T max(T... args)
T min(T... args)
T operator()(T... args)
T quiet_NaN(T... args)
T round_error(T... args)
T signaling_NaN(T... args)