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(hikogui.utility.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 { inline namespace v1 {
25
26struct half {
27 uint16_t v = 0;
28
29 constexpr half() noexcept = default;
30 constexpr half(half const&) noexcept = default;
31 constexpr half(half&&) noexcept = default;
32 constexpr half& operator=(half const&) noexcept = default;
33 constexpr half& operator=(half&&) noexcept = default;
34
35 constexpr explicit half(float other) noexcept : v(float_to_half(other)) {}
36 constexpr explicit half(double other) noexcept : half(static_cast<float>(other)) {}
37 constexpr explicit half(long double other) noexcept : half(static_cast<float>(other)) {}
38
39 constexpr half(std::in_place_t, uint16_t v) noexcept : v(v) {}
40
41 [[nodiscard]] constexpr uint16_t const& intrinsic() const noexcept
42 {
43 return v;
44 }
45
46 [[nodiscard]] constexpr uint16_t& intrinsic() noexcept
47 {
48 return v;
49 }
50
51 constexpr half& operator=(float other) noexcept
52 {
53 v = float_to_half(other);
54 return *this;
55 }
56
57 constexpr operator float() const noexcept
58 {
59 return half_to_float(v);
60 }
61
62 [[nodiscard]] std::size_t hash() const noexcept
63 {
64 return std::hash<uint16_t>{}(v);
65 }
66
67 [[nodiscard]] constexpr friend bool operator==(half const& lhs, half const& rhs) noexcept
68 {
69 return static_cast<float>(lhs) == static_cast<float>(rhs);
70 }
71
72 [[nodiscard]] constexpr friend auto operator<=>(half const& lhs, half const& rhs) noexcept
73 {
74 return static_cast<float>(lhs) <=> static_cast<float>(rhs);
75 }
76
77#define HI_X_binary_math_op(op) \
78 [[nodiscard]] constexpr friend half operator op(half const& lhs, half const& rhs) noexcept \
79 { \
80 return half{static_cast<float>(lhs) op static_cast<float>(rhs)}; \
81 }
82
83 // clang-format off
84 HI_X_binary_math_op(+)
85 HI_X_binary_math_op(-)
86 HI_X_binary_math_op(*)
87 HI_X_binary_math_op(/)
88 // clang-format on
89#undef HI_X_binary_math_op
90
91 //[[nodiscard]] constexpr friend half operator%(half const& lhs, half const& rhs) noexcept
92 //{
93 // auto const lhs_ = static_cast<float>(lhs);
94 // auto const rhs_ = static_cast<float>(rhs);
95 // auto const div_result = std::floor(lhs_ / rhs_);
96 // return half{lhs_ - (div_result * rhs_)};
97 //}
98
99#define HI_X_binary_bit_op(op) \
100 [[nodiscard]] constexpr friend half operator op(half const& lhs, half const& rhs) noexcept \
101 { \
102 return half(std::in_place, lhs.v op rhs.v); \
103 }
104
105 // clang-format off
106 HI_X_binary_bit_op(|)
107 HI_X_binary_bit_op(&)
108 HI_X_binary_bit_op(^)
109 // clang-format on
110#undef HI_X_binary_bit_op
111};
112
113// Check if half can be std::bit_cast<uint16_t>().
114static_assert(sizeof(half) == sizeof(uint16_t));
115static_assert(std::is_trivially_copy_constructible_v<half>);
116static_assert(std::is_trivially_move_constructible_v<half>);
117static_assert(std::is_trivially_copy_assignable_v<half>);
118static_assert(std::is_trivially_move_assignable_v<half>);
119static_assert(std::is_trivially_destructible_v<half>);
120
121static_assert(requires(half a) { std::bit_cast<uint16_t>(a); });
122static_assert(requires(uint16_t a) { std::bit_cast<half>(a); });
123
124}} // namespace hi::inline v1
125
126hi_export namespace std {
127
128template<>
129struct hash<::hi::half> {
130 size_t operator()(::hi::half const& rhs) noexcept
131 {
132 return rhs.hash();
133 }
134};
135
136// XXX #617 MSVC bug does not handle partial specialization in modules.
137template<>
138struct formatter<::hi::half, char> : formatter<float, char> {
139 constexpr auto format(::hi::half const& t, auto& fc) const
140 {
141 return formatter<float, char>::format(static_cast<float>(t), fc);
142 }
143};
144
145template<>
147 using value_type = ::hi::half;
148
149 constexpr static bool is_specialized = true;
150 constexpr static bool is_signed = true;
151 constexpr static bool is_integer = false;
152 constexpr static bool is_exact = false;
153 constexpr static bool has_infinity = true;
154 constexpr static bool has_quiet_NaN = true;
155 constexpr static bool has_signaling_NaN = false;
156 constexpr static float_round_style round_style = round_to_nearest;
157 constexpr static bool is_iec559 = true;
158 constexpr static bool is_bounded = true;
159 constexpr static bool is_modulo = false;
160 constexpr static int digits = 10;
161 constexpr static int digits10 = 4;
162 constexpr static int max_digits10 = 4;
163 constexpr static int min_exponent = -14;
164 constexpr static int min_exponent10 = -3;
165 constexpr static int max_exponent = 15;
166 constexpr static int max_exponent10 = 3;
167 constexpr static bool traps = false;
168 constexpr static bool tinyness_before = false;
169
170 constexpr static value_type min() noexcept
171 {
172 return ::hi::half(std::in_place, 0x0400);
173 }
174
175 constexpr static value_type lowest() noexcept
176 {
177 return ::hi::half(std::in_place, 0xfbff);
178 }
179
180 constexpr static value_type max() noexcept
181 {
182 return ::hi::half(std::in_place, 0x7bff);
183 }
184
185 constexpr static value_type epsilon() noexcept
186 {
187 return ::hi::half(std::in_place, 0xfbff);
188 }
189
190 constexpr static value_type round_error() noexcept
191 {
192 return ::hi::half(std::in_place, 0x3800); // 0.5
193 }
194
195 constexpr static value_type infinity() noexcept
196 {
197 return ::hi::half(std::in_place, 0x7c00);
198 }
199
200 constexpr static value_type quiet_NaN() noexcept
201 {
202 return ::hi::half(std::in_place, 0x7c01);
203 }
204
205 constexpr static value_type signaling_NaN() noexcept
206 {
207 return ::hi::half(std::in_place, 0x7e01);
208 }
209
210 constexpr static value_type denorm_min() noexcept
211 {
212 return ::hi::half(std::in_place, 0x0001);
213 }
214};
215
216}
217
218hi_warning_pop();
@ other
The gui_event does not have associated data.
STL namespace.
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
The HikoGUI namespace.
Definition recursive_iterator.hpp:15
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
Definition half.hpp:26
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)