1 // <max_size_type.h> -*- C++ -*-
3 // Copyright (C) 2019-2024 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file bits/max_size_type.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{iterator}
30 #ifndef _GLIBCXX_MAX_SIZE_TYPE_H
31 #define _GLIBCXX_MAX_SIZE_TYPE_H 1
33 #pragma GCC system_header
35 #if __cplusplus > 201703L && __cpp_lib_concepts
36 #include <ext/numeric_traits.h>
39 // This header implements unsigned and signed integer-class types (as per
40 // [iterator.concept.winc]) that are one bit wider than the widest supported
43 // The set of integer types we consider includes __int128 and unsigned __int128
44 // (when they exist), even though they are really integer types only in GNU
45 // mode. This is to obtain a consistent ABI for these integer-class types
46 // across strict mode and GNU mode.
48 namespace std
_GLIBCXX_VISIBILITY(default)
50 _GLIBCXX_BEGIN_NAMESPACE_VERSION
52 template<typename _Tp
>
53 struct numeric_limits
;
62 __max_size_type() = default;
64 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
66 __max_size_type(_Tp __i
) noexcept
67 : _M_val(__i
), _M_msb(__i
< 0)
71 __max_size_type(const __max_diff_type
& __d
) noexcept
;
73 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
75 operator _Tp() const noexcept
79 operator bool() const noexcept
80 { return _M_val
!= 0 || _M_msb
!= 0; }
82 constexpr __max_size_type
83 operator+() const noexcept
86 constexpr __max_size_type
87 operator~() const noexcept
88 { return __max_size_type
{~_M_val
, !_M_msb
}; }
90 constexpr __max_size_type
91 operator-() const noexcept
92 { return operator~() + 1; }
94 constexpr __max_size_type
&
96 { return *this += 1; }
98 constexpr __max_size_type
99 operator++(int) noexcept
106 constexpr __max_size_type
&
107 operator--() noexcept
108 { return *this -= 1; }
110 constexpr __max_size_type
111 operator--(int) noexcept
118 constexpr __max_size_type
&
119 operator+=(const __max_size_type
& __r
) noexcept
121 const auto __sum
= _M_val
+ __r
._M_val
;
122 const bool __overflow
= (__sum
< _M_val
);
123 _M_msb
= _M_msb
^ __r
._M_msb
^ __overflow
;
128 constexpr __max_size_type
&
129 operator-=(const __max_size_type
& __r
) noexcept
130 { return *this += -__r
; }
132 constexpr __max_size_type
&
133 operator*=(__max_size_type __r
) noexcept
135 constexpr __max_size_type __threshold
136 = __rep(1) << (_S_rep_bits
/ 2 - 1);
137 if (_M_val
< __threshold
&& __r
< __threshold
)
138 // When both operands are below this threshold then the
139 // multiplication can be safely computed in the base precision.
140 _M_val
= _M_val
* __r
._M_val
;
143 // Otherwise, perform the multiplication in four steps, by
144 // decomposing the LHS and the RHS into 2*x+a and 2*y+b,
145 // respectively, and computing 4*x*y + 2*x*b + 2*y*a + a*b.
146 const bool __lsb
= _M_val
& 1;
147 const bool __rlsb
= __r
._M_val
& 1;
150 _M_val
= (2 * _M_val
* __r
._M_val
151 + _M_val
* __rlsb
+ __r
._M_val
* __lsb
);
153 *this += __rlsb
* __lsb
;
159 constexpr __max_size_type
&
160 operator/=(const __max_size_type
& __r
) noexcept
162 __glibcxx_assert(__r
!= 0);
164 if (!_M_msb
&& !__r
._M_msb
) [[likely
]]
165 _M_val
/= __r
._M_val
;
166 else if (_M_msb
&& __r
._M_msb
)
168 _M_val
= (_M_val
>= __r
._M_val
);
171 else if (!_M_msb
&& __r
._M_msb
)
173 else if (_M_msb
&& !__r
._M_msb
)
175 // The non-trivial case: the dividend has its MSB set and the
176 // divisor doesn't. In this case we compute ((LHS/2)/RHS)*2
177 // in the base precision. This quantity is either the true
178 // quotient or one less than the true quotient.
179 const auto __orig
= *this;
181 _M_val
/= __r
._M_val
;
183 if (__orig
- *this * __r
>= __r
)
189 constexpr __max_size_type
&
190 operator%=(const __max_size_type
& __r
) noexcept
192 if (!_M_msb
&& !__r
._M_msb
) [[likely
]]
193 _M_val
%= __r
._M_val
;
195 *this -= (*this / __r
) * __r
;
199 constexpr __max_size_type
&
200 operator<<=(const __max_size_type
& __r
) noexcept
202 __glibcxx_assert(__r
<= _S_rep_bits
);
205 _M_msb
= (_M_val
>> (_S_rep_bits
- __r
._M_val
)) & 1;
207 if (__r
._M_val
== _S_rep_bits
) [[unlikely
]]
210 _M_val
<<= __r
._M_val
;
215 constexpr __max_size_type
&
216 operator>>=(const __max_size_type
& __r
) noexcept
218 __glibcxx_assert(__r
<= _S_rep_bits
);
221 if (__r
._M_val
== _S_rep_bits
) [[unlikely
]]
224 _M_val
>>= __r
._M_val
;
226 if (_M_msb
) [[unlikely
]]
228 _M_val
|= __rep(1) << (_S_rep_bits
- __r
._M_val
);
235 constexpr __max_size_type
&
236 operator&=(const __max_size_type
& __r
) noexcept
238 _M_val
&= __r
._M_val
;
239 _M_msb
&= __r
._M_msb
;
243 constexpr __max_size_type
&
244 operator|=(const __max_size_type
& __r
) noexcept
246 _M_val
|= __r
._M_val
;
247 _M_msb
|= __r
._M_msb
;
251 constexpr __max_size_type
&
252 operator^=(const __max_size_type
& __r
) noexcept
254 _M_val
^= __r
._M_val
;
255 _M_msb
^= __r
._M_msb
;
259 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
260 friend constexpr _Tp
&
261 operator+=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
262 { return (__a
= static_cast<_Tp
>(__a
+ __b
)); }
264 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
265 friend constexpr _Tp
&
266 operator-=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
267 { return (__a
= static_cast<_Tp
>(__a
- __b
)); }
269 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
270 friend constexpr _Tp
&
271 operator*=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
272 { return (__a
= static_cast<_Tp
>(__a
* __b
)); }
274 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
275 friend constexpr _Tp
&
276 operator/=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
277 { return (__a
= static_cast<_Tp
>(__a
/ __b
)); }
279 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
280 friend constexpr _Tp
&
281 operator%=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
282 { return (__a
= static_cast<_Tp
>(__a
% __b
)); }
284 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
285 friend constexpr _Tp
&
286 operator&=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
287 { return (__a
= static_cast<_Tp
>(__a
& __b
)); }
289 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
290 friend constexpr _Tp
&
291 operator|=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
292 { return (__a
= static_cast<_Tp
>(__a
| __b
)); }
294 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
295 friend constexpr _Tp
&
296 operator^=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
297 { return (__a
= static_cast<_Tp
>(__a
^ __b
)); }
299 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
300 friend constexpr _Tp
&
301 operator<<=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
302 { return (__a
= static_cast<_Tp
>(__a
<< __b
)); }
304 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
305 friend constexpr _Tp
&
306 operator>>=(_Tp
& __a
, const __max_size_type
& __b
) noexcept
307 { return (__a
= static_cast<_Tp
>(__a
>> __b
)); }
309 friend constexpr __max_size_type
310 operator+(__max_size_type __l
, const __max_size_type
& __r
) noexcept
316 friend constexpr __max_size_type
317 operator-(__max_size_type __l
, const __max_size_type
& __r
) noexcept
323 friend constexpr __max_size_type
324 operator*(__max_size_type __l
, const __max_size_type
& __r
) noexcept
330 friend constexpr __max_size_type
331 operator/(__max_size_type __l
, const __max_size_type
& __r
) noexcept
337 friend constexpr __max_size_type
338 operator%(__max_size_type __l
, const __max_size_type
& __r
) noexcept
344 friend constexpr __max_size_type
345 operator<<(__max_size_type __l
, const __max_size_type
& __r
) noexcept
351 friend constexpr __max_size_type
352 operator>>(__max_size_type __l
, const __max_size_type
& __r
) noexcept
358 friend constexpr __max_size_type
359 operator&(__max_size_type __l
, const __max_size_type
& __r
) noexcept
365 friend constexpr __max_size_type
366 operator|(__max_size_type __l
, const __max_size_type
& __r
) noexcept
372 friend constexpr __max_size_type
373 operator^(__max_size_type __l
, const __max_size_type
& __r
) noexcept
379 friend constexpr bool
380 operator==(const __max_size_type
& __l
, const __max_size_type
& __r
) noexcept
381 { return __l
._M_val
== __r
._M_val
&& __l
._M_msb
== __r
._M_msb
; }
383 #if __cpp_lib_three_way_comparison
384 friend constexpr strong_ordering
385 operator<=>(const __max_size_type
& __l
, const __max_size_type
& __r
) noexcept
387 if (__l
._M_msb
^ __r
._M_msb
)
388 return __l
._M_msb
? strong_ordering::greater
: strong_ordering::less
;
390 return __l
._M_val
<=> __r
._M_val
;
393 friend constexpr bool
394 operator!=(const __max_size_type
& __l
, const __max_size_type
& __r
) noexcept
395 { return !(__l
== __r
); }
397 friend constexpr bool
398 operator<(const __max_size_type
& __l
, const __max_size_type
& __r
) noexcept
400 if (__l
._M_msb
== __r
._M_msb
)
401 return __l
._M_val
< __r
._M_val
;
406 friend constexpr bool
407 operator>(const __max_size_type
& __l
, const __max_size_type
& __r
) noexcept
408 { return __r
< __l
; }
410 friend constexpr bool
411 operator<=(const __max_size_type
& __l
, const __max_size_type
& __r
) noexcept
412 { return !(__l
> __r
); }
414 friend constexpr bool
415 operator>=(const __max_size_type
& __l
, const __max_size_type
& __r
) noexcept
416 { return __r
<= __l
; }
419 #if __SIZEOF_INT128__
421 using __rep
= unsigned __int128
;
423 using __rep
= unsigned long long;
425 static constexpr size_t _S_rep_bits
= sizeof(__rep
) * __CHAR_BIT__
;
428 unsigned _M_msb
:1 = 0;
431 __max_size_type(__rep __val
, int __msb
) noexcept
432 : _M_val(__val
), _M_msb(__msb
)
435 friend __max_diff_type
;
436 friend std::numeric_limits
<__max_size_type
>;
437 friend std::numeric_limits
<__max_diff_type
>;
440 class __max_diff_type
443 __max_diff_type() = default;
445 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
447 __max_diff_type(_Tp __i
) noexcept
452 __max_diff_type(const __max_size_type
& __d
) noexcept
456 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
458 operator _Tp() const noexcept
459 { return static_cast<_Tp
>(_M_rep
); }
462 operator bool() const noexcept
463 { return _M_rep
!= 0; }
465 constexpr __max_diff_type
466 operator+() const noexcept
469 constexpr __max_diff_type
470 operator-() const noexcept
471 { return __max_diff_type(-_M_rep
); }
473 constexpr __max_diff_type
474 operator~() const noexcept
475 { return __max_diff_type(~_M_rep
); }
477 constexpr __max_diff_type
&
478 operator++() noexcept
479 { return *this += 1; }
481 constexpr __max_diff_type
482 operator++(int) noexcept
489 constexpr __max_diff_type
&
490 operator--() noexcept
491 { return *this -= 1; }
493 constexpr __max_diff_type
494 operator--(int) noexcept
501 constexpr __max_diff_type
&
502 operator+=(const __max_diff_type
& __r
) noexcept
504 _M_rep
+= __r
._M_rep
;
508 constexpr __max_diff_type
&
509 operator-=(const __max_diff_type
& __r
) noexcept
511 _M_rep
-= __r
._M_rep
;
515 constexpr __max_diff_type
&
516 operator*=(const __max_diff_type
& __r
) noexcept
518 _M_rep
*= __r
._M_rep
;
522 constexpr __max_diff_type
&
523 operator/=(const __max_diff_type
& __r
) noexcept
525 __glibcxx_assert (__r
!= 0);
526 const bool __neg
= *this < 0;
527 const bool __rneg
= __r
< 0;
528 if (!__neg
&& !__rneg
)
529 _M_rep
= _M_rep
/ __r
._M_rep
;
530 else if (__neg
&& __rneg
)
531 _M_rep
= -_M_rep
/ -__r
._M_rep
;
532 else if (__neg
&& !__rneg
)
533 _M_rep
= -(-_M_rep
/ __r
._M_rep
);
535 _M_rep
= -(_M_rep
/ -__r
._M_rep
);
539 constexpr __max_diff_type
&
540 operator%=(const __max_diff_type
& __r
) noexcept
542 __glibcxx_assert (__r
!= 0);
543 if (*this >= 0 && __r
> 0)
544 _M_rep
%= __r
._M_rep
;
546 *this -= (*this / __r
) * __r
;
550 constexpr __max_diff_type
&
551 operator<<=(const __max_diff_type
& __r
) noexcept
553 _M_rep
.operator<<=(__r
._M_rep
);
557 constexpr __max_diff_type
&
558 operator>>=(const __max_diff_type
& __r
) noexcept
560 // Arithmetic right shift.
561 const auto __msb
= _M_rep
._M_msb
;
562 _M_rep
>>= __r
._M_rep
;
564 _M_rep
|= ~(__max_size_type(-1) >> __r
._M_rep
);
568 constexpr __max_diff_type
&
569 operator&=(const __max_diff_type
& __r
) noexcept
571 _M_rep
&= __r
._M_rep
;
575 constexpr __max_diff_type
&
576 operator|=(const __max_diff_type
& __r
) noexcept
578 _M_rep
|= __r
._M_rep
;
582 constexpr __max_diff_type
&
583 operator^=(const __max_diff_type
& __r
) noexcept
585 _M_rep
^= __r
._M_rep
;
589 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
590 friend constexpr _Tp
&
591 operator+=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
592 { return (__a
= static_cast<_Tp
>(__a
+ __b
)); }
594 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
595 friend constexpr _Tp
&
596 operator-=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
597 { return (__a
= static_cast<_Tp
>(__a
- __b
)); }
599 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
600 friend constexpr _Tp
&
601 operator*=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
602 { return (__a
= static_cast<_Tp
>(__a
* __b
)); }
604 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
605 friend constexpr _Tp
&
606 operator/=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
607 { return (__a
= static_cast<_Tp
>(__a
/ __b
)); }
609 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
610 friend constexpr _Tp
&
611 operator%=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
612 { return (__a
= static_cast<_Tp
>(__a
% __b
)); }
614 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
615 friend constexpr _Tp
&
616 operator&=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
617 { return (__a
= static_cast<_Tp
>(__a
& __b
)); }
619 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
620 friend constexpr _Tp
&
621 operator|=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
622 { return (__a
= static_cast<_Tp
>(__a
| __b
)); }
624 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
625 friend constexpr _Tp
&
626 operator^=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
627 { return (__a
= static_cast<_Tp
>(__a
^ __b
)); }
629 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
630 friend constexpr _Tp
&
631 operator<<=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
632 { return (__a
= static_cast<_Tp
>(__a
<< __b
)); }
634 template<typename _Tp
> requires integral
<_Tp
> || __is_int128
<_Tp
>
635 friend constexpr _Tp
&
636 operator>>=(_Tp
& __a
, const __max_diff_type
& __b
) noexcept
637 { return (__a
= static_cast<_Tp
>(__a
>> __b
)); }
639 friend constexpr __max_diff_type
640 operator+(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
646 friend constexpr __max_diff_type
647 operator-(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
653 friend constexpr __max_diff_type
654 operator*(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
660 friend constexpr __max_diff_type
661 operator/(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
667 friend constexpr __max_diff_type
668 operator%(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
674 friend constexpr __max_diff_type
675 operator<<(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
681 friend constexpr __max_diff_type
682 operator>>(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
688 friend constexpr __max_diff_type
689 operator&(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
695 friend constexpr __max_diff_type
696 operator|(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
702 friend constexpr __max_diff_type
703 operator^(__max_diff_type __l
, const __max_diff_type
& __r
) noexcept
709 friend constexpr bool
710 operator==(const __max_diff_type
& __l
, const __max_diff_type
& __r
) noexcept
711 { return __l
._M_rep
== __r
._M_rep
; }
713 #if __cpp_lib_three_way_comparison
714 constexpr strong_ordering
715 operator<=>(const __max_diff_type
& __r
) const noexcept
717 const auto __lsign
= _M_rep
._M_msb
;
718 const auto __rsign
= __r
._M_rep
._M_msb
;
719 if (__lsign
^ __rsign
)
720 return __lsign
? strong_ordering::less
: strong_ordering::greater
;
722 return _M_rep
<=> __r
._M_rep
;
725 friend constexpr bool
726 operator!=(const __max_diff_type
& __l
, const __max_diff_type
& __r
) noexcept
727 { return !(__l
== __r
); }
730 operator<(const __max_diff_type
& __r
) const noexcept
732 const auto __lsign
= _M_rep
._M_msb
;
733 const auto __rsign
= __r
._M_rep
._M_msb
;
734 if (__lsign
^ __rsign
)
737 return _M_rep
< __r
._M_rep
;
740 friend constexpr bool
741 operator>(const __max_diff_type
& __l
, const __max_diff_type
& __r
) noexcept
742 { return __r
< __l
; }
744 friend constexpr bool
745 operator<=(const __max_diff_type
& __l
, const __max_diff_type
& __r
) noexcept
746 { return !(__r
< __l
); }
748 friend constexpr bool
749 operator>=(const __max_diff_type
& __l
, const __max_diff_type
& __r
) noexcept
750 { return !(__l
< __r
); }
754 __max_size_type _M_rep
= 0;
756 friend class __max_size_type
;
760 __max_size_type::__max_size_type(const __max_diff_type
& __d
) noexcept
761 : __max_size_type(__d
._M_rep
)
764 } // namespace __detail
765 } // namespace ranges
768 struct numeric_limits
<ranges::__detail::__max_size_type
>
770 using _Sp
= ranges::__detail::__max_size_type
;
771 static constexpr bool is_specialized
= true;
772 static constexpr bool is_signed
= false;
773 static constexpr bool is_integer
= true;
774 static constexpr bool is_exact
= true;
775 static constexpr int digits
776 = __gnu_cxx::__int_traits
<_Sp::__rep
>::__digits
+ 1;
777 static constexpr int digits10
778 = static_cast<int>(digits
* numbers::ln2
/ numbers::ln10
);
786 { return _Sp(static_cast<_Sp::__rep
>(-1), 1); }
794 struct numeric_limits
<ranges::__detail::__max_diff_type
>
796 using _Dp
= ranges::__detail::__max_diff_type
;
797 using _Sp
= ranges::__detail::__max_size_type
;
798 static constexpr bool is_specialized
= true;
799 static constexpr bool is_signed
= true;
800 static constexpr bool is_integer
= true;
801 static constexpr bool is_exact
= true;
802 static constexpr int digits
= numeric_limits
<_Sp
>::digits
- 1;
803 static constexpr int digits10
804 = static_cast<int>(digits
* numbers::ln2
/ numbers::ln10
);
808 { return _Dp(_Sp(0, 1)); }
812 { return _Dp(_Sp(static_cast<_Sp::__rep
>(-1), 0)); }
819 _GLIBCXX_END_NAMESPACE_VERSION
822 #endif // C++20 && library concepts
823 #endif // _GLIBCXX_MAX_SIZE_TYPE_H