File indexing completed on 2025-01-18 10:09:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_ITERATOR_DIFFMAX_T_HPP
0015 #define RANGES_V3_ITERATOR_DIFFMAX_T_HPP
0016
0017 #include <cstdint>
0018 #include <iosfwd>
0019 #include <limits>
0020
0021 #include <concepts/concepts.hpp>
0022
0023 #include <range/v3/range_fwd.hpp>
0024
0025 #include <range/v3/iterator/concepts.hpp>
0026
0027 #include <range/v3/detail/prologue.hpp>
0028
0029 RANGES_DIAGNOSTIC_PUSH
0030 RANGES_DIAGNOSTIC_IGNORE_UNSIGNED_MATH
0031
0032 namespace ranges
0033 {
0034
0035 namespace detail
0036 {
0037 struct diffmax_t
0038 {
0039 private:
0040 bool neg_;
0041 std::uintmax_t val_;
0042 struct tag
0043 {};
0044
0045 constexpr diffmax_t(tag, bool neg, std::uintmax_t val)
0046 : neg_(val && neg)
0047 , val_(val)
0048 {}
0049
0050
0051 constexpr void _check()
0052 {
0053 RANGES_ENSURE(!neg_ || val_);
0054 }
0055 static constexpr diffmax_t _normalize(bool neg, std::uintmax_t val)
0056 {
0057 return diffmax_t{tag{}, val && neg, val};
0058 }
0059
0060
0061 public:
0062 diffmax_t() = default;
0063
0064 template(typename T)(
0065 requires integral<T>)
0066 constexpr diffmax_t(T val) noexcept
0067 : neg_(0 > val)
0068 , val_(0 > val ? static_cast<std::uintmax_t>(-val)
0069 : static_cast<std::uintmax_t>(val))
0070 {}
0071
0072 friend constexpr bool operator<(diffmax_t a, diffmax_t b) noexcept
0073 {
0074 a._check();
0075 b._check();
0076 return a.neg_ ? (b.neg_ ? a.val_ > b.val_ : true)
0077 : (b.neg_ ? false : a.val_ < b.val_);
0078 }
0079 friend constexpr bool operator>(diffmax_t a, diffmax_t b) noexcept
0080 {
0081 return b < a;
0082 }
0083 friend constexpr bool operator<=(diffmax_t a, diffmax_t b) noexcept
0084 {
0085 return !(b < a);
0086 }
0087 friend constexpr bool operator>=(diffmax_t a, diffmax_t b) noexcept
0088 {
0089 return !(a < b);
0090 }
0091 friend constexpr bool operator==(diffmax_t a, diffmax_t b) noexcept
0092 {
0093 a._check();
0094 b._check();
0095 return a.val_ == b.val_ && a.neg_ == b.neg_;
0096 }
0097 friend constexpr bool operator!=(diffmax_t a, diffmax_t b) noexcept
0098 {
0099 return !(a == b);
0100 }
0101
0102 friend constexpr diffmax_t operator+(diffmax_t a) noexcept
0103 {
0104 return a;
0105 }
0106 friend constexpr diffmax_t operator-(diffmax_t a) noexcept
0107 {
0108 return _normalize(!a.neg_, a.val_);
0109 }
0110
0111 friend constexpr diffmax_t operator+(diffmax_t a, diffmax_t b) noexcept
0112 {
0113 return a.neg_ == b.neg_
0114 ? diffmax_t{tag{}, a.neg_, a.val_ + b.val_}
0115 : (a.neg_ ? (a.val_ > b.val_
0116 ? diffmax_t{tag{}, true, a.val_ - b.val_}
0117 : diffmax_t{tag{}, false, b.val_ - a.val_})
0118 : (b.val_ > a.val_
0119 ? diffmax_t{tag{}, true, b.val_ - a.val_}
0120 : diffmax_t{tag{}, false, a.val_ - b.val_}));
0121 }
0122 friend constexpr diffmax_t operator-(diffmax_t a, diffmax_t b) noexcept
0123 {
0124 return a + -b;
0125 }
0126 friend constexpr diffmax_t operator*(diffmax_t a, diffmax_t b) noexcept
0127 {
0128 return _normalize(a.neg_ ^ b.neg_, a.val_ * b.val_);
0129 }
0130 friend constexpr diffmax_t operator/(diffmax_t a, diffmax_t b) noexcept
0131 {
0132 return _normalize(a.neg_ ^ b.neg_, a.val_ / b.val_);
0133 }
0134 friend constexpr diffmax_t operator%(diffmax_t a, diffmax_t b) noexcept
0135 {
0136 return _normalize(a.neg_, a.val_ % b.val_);
0137 }
0138 static constexpr std::uintmax_t compl_if(bool neg,
0139 std::uintmax_t val) noexcept
0140 {
0141 return neg ? ~val + 1 : val;
0142 }
0143 friend constexpr diffmax_t operator&(diffmax_t a, diffmax_t b) noexcept
0144 {
0145 return _normalize(
0146 a.neg_ && b.neg_,
0147 compl_if(a.neg_ && b.neg_,
0148 compl_if(a.neg_, a.val_) & compl_if(b.neg_, b.val_)));
0149 }
0150 friend constexpr diffmax_t operator|(diffmax_t a, diffmax_t b) noexcept
0151 {
0152 return _normalize(
0153 a.neg_ || b.neg_,
0154 compl_if(a.neg_ || b.neg_,
0155 compl_if(a.neg_, a.val_) | compl_if(b.neg_, b.val_)));
0156 }
0157 friend constexpr diffmax_t operator^(diffmax_t a, diffmax_t b) noexcept
0158 {
0159 return _normalize(
0160 bool(a.neg_ ^ b.neg_),
0161 compl_if(bool(a.neg_ ^ b.neg_),
0162 compl_if(a.neg_, a.val_) ^ compl_if(b.neg_, b.val_)));
0163 }
0164
0165 friend constexpr diffmax_t operator<<(diffmax_t a, diffmax_t b) noexcept
0166 {
0167 RANGES_ENSURE(!a.neg_);
0168 return b.neg_ ? diffmax_t{tag{}, false, a.val_ >> b.val_}
0169 : diffmax_t{tag{}, false, a.val_ << b.val_};
0170 }
0171 friend constexpr diffmax_t operator>>(diffmax_t a, diffmax_t b) noexcept
0172 {
0173 return b.neg_ ? diffmax_t{tag{}, a.neg_, a.val_ << b.val_}
0174 : diffmax_t{tag{}, a.neg_, a.val_ >> b.val_};
0175 }
0176
0177 friend constexpr diffmax_t & operator+=(diffmax_t & a, diffmax_t b) noexcept
0178 {
0179 return (a = a + b);
0180 }
0181 friend constexpr diffmax_t & operator-=(diffmax_t & a, diffmax_t b) noexcept
0182 {
0183 return (a = a - b);
0184 }
0185 friend constexpr diffmax_t & operator*=(diffmax_t & a, diffmax_t b) noexcept
0186 {
0187 return (a = a * b);
0188 }
0189 friend constexpr diffmax_t & operator/=(diffmax_t & a, diffmax_t b) noexcept
0190 {
0191 return (a = a / b);
0192 }
0193 friend constexpr diffmax_t & operator%=(diffmax_t & a, diffmax_t b) noexcept
0194 {
0195 return (a = a % b);
0196 }
0197 friend constexpr diffmax_t & operator&=(diffmax_t & a, diffmax_t b) noexcept
0198 {
0199 return (a = a & b);
0200 }
0201 friend constexpr diffmax_t & operator|=(diffmax_t & a, diffmax_t b) noexcept
0202 {
0203 return (a = a | b);
0204 }
0205 friend constexpr diffmax_t & operator^=(diffmax_t & a, diffmax_t b) noexcept
0206 {
0207 return (a = a ^ b);
0208 }
0209 friend constexpr diffmax_t & operator<<=(diffmax_t & a, diffmax_t b) noexcept
0210 {
0211 a = (a << b);
0212 return a;
0213 }
0214 friend constexpr diffmax_t & operator>>=(diffmax_t & a, diffmax_t b) noexcept
0215 {
0216 a = (a >> b);
0217 return a;
0218 }
0219
0220 template<typename T>
0221 friend constexpr auto operator+=(T & a, diffmax_t b) noexcept
0222 -> CPP_broken_friend_ret(T &)(
0223 requires integral<T>)
0224 {
0225 return (a = static_cast<T>(diffmax_t{a} + b));
0226 }
0227 template<typename T>
0228 friend constexpr auto operator-=(T & a, diffmax_t b) noexcept
0229 -> CPP_broken_friend_ret(T &)(
0230 requires integral<T>)
0231 {
0232 return (a = static_cast<T>(diffmax_t{a} - b));
0233 }
0234 template<typename T>
0235 friend constexpr auto operator*=(T & a, diffmax_t b) noexcept
0236 -> CPP_broken_friend_ret(T &)(
0237 requires integral<T>)
0238 {
0239 return (a = static_cast<T>(diffmax_t{a} * b));
0240 }
0241 template<typename T>
0242 friend constexpr auto operator/=(T & a, diffmax_t b) noexcept
0243 -> CPP_broken_friend_ret(T &)(
0244 requires integral<T>)
0245 {
0246 return (a = static_cast<T>(diffmax_t{a} / b));
0247 }
0248 template<typename T>
0249 friend constexpr auto operator%=(T & a, diffmax_t b) noexcept
0250 -> CPP_broken_friend_ret(T &)(
0251 requires integral<T>)
0252 {
0253 return (a = static_cast<T>(diffmax_t{a} % b));
0254 }
0255 template<typename T>
0256 friend constexpr auto operator&=(T & a, diffmax_t b) noexcept
0257 -> CPP_broken_friend_ret(T &)(
0258 requires integral<T>)
0259 {
0260 return (a = static_cast<T>(diffmax_t{a} & b));
0261 }
0262 template<typename T>
0263 friend constexpr auto operator|=(T & a, diffmax_t b) noexcept
0264 -> CPP_broken_friend_ret(T &)(
0265 requires integral<T>)
0266 {
0267 return (a = static_cast<T>(diffmax_t{a} | b));
0268 }
0269 template<typename T>
0270 friend constexpr auto operator^=(T & a, diffmax_t b) noexcept
0271 -> CPP_broken_friend_ret(T &)(
0272 requires integral<T>)
0273 {
0274 return (a = static_cast<T>(diffmax_t{a} ^ b));
0275 }
0276 template<typename T>
0277 friend constexpr auto operator<<=(T & a, diffmax_t b) noexcept
0278 -> CPP_broken_friend_ret(T &)(
0279 requires integral<T>)
0280 {
0281 a = static_cast<T>(diffmax_t{a} << b);
0282 return a;
0283 }
0284 template<typename T>
0285 friend constexpr auto operator>>=(T & a, diffmax_t b) noexcept
0286 -> CPP_broken_friend_ret(T &)(
0287 requires integral<T>)
0288 {
0289 a = static_cast<T>(diffmax_t{a} >> b);
0290 return a;
0291 }
0292
0293 friend constexpr diffmax_t & operator++(diffmax_t & a) noexcept
0294 {
0295 a.neg_ = (a.neg_ ? --a.val_ : ++a.val_) && a.neg_;
0296 return a;
0297 }
0298 friend constexpr diffmax_t & operator--(diffmax_t & a) noexcept
0299 {
0300 a.neg_ = (a.neg_ ? ++a.val_ : --a.val_) && a.neg_;
0301 return a;
0302 }
0303 friend constexpr diffmax_t operator++(diffmax_t & a, int) noexcept
0304 {
0305 auto tmp = a;
0306 ++a;
0307 return tmp;
0308 }
0309 friend constexpr diffmax_t operator--(diffmax_t & a, int) noexcept
0310 {
0311 auto tmp = a;
0312 --a;
0313 return tmp;
0314 }
0315
0316 template(typename T)(
0317 requires integral<T>)
0318 constexpr explicit
0319 operator T() const noexcept
0320 {
0321 return neg_ ? -static_cast<T>(val_) : static_cast<T>(val_);
0322 }
0323 constexpr explicit operator bool() const noexcept
0324 {
0325 return val_ != 0;
0326 }
0327 constexpr bool operator!() const noexcept
0328 {
0329 return val_ == 0;
0330 }
0331
0332 template<typename Ostream>
0333 friend auto operator<<(Ostream & sout, diffmax_t a)
0334 -> CPP_broken_friend_ret(std::ostream &)(
0335 requires derived_from<
0336 Ostream, std::basic_ostream<typename Ostream::char_type,
0337 typename Ostream::traits_type>>)
0338 {
0339 return sout << (&"-"[!a.neg_]) << a.val_;
0340 }
0341 };
0342
0343 #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
0344 template<>
0345 inline constexpr bool _is_integer_like_<diffmax_t> = true;
0346 #else
0347 template<typename Enable>
0348 constexpr bool _is_integer_like_<diffmax_t, Enable> = true;
0349 #endif
0350 }
0351
0352 }
0353
0354
0355 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
0356
0357 namespace std
0358 {
0359 template<>
0360 struct numeric_limits<::ranges::detail::diffmax_t>
0361 {
0362 static constexpr bool is_specialized = true;
0363 static constexpr bool is_signed = true;
0364 static constexpr bool is_integer = true;
0365 static constexpr bool is_exact = true;
0366 static constexpr bool has_infinity = false;
0367 static constexpr bool has_quiet_NaN = false;
0368 static constexpr bool has_signaling_NaN = false;
0369 static constexpr bool has_denorm = false;
0370 static constexpr bool has_denorm_loss = false;
0371 static constexpr std::float_round_style round_style = std::round_toward_zero;
0372 static constexpr bool is_iec559 = false;
0373 static constexpr bool is_bounded = true;
0374 static constexpr bool is_modulo = false;
0375 static constexpr int digits = CHAR_BIT * sizeof(std::uintmax_t) + 1;
0376 static constexpr int digits10 =
0377 static_cast<int>(digits * 0.301029996);
0378 static constexpr int max_digits10 = 0;
0379 static constexpr int radix = 2;
0380 static constexpr int min_exponent = 0;
0381 static constexpr int min_exponent10 = 0;
0382 static constexpr int max_exponent = 0;
0383 static constexpr int max_exponent10 = 0;
0384 static constexpr bool traps = true;
0385 static constexpr bool tinyness_before = false;
0386
0387 static constexpr ::ranges::detail::diffmax_t max() noexcept
0388 {
0389 return std::uintmax_t(-1);
0390 }
0391 static constexpr ::ranges::detail::diffmax_t min() noexcept
0392 {
0393 return -max();
0394 }
0395 static constexpr ::ranges::detail::diffmax_t lowest() noexcept
0396 {
0397 return min();
0398 }
0399 static constexpr ::ranges::detail::diffmax_t epsilon() noexcept
0400 {
0401 return 0;
0402 }
0403 static constexpr ::ranges::detail::diffmax_t round_error() noexcept
0404 {
0405 return 0;
0406 }
0407 static constexpr ::ranges::detail::diffmax_t infinity() noexcept
0408 {
0409 return 0;
0410 }
0411 static constexpr ::ranges::detail::diffmax_t quiet_NaN() noexcept
0412 {
0413 return 0;
0414 }
0415 static constexpr ::ranges::detail::diffmax_t signaling_NaN() noexcept
0416 {
0417 return 0;
0418 }
0419 static constexpr ::ranges::detail::diffmax_t denorm_min() noexcept
0420 {
0421 return 0;
0422 }
0423 };
0424 template<>
0425 struct numeric_limits<::ranges::detail::diffmax_t const>
0426 : numeric_limits<::ranges::detail::diffmax_t>
0427 {};
0428 template<>
0429 struct numeric_limits<::ranges::detail::diffmax_t volatile>
0430 : numeric_limits<::ranges::detail::diffmax_t>
0431 {};
0432 template<>
0433 struct numeric_limits<::ranges::detail::diffmax_t const volatile>
0434 : numeric_limits<::ranges::detail::diffmax_t>
0435 {};
0436
0437 #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
0438 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_specialized;
0439 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_signed;
0440 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_integer;
0441 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_exact;
0442 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_infinity;
0443 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_quiet_NaN;
0444 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_signaling_NaN;
0445 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_denorm;
0446 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::has_denorm_loss;
0447 inline constexpr std::float_round_style
0448 numeric_limits<::ranges::detail::diffmax_t>::round_style;
0449 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_iec559;
0450 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_bounded;
0451 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_modulo;
0452 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::digits;
0453 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::digits10;
0454 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::max_digits10;
0455 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::radix;
0456 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::min_exponent;
0457 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::min_exponent10;
0458 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::max_exponent;
0459 inline constexpr int numeric_limits<::ranges::detail::diffmax_t>::max_exponent10;
0460 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::traps;
0461 inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::tinyness_before;
0462 #endif
0463 }
0464
0465
0466 RANGES_DIAGNOSTIC_POP
0467
0468 #include <range/v3/detail/epilogue.hpp>
0469
0470 #endif