Horizon
Loading...
Searching...
No Matches
diffmax_t.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2019-present
5//
6// Use, modification and distribution is subject to the
7// Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// Project home: https://github.com/ericniebler/range-v3
12//
13
14#ifndef RANGES_V3_ITERATOR_DIFFMAX_T_HPP
15#define RANGES_V3_ITERATOR_DIFFMAX_T_HPP
16
17#include <cstdint>
18#include <iosfwd>
19#include <limits>
20
21#include <concepts/concepts.hpp>
22
24
26
27#include <range/v3/detail/prologue.hpp>
28
29RANGES_DIAGNOSTIC_PUSH
30RANGES_DIAGNOSTIC_IGNORE_UNSIGNED_MATH
31
32namespace ranges
33{
35 namespace detail
36 {
37 struct diffmax_t
38 {
39 private:
40 bool neg_;
41 std::uintmax_t val_;
42 struct tag
43 {};
44
45 constexpr diffmax_t(tag, bool neg, std::uintmax_t val)
46 : neg_(val && neg)
47 , val_(val)
48 {}
49
51 constexpr void _check()
52 {
53 RANGES_ENSURE(!neg_ || val_);
54 }
55 static constexpr diffmax_t _normalize(bool neg, std::uintmax_t val)
56 {
57 return diffmax_t{tag{}, val && neg, val};
58 }
60
61 public:
62 diffmax_t() = default;
63
64 template(typename T)(
65 requires integral<T>)
66 constexpr diffmax_t(T val) noexcept
67 : neg_(0 > val)
68 , val_(0 > val ? static_cast<std::uintmax_t>(-val)
69 : static_cast<std::uintmax_t>(val))
70 {}
71
72 friend constexpr bool operator<(diffmax_t a, diffmax_t b) noexcept
73 {
74 a._check();
75 b._check();
76 return a.neg_ ? (b.neg_ ? a.val_ > b.val_ : true)
77 : (b.neg_ ? false : a.val_ < b.val_);
78 }
79 friend constexpr bool operator>(diffmax_t a, diffmax_t b) noexcept
80 {
81 return b < a;
82 }
83 friend constexpr bool operator<=(diffmax_t a, diffmax_t b) noexcept
84 {
85 return !(b < a);
86 }
87 friend constexpr bool operator>=(diffmax_t a, diffmax_t b) noexcept
88 {
89 return !(a < b);
90 }
91 friend constexpr bool operator==(diffmax_t a, diffmax_t b) noexcept
92 {
93 a._check();
94 b._check();
95 return a.val_ == b.val_ && a.neg_ == b.neg_;
96 }
97 friend constexpr bool operator!=(diffmax_t a, diffmax_t b) noexcept
98 {
99 return !(a == b);
100 }
101
102 friend constexpr diffmax_t operator+(diffmax_t a) noexcept
103 {
104 return a;
105 }
106 friend constexpr diffmax_t operator-(diffmax_t a) noexcept
107 {
108 return _normalize(!a.neg_, a.val_);
109 }
110
111 friend constexpr diffmax_t operator+(diffmax_t a, diffmax_t b) noexcept
112 {
113 return a.neg_ == b.neg_
114 ? diffmax_t{tag{}, a.neg_, a.val_ + b.val_}
115 : (a.neg_ ? (a.val_ > b.val_
116 ? diffmax_t{tag{}, true, a.val_ - b.val_}
117 : diffmax_t{tag{}, false, b.val_ - a.val_})
118 : (b.val_ > a.val_
119 ? diffmax_t{tag{}, true, b.val_ - a.val_}
120 : diffmax_t{tag{}, false, a.val_ - b.val_}));
121 }
122 friend constexpr diffmax_t operator-(diffmax_t a, diffmax_t b) noexcept
123 {
124 return a + -b;
125 }
126 friend constexpr diffmax_t operator*(diffmax_t a, diffmax_t b) noexcept
127 {
128 return _normalize(a.neg_ ^ b.neg_, a.val_ * b.val_);
129 }
130 friend constexpr diffmax_t operator/(diffmax_t a, diffmax_t b) noexcept
131 {
132 return _normalize(a.neg_ ^ b.neg_, a.val_ / b.val_);
133 }
134 friend constexpr diffmax_t operator%(diffmax_t a, diffmax_t b) noexcept
135 {
136 return _normalize(a.neg_, a.val_ % b.val_);
137 }
138 static constexpr std::uintmax_t compl_if(bool neg,
139 std::uintmax_t val) noexcept
140 {
141 return neg ? ~val + 1 : val;
142 }
143 friend constexpr diffmax_t operator&(diffmax_t a, diffmax_t b) noexcept
144 {
145 return _normalize(
146 a.neg_ && b.neg_,
147 compl_if(a.neg_ && b.neg_,
148 compl_if(a.neg_, a.val_) & compl_if(b.neg_, b.val_)));
149 }
150 friend constexpr diffmax_t operator|(diffmax_t a, diffmax_t b) noexcept
151 {
152 return _normalize(
153 a.neg_ || b.neg_,
154 compl_if(a.neg_ || b.neg_,
155 compl_if(a.neg_, a.val_) | compl_if(b.neg_, b.val_)));
156 }
157 friend constexpr diffmax_t operator^(diffmax_t a, diffmax_t b) noexcept
158 {
159 return _normalize(
160 bool(a.neg_ ^ b.neg_),
161 compl_if(bool(a.neg_ ^ b.neg_),
162 compl_if(a.neg_, a.val_) ^ compl_if(b.neg_, b.val_)));
163 }
164
165 friend constexpr diffmax_t operator<<(diffmax_t a, diffmax_t b) noexcept
166 {
167 RANGES_ENSURE(!a.neg_);
168 return b.neg_ ? diffmax_t{tag{}, false, a.val_ >> b.val_}
169 : diffmax_t{tag{}, false, a.val_ << b.val_};
170 }
171 friend constexpr diffmax_t operator>>(diffmax_t a, diffmax_t b) noexcept
172 {
173 return b.neg_ ? diffmax_t{tag{}, a.neg_, a.val_ << b.val_}
174 : diffmax_t{tag{}, a.neg_, a.val_ >> b.val_};
175 }
176
177 friend constexpr diffmax_t & operator+=(diffmax_t & a, diffmax_t b) noexcept
178 {
179 return (a = a + b);
180 }
181 friend constexpr diffmax_t & operator-=(diffmax_t & a, diffmax_t b) noexcept
182 {
183 return (a = a - b);
184 }
185 friend constexpr diffmax_t & operator*=(diffmax_t & a, diffmax_t b) noexcept
186 {
187 return (a = a * b);
188 }
189 friend constexpr diffmax_t & operator/=(diffmax_t & a, diffmax_t b) noexcept
190 {
191 return (a = a / b);
192 }
193 friend constexpr diffmax_t & operator%=(diffmax_t & a, diffmax_t b) noexcept
194 {
195 return (a = a % b);
196 }
197 friend constexpr diffmax_t & operator&=(diffmax_t & a, diffmax_t b) noexcept
198 {
199 return (a = a & b);
200 }
201 friend constexpr diffmax_t & operator|=(diffmax_t & a, diffmax_t b) noexcept
202 {
203 return (a = a | b);
204 }
205 friend constexpr diffmax_t & operator^=(diffmax_t & a, diffmax_t b) noexcept
206 {
207 return (a = a ^ b);
208 }
209 friend constexpr diffmax_t & operator<<=(diffmax_t & a, diffmax_t b) noexcept
210 {
211 a = (a << b);
212 return a;
213 }
214 friend constexpr diffmax_t & operator>>=(diffmax_t & a, diffmax_t b) noexcept
215 {
216 a = (a >> b);
217 return a;
218 }
219
220 template<typename T>
221 friend constexpr auto operator+=(T & a, diffmax_t b) noexcept
222 -> CPP_broken_friend_ret(T &)(
223 requires integral<T>)
224 {
225 return (a = static_cast<T>(diffmax_t{a} + b));
226 }
227 template<typename T>
228 friend constexpr auto operator-=(T & a, diffmax_t b) noexcept
229 -> CPP_broken_friend_ret(T &)(
230 requires integral<T>)
231 {
232 return (a = static_cast<T>(diffmax_t{a} - b));
233 }
234 template<typename T>
235 friend constexpr auto operator*=(T & a, diffmax_t b) noexcept
236 -> CPP_broken_friend_ret(T &)(
237 requires integral<T>)
238 {
239 return (a = static_cast<T>(diffmax_t{a} * b));
240 }
241 template<typename T>
242 friend constexpr auto operator/=(T & a, diffmax_t b) noexcept
243 -> CPP_broken_friend_ret(T &)(
244 requires integral<T>)
245 {
246 return (a = static_cast<T>(diffmax_t{a} / b));
247 }
248 template<typename T>
249 friend constexpr auto operator%=(T & a, diffmax_t b) noexcept
250 -> CPP_broken_friend_ret(T &)(
251 requires integral<T>)
252 {
253 return (a = static_cast<T>(diffmax_t{a} % b));
254 }
255 template<typename T>
256 friend constexpr auto operator&=(T & a, diffmax_t b) noexcept
257 -> CPP_broken_friend_ret(T &)(
258 requires integral<T>)
259 {
260 return (a = static_cast<T>(diffmax_t{a} & b));
261 }
262 template<typename T>
263 friend constexpr auto operator|=(T & a, diffmax_t b) noexcept
264 -> CPP_broken_friend_ret(T &)(
265 requires integral<T>)
266 {
267 return (a = static_cast<T>(diffmax_t{a} | b));
268 }
269 template<typename T>
270 friend constexpr auto operator^=(T & a, diffmax_t b) noexcept
271 -> CPP_broken_friend_ret(T &)(
272 requires integral<T>)
273 {
274 return (a = static_cast<T>(diffmax_t{a} ^ b));
275 }
276 template<typename T>
277 friend constexpr auto operator<<=(T & a, diffmax_t b) noexcept
278 -> CPP_broken_friend_ret(T &)(
279 requires integral<T>)
280 {
281 a = static_cast<T>(diffmax_t{a} << b);
282 return a;
283 }
284 template<typename T>
285 friend constexpr auto operator>>=(T & a, diffmax_t b) noexcept
286 -> CPP_broken_friend_ret(T &)(
287 requires integral<T>)
288 {
289 a = static_cast<T>(diffmax_t{a} >> b);
290 return a;
291 }
292
293 friend constexpr diffmax_t & operator++(diffmax_t & a) noexcept
294 {
295 a.neg_ = (a.neg_ ? --a.val_ : ++a.val_) && a.neg_;
296 return a;
297 }
298 friend constexpr diffmax_t & operator--(diffmax_t & a) noexcept
299 {
300 a.neg_ = (a.neg_ ? ++a.val_ : --a.val_) && a.neg_;
301 return a;
302 }
303 friend constexpr diffmax_t operator++(diffmax_t & a, int) noexcept
304 {
305 auto tmp = a;
306 ++a;
307 return tmp;
308 }
309 friend constexpr diffmax_t operator--(diffmax_t & a, int) noexcept
310 {
311 auto tmp = a;
312 --a;
313 return tmp;
314 }
315
316 template(typename T)(
317 requires integral<T>)
318 constexpr explicit
319 operator T() const noexcept
320 {
321 return neg_ ? -static_cast<T>(val_) : static_cast<T>(val_);
322 }
323 constexpr explicit operator bool() const noexcept
324 {
325 return val_ != 0;
326 }
327 constexpr bool operator!() const noexcept
328 {
329 return val_ == 0;
330 }
331
332 template<typename Ostream>
333 friend auto operator<<(Ostream & sout, diffmax_t a)
334 -> CPP_broken_friend_ret(std::ostream &)(
335 requires derived_from<
336 Ostream, std::basic_ostream<typename Ostream::char_type,
337 typename Ostream::traits_type>>)
338 {
339 return sout << (&"-"[!a.neg_]) << a.val_;
340 }
341 };
342
343#if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
344 template<>
345 inline constexpr bool _is_integer_like_<diffmax_t> = true;
346#else
347 template<typename Enable>
348 constexpr bool _is_integer_like_<diffmax_t, Enable> = true;
349#endif
350 } // namespace detail
352} // namespace ranges
353
355RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
356
357namespace std
358{
359 template<>
360 struct numeric_limits<::ranges::detail::diffmax_t>
361 {
362 static constexpr bool is_specialized = true;
363 static constexpr bool is_signed = true;
364 static constexpr bool is_integer = true;
365 static constexpr bool is_exact = true;
366 static constexpr bool has_infinity = false;
367 static constexpr bool has_quiet_NaN = false;
368 static constexpr bool has_signaling_NaN = false;
369 static constexpr bool has_denorm = false;
370 static constexpr bool has_denorm_loss = false;
371 static constexpr std::float_round_style round_style = std::round_toward_zero;
372 static constexpr bool is_iec559 = false;
373 static constexpr bool is_bounded = true;
374 static constexpr bool is_modulo = false;
375 static constexpr int digits = CHAR_BIT * sizeof(std::uintmax_t) + 1;
376 static constexpr int digits10 =
377 static_cast<int>(digits * 0.301029996); // digits * std::log10(2)
378 static constexpr int max_digits10 = 0;
379 static constexpr int radix = 2;
380 static constexpr int min_exponent = 0;
381 static constexpr int min_exponent10 = 0;
382 static constexpr int max_exponent = 0;
383 static constexpr int max_exponent10 = 0;
384 static constexpr bool traps = true;
385 static constexpr bool tinyness_before = false;
386
387 static constexpr ::ranges::detail::diffmax_t max() noexcept
388 {
389 return std::uintmax_t(-1);
390 }
391 static constexpr ::ranges::detail::diffmax_t min() noexcept
392 {
393 return -max();
394 }
395 static constexpr ::ranges::detail::diffmax_t lowest() noexcept
396 {
397 return min();
398 }
399 static constexpr ::ranges::detail::diffmax_t epsilon() noexcept
400 {
401 return 0;
402 }
403 static constexpr ::ranges::detail::diffmax_t round_error() noexcept
404 {
405 return 0;
406 }
407 static constexpr ::ranges::detail::diffmax_t infinity() noexcept
408 {
409 return 0;
410 }
411 static constexpr ::ranges::detail::diffmax_t quiet_NaN() noexcept
412 {
413 return 0;
414 }
415 static constexpr ::ranges::detail::diffmax_t signaling_NaN() noexcept
416 {
417 return 0;
418 }
419 static constexpr ::ranges::detail::diffmax_t denorm_min() noexcept
420 {
421 return 0;
422 }
423 };
424 template<>
425 struct numeric_limits<::ranges::detail::diffmax_t const>
426 : numeric_limits<::ranges::detail::diffmax_t>
427 {};
428 template<>
429 struct numeric_limits<::ranges::detail::diffmax_t volatile>
430 : numeric_limits<::ranges::detail::diffmax_t>
431 {};
432 template<>
433 struct numeric_limits<::ranges::detail::diffmax_t const volatile>
434 : numeric_limits<::ranges::detail::diffmax_t>
435 {};
436
437#if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
438 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_specialized;
439 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_signed;
440 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_integer;
441 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_exact;
442 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_infinity;
443 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_quiet_NaN;
444 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_signaling_NaN;
445 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_denorm;
446 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_denorm_loss;
447 inline constexpr std::float_round_style
448 numeric_limits<::ranges::detail::diffmax_t>::round_style;
449 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_iec559;
450 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_bounded;
451 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_modulo;
452 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::digits;
453 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::digits10;
454 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::max_digits10;
455 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::radix;
456 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::min_exponent;
457 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::min_exponent10;
458 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::max_exponent;
459 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::max_exponent10;
460 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::traps;
461 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::tinyness_before;
462#endif
463} // namespace std
465
466RANGES_DIAGNOSTIC_POP
467
468#include <range/v3/detail/epilogue.hpp>
469
470#endif
Point operator*(double s, const Point &a)
Multiply point by scalar.
Definition shapes.h:250
Point operator-(const Point &a, const Point &b)
Subtract two points_ component-wise.
Definition shapes.h:244