Horizon
diffmax_t.hpp
Go to the documentation of this file.
1 // 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 
23 #include <range/v3/range_fwd.hpp>
24 
26 
27 #include <range/v3/detail/prologue.hpp>
28 
29 RANGES_DIAGNOSTIC_PUSH
30 RANGES_DIAGNOSTIC_IGNORE_UNSIGNED_MATH
31 
32 namespace 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 
355 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
356 
357 namespace 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 
466 RANGES_DIAGNOSTIC_POP
467 
468 #include <range/v3/detail/epilogue.hpp>
469 
470 #endif
CPP_concept derived_from
\concept derived_from
Definition: concepts.hpp:904
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