HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
ranged_numeric.hpp
1// Copyright Take Vos 2020.
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 <limits>
8#include <ranges>
9#include "cast.hpp"
10
11namespace tt {
12
20template<typename T, T A, T B=A>
22public:
23 using value_type = T;
24 static constexpr int value_min = (B == A) ? 0 : A;
25 static constexpr int value_max = (B == A) ? A : B;
26
27 static_assert(value_min < value_max);
28
29 constexpr ranged_numeric() noexcept : value(value_min) {}
30 constexpr ranged_numeric(ranged_numeric const &rhs) noexcept = default;
31 constexpr ranged_numeric(ranged_numeric &&rhs) noexcept = default;
32 constexpr ranged_numeric &operator=(ranged_numeric const &rhs) noexcept = default;
33 constexpr ranged_numeric &operator=(ranged_numeric &&rhs) noexcept = default;
34
35 constexpr explicit operator value_type () noexcept
36 {
37 return value;
38 }
39
40 [[nodiscard]] constexpr ranged_numeric(signed long long rhs) noexcept : value(narrow_cast<T>(rhs))
41 {
42 tt_axiom(value >= value_min && value < value_max);
43 }
44
45 [[nodiscard]] constexpr ranged_numeric(unsigned long long rhs) noexcept : value(narrow_cast<T>(rhs))
46 {
47 tt_axiom(value >= value_min && value < value_max);
48 }
49
50 [[nodiscard]] constexpr ranged_numeric(signed long rhs) noexcept : value(narrow_cast<T>(rhs))
51 {
52 tt_axiom(value >= value_min && value < value_max);
53 }
54
55 [[nodiscard]] constexpr ranged_numeric(unsigned long rhs) noexcept : value(narrow_cast<T>(rhs))
56 {
57 tt_axiom(value >= value_min && value < value_max);
58 }
59
60 [[nodiscard]] constexpr ranged_numeric(signed int rhs) noexcept : value(narrow_cast<T>(rhs))
61 {
62 tt_axiom(value >= value_min && value < value_max);
63 }
64
65 [[nodiscard]] constexpr ranged_numeric(unsigned int rhs) noexcept : value(narrow_cast<T>(rhs))
66 {
67 tt_axiom(value >= value_min && value < value_max);
68 }
69
70 [[nodiscard]] constexpr ranged_numeric(signed short rhs) noexcept : value(narrow_cast<T>(rhs))
71 {
72 tt_axiom(value >= value_min && value < value_max);
73 }
74
75 [[nodiscard]] constexpr ranged_numeric(unsigned short rhs) noexcept : value(narrow_cast<T>(rhs))
76 {
77 tt_axiom(value >= value_min && value < value_max);
78 }
79
80 [[nodiscard]] constexpr ranged_numeric(signed char rhs) noexcept : value(narrow_cast<T>(rhs))
81 {
82 tt_axiom(value >= value_min && value < value_max);
83 }
84
85 [[nodiscard]] constexpr ranged_numeric(unsigned char rhs) noexcept : value(narrow_cast<T>(rhs))
86 {
87 tt_axiom(value >= value_min && value < value_max);
88 }
89
90 [[nodiscard]] constexpr ranged_numeric &operator++() noexcept
91 {
92 tt_axiom(value < value_max - 1);
93 ++value;
94 return *this;
95 }
96
97 [[nodiscard]] constexpr ranged_numeric &operator--() noexcept
98 {
99 tt_axiom(value > value_min);
100 --value;
101 return *this;
102 }
103
104 [[nodiscard]] friend bool operator==(ranged_numeric const &lhs, ranged_numeric const &rhs) noexcept
105 {
106 return lhs.value == rhs.value;
107 }
108
109 [[nodiscard]] friend bool operator!=(ranged_numeric const &lhs, ranged_numeric const &rhs) noexcept
110 {
111 return lhs.value != rhs.value;
112 }
113
114 [[nodiscard]] friend bool operator<(ranged_numeric const &lhs, ranged_numeric const &rhs) noexcept
115 {
116 return lhs.value < rhs.value;
117 }
118
119 [[nodiscard]] friend bool operator>(ranged_numeric const &lhs, ranged_numeric const &rhs) noexcept
120 {
121 return lhs.value > rhs.value;
122 }
123
124 [[nodiscard]] friend bool operator<=(ranged_numeric const &lhs, ranged_numeric const &rhs) noexcept
125 {
126 return lhs.value <= rhs.value;
127 }
128
129 [[nodiscard]] friend bool operator>=(ranged_numeric const &lhs, ranged_numeric const &rhs) noexcept
130 {
131 return lhs.value >= rhs.value;
132 }
133
134 [[nodiscard]] static constexpr auto range() noexcept
135 {
136 tt_assert(value_max - value_min < 10, "Don't use this until std::views::iota() is implemented");
137
139 r.reserve(value_max - value_min);
140 for (auto i = value_min; i != value_max; ++i) {
141 r.push_back(i);
142 }
143
144 return r;
145
146 //return
147 // std::views::iota(value_min, value_max) | std::views::transform([](auto &&x) {
148 // return ranged_numeric{x};
149 // });
150 }
151
152private:
153 int value;
154};
155
156template<int A, int B = A>
158
159}
160
161namespace std {
162
163template<typename T, int A, int B>
164class numeric_limits<tt::ranged_numeric<T,A,B>> {
165 static constexpr auto is_specialized = true;
166 static constexpr auto is_signed = std::numeric_limits<T>::is_signed;
167 static constexpr auto is_integer = std::numeric_limits<T>::is_integer;
168 static constexpr auto is_exact = std::numeric_limits<T>::is_exact;
169 static constexpr auto has_infinity = std::numeric_limits<T>::has_infinity;
170 static constexpr auto has_quiet_NaN = std::numeric_limits<T>::has_quiet_NaN;
171 static constexpr auto has_signaling_NaN = std::numeric_limits<T>::has_signaling_NaN;
172 static constexpr auto has_denorm = std::numeric_limits<T>::has_denorm;
173 static constexpr auto has_denorm_loss = std::numeric_limits<T>::has_denorm_loss;
174 static constexpr auto round_style = std::numeric_limits<T>::round_style;
175 static constexpr auto is_iec559 = std::numeric_limits<T>::is_iec559;
176 static constexpr auto is_bounded = std::numeric_limits<T>::is_bounded;
177 static constexpr auto is_modulo = std::numeric_limits<T>::is_modulo;
178 static constexpr auto digits = std::numeric_limits<T>::digits;
179 static constexpr auto digits10 = std::numeric_limits<T>::digits10;
180 static constexpr auto max_digits10 = std::numeric_limits<T>::max_digits10;
181 static constexpr auto radix = std::numeric_limits<T>::radix;
182 static constexpr auto min_exponent = std::numeric_limits<T>::min_exponent;
183 static constexpr auto min_exponent10 = std::numeric_limits<T>::min_exponent10;
184 static constexpr auto max_exponent = std::numeric_limits<T>::max_exponent;
185 static constexpr auto max_exponent10 = std::numeric_limits<T>::max_exponent10;
186 static constexpr auto traps = std::numeric_limits<T>::traps;
187 static constexpr auto tinyness_before = std::numeric_limits<T>::tinyness_before;
188
189 static constexpr auto min() noexcept
190 {
191 if constexpr (is_floating_point_v<T> && tt::ranged_int<T, A, B>::value_min < std::numeric_limits<T>::min()) {
193 } else {
195 }
196 }
197
198 static constexpr auto lowest() noexcept
199 {
201 }
202
203 static constexpr auto max() noexcept
204 {
206 }
207
208 static constexpr auto epsilon() noexcept
209 {
211 }
212
213 static constexpr auto round_error() noexcept
214 {
216 }
217
218 static constexpr auto infinity() noexcept
219 {
221 }
222
223 static constexpr auto quiet_NaN() noexcept
224 {
226 }
227
228 static constexpr auto signaling_NaN() noexcept
229 {
231 }
232
233 static constexpr auto denorm_min() noexcept
234 {
235 if constexpr (is_floating_point_v<T> && tt::ranged_int<T, A, B>::value_min < std::numeric_limits<T>::denorm_min()) {
237 } else {
239 }
240 }
241};
242
243}
STL namespace.
A ranged integer.
Definition ranged_numeric.hpp:21
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 push_back(T... args)
T quiet_NaN(T... args)
T reserve(T... args)
T round_error(T... args)
T signaling_NaN(T... args)