[gcc(refs/users/ppalka/heads/integer_class_type)] Finish the implementation of the integer-like class types
Patrick Palka
ppalka@gcc.gnu.org
Fri Jan 17 03:59:00 GMT 2020
https://gcc.gnu.org/g:2a3cc1279de019c67bf9f077db34dc89db23a02f
commit 2a3cc1279de019c67bf9f077db34dc89db23a02f
Author: Patrick Palka <ppalka@gcc.gnu.org>
Date: Thu Jan 16 10:49:48 2020 -0500
Finish the implementation of the integer-like class types
Diff:
---
libstdc++-v3/include/bits/iterator_concepts.h | 12 +-
libstdc++-v3/include/bits/range_access.h | 491 ++++++++++++---------
.../testsuite/std/ranges/iota/difference_type.cc | 132 ++++++
3 files changed, 428 insertions(+), 207 deletions(-)
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index c7d14f5..32cf02c 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -494,27 +494,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace ranges::__detail
{
-#ifdef _GLIBCXX_INTEGER_LIKE_TYPES
class __max_diff_type;
class __max_size_type;
-#elif __SIZEOF_INT128__
- using __max_diff_type = __int128;
- using __max_size_type = unsigned __int128;
-#else
- using __max_diff_type = long long;
- using __max_size_type = unsigned long long;
-#endif
template<typename _Tp>
concept __is_integer_like = integral<_Tp>
-#if defined _GLIBCXX_INTEGER_LIKE_TYPES && __SIZEOF_INT128__
+#if __SIZEOF_INT128__
|| same_as<_Tp, __int128> || same_as<_Tp, unsigned __int128>
#endif
|| same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>;
template<typename _Tp>
concept __is_signed_integer_like = signed_integral<_Tp>
-#if defined _GLIBCXX_INTEGER_LIKE_TYPES && __SIZEOF_INT128__
+#if __SIZEOF_INT128__
|| same_as<_Tp, __int128>
#endif
|| same_as<_Tp, __max_diff_type>;
diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index 82922a0..2adafc2 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -347,418 +347,517 @@ namespace ranges
namespace __detail
{
-#ifdef _GLIBCXX_INTEGER_LIKE_TYPES
- class __max_diff_type
+ class __max_size_type
{
public:
- __max_diff_type() = default;
+ __max_size_type() = default;
- template<signed_integral _Tp>
+ template<integral _Tp>
constexpr
- __max_diff_type(_Tp __i) noexcept
- : _M_val(__i < 0 ? rep(~__i) + rep(1) : __i), _M_sign_bit(__i < 0)
+ __max_size_type(_Tp __i) noexcept
+ : _M_val(__i), _M_msb(__i < 0)
{ }
- template<unsigned_integral _Tp>
- constexpr
- __max_diff_type(_Tp __i) noexcept
- : _M_val(__i), _M_sign_bit(false)
+ template<int __dummy = 0>
+ constexpr explicit
+ __max_size_type(const __max_diff_type& __d) noexcept
+ : __max_size_type(__d._M_rep)
{ }
- template<signed_integral _Tp>
- constexpr explicit operator _Tp() const noexcept
- {
- _Tp __val = _M_val % (sizeof(_Tp) * __CHAR_BIT__);
- if (_M_sign_bit)
- return -__val;
- else
- return __val;
- }
-
- template<unsigned_integral _Tp>
+ template<integral _Tp>
constexpr explicit operator _Tp() const noexcept
{ return _M_val; }
constexpr explicit
- operator bool() const noexcept { return _M_val != 0; }
+ operator bool() const noexcept { return _M_val != 0 || _M_msb != 0; }
- constexpr __max_diff_type
+ constexpr __max_size_type
operator+() const noexcept { return *this; }
- constexpr __max_diff_type
+ constexpr __max_size_type
+ operator~() const noexcept
+ { return __max_size_type{~_M_val, !_M_msb}; }
+
+ constexpr __max_size_type
operator-() const noexcept
- { return __max_diff_type{_M_val, !_M_sign_bit}; }
+ { return operator~() + 1; }
- constexpr __max_diff_type
- operator~() const noexcept
- { return __max_diff_type{~_M_val, !_M_sign_bit}; }
+ constexpr __max_size_type&
+ operator+=(const __max_size_type& __r) noexcept
+ {
+ const auto __sum = _M_val + __r._M_val;
+ const bool __overflow = (__sum < _M_val);
+ _M_msb = _M_msb ^ __r._M_msb ^ __overflow;
+ _M_val = __sum;
+ return *this;
+ }
- constexpr __max_diff_type&
- operator+=(const __max_diff_type& __r) noexcept
+ constexpr __max_size_type&
+ operator-=(const __max_size_type& __r) noexcept
+ { return *this += -__r; }
+
+ constexpr __max_size_type&
+ operator*=(const __max_size_type& __r) noexcept
{
- if (_M_sign_bit == __r._M_sign_bit)
- _M_val += __r._M_val;
- else if (_M_val >= __r._M_val)
- _M_val -= __r._M_val;
- else
+ const bool __lsb = _M_val % 2;
+ *this >>= 1;
+
+ auto __rcopy = __r;
+ const bool __rlsb = __rcopy._M_val % 2;
+ __rcopy >>= 1;
+
+ auto __res = 2 * _M_val * __rcopy._M_val;
+ __res += _M_val * __rlsb;
+ __res += __rcopy._M_val * __lsb;
+ _M_val = __res;
+ *this <<= 1;
+ *this += __rlsb * __lsb;
+
+ return *this;
+ }
+
+ constexpr __max_size_type&
+ operator/=(const __max_size_type& __r) noexcept
+ {
+ __glibcxx_assert(__r != 0);
+
+ if (_M_msb && __r._M_msb)
{
- _M_val = __r._M_val - _M_val;
- _M_sign_bit = !_M_sign_bit;
+ _M_val = (_M_val >= __r._M_val);
+ _M_msb = 0;
+ }
+ else if (!_M_msb && __r._M_msb)
+ _M_val = 0;
+ else if (!_M_msb && !__r._M_msb)
+ _M_val /= __r._M_val;
+ else if (_M_msb && !__r._M_msb)
+ {
+ const auto __orig = *this;
+ *this >>= 1;
+ _M_val /= __r._M_val;
+ *this <<= 1;
+ if (__orig - *this * __r >= __r)
+ _M_val++;
}
return *this;
}
- constexpr __max_diff_type&
- operator-=(const __max_diff_type& __r) noexcept
+ constexpr __max_size_type&
+ operator%=(const __max_size_type& __r) noexcept
{
- auto __rneg = __r;
- __rneg._M_sign_bit = !__r._M_sign_bit;
- return *this += __rneg;
+ *this = *this - (*this / __r) * __r;
+ return *this;
}
- constexpr __max_diff_type&
- operator*=(const __max_diff_type& __r) noexcept
+ constexpr __max_size_type&
+ operator<<=(const __max_size_type& __r) noexcept
{
- _M_val *= __r._M_val;
- _M_sign_bit = (_M_sign_bit != __r._M_sign_bit);
+ constexpr auto __digits = numeric_limits<__rep>::digits;
+ __glibcxx_assert(__r._M_val < __digits);
+ __glibcxx_assert(__r._M_msb == 0);
+ if (_M_val & (__rep(1) << __digits - __r._M_val))
+ _M_msb = 1;
+ else
+ _M_msb = 0;
+ _M_val <<= __r._M_val;
return *this;
}
- constexpr __max_diff_type&
- operator/=(const __max_diff_type& __r) noexcept
+ constexpr __max_size_type&
+ operator>>=(const __max_size_type& __r) noexcept
{
- _M_val /= __r._M_val;
- _M_sign_bit = (_M_sign_bit != __r._M_sign_bit);
+ constexpr auto __digits = numeric_limits<__rep>::digits;
+ __glibcxx_assert(__r._M_val < __digits);
+ __glibcxx_assert(__r._M_msb == 0);
+
+ _M_val >>= __r._M_val;
+ if (_M_msb && __r._M_val != 0)
+ {
+ _M_val |= __rep(1) << (__digits - __r._M_val);
+ _M_msb = 0;
+ }
+
return *this;
}
- constexpr __max_diff_type&
- operator%=(const __max_diff_type& __r) noexcept
+ constexpr __max_size_type&
+ operator&=(const __max_size_type& __r) noexcept
{
- _M_val /= __r._M_val;
+ _M_val &= __r._M_val;
+ _M_msb &= __r._M_msb;
return *this;
}
- constexpr __max_diff_type&
- operator<<=(const __max_diff_type& __r) noexcept
+ constexpr __max_size_type&
+ operator|=(const __max_size_type& __r) noexcept
{
- __glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
- __glibcxx_assert(!__r._M_sign_bit);
- _M_val <<= __r._M_val;
+ _M_val |= __r._M_val;
+ _M_msb |= __r._M_msb;
return *this;
}
- constexpr __max_diff_type&
- operator>>=(const __max_diff_type& __r) noexcept
+ constexpr __max_size_type&
+ operator^=(const __max_size_type& __r) noexcept
{
- __glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
- __glibcxx_assert(!__r._M_sign_bit);
- _M_val >>= __r._M_val;
+ _M_val ^= __r._M_val;
+ _M_msb ^= __r._M_msb;
return *this;
}
- friend constexpr __max_diff_type
- operator+(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ friend constexpr __max_size_type
+ operator+(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l += __r;
return __l;
}
- friend constexpr __max_diff_type
- operator-(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ friend constexpr __max_size_type
+ operator-(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l -= __r;
return __l;
}
- friend constexpr __max_diff_type
- operator*(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ friend constexpr __max_size_type
+ operator*(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l *= __r;
return __l;
}
- friend constexpr __max_diff_type
- operator/(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ friend constexpr __max_size_type
+ operator/(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l /= __r;
return __l;
}
- friend constexpr __max_diff_type
- operator%(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ friend constexpr __max_size_type
+ operator%(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l %= __r;
return __l;
}
- friend constexpr __max_diff_type
- operator<<(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ friend constexpr __max_size_type
+ operator<<(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l <<= __r;
return __l;
}
- friend constexpr __max_diff_type
- operator>>(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ friend constexpr __max_size_type
+ operator>>(__max_size_type __l, const __max_size_type& __r) noexcept
{
__l >>= __r;
return __l;
}
- // TODO & | ^
+ friend constexpr __max_size_type
+ operator&(__max_size_type __l, const __max_size_type& __r) noexcept
+ {
+ __l &= __r;
+ return __l;
+ }
- friend constexpr bool
- operator==(const __max_diff_type& __l, const __max_diff_type& __r)
- noexcept
+ friend constexpr __max_size_type
+ operator|(__max_size_type __l, const __max_size_type& __r) noexcept
{
- return __l._M_val == __r._M_val && __l._M_sign_bit == __r._M_sign_bit;
+ __l |= __r;
+ return __l;
+ }
+
+ friend constexpr __max_size_type
+ operator^(__max_size_type __l, const __max_size_type& __r) noexcept
+ {
+ __l ^= __r;
+ return __l;
}
friend constexpr bool
- operator!=(const __max_diff_type& __l, const __max_diff_type& __r)
+ operator==(const __max_size_type& __l, const __max_size_type& __r)
noexcept
- { return !(__l == __r); }
+ { return __l._M_val == __r._M_val && __l._M_msb == __r._M_msb; }
friend constexpr bool
- operator<(const __max_diff_type& __l, const __max_diff_type& __r)
+ operator!=(const __max_size_type& __l, const __max_size_type& __r)
noexcept
+ { return !(__l == __r); }
+
+ friend constexpr bool
+ operator<(const __max_size_type& __l, const __max_size_type& __r) noexcept
{
- if (__l._M_sign_bit)
- {
- if (__r._M_sign_bit)
- return __l._M_val > __r._M_val;
- else
- return true;
- }
- else if (__r._M_sign_bit)
- return false;
- return __l._M_val < __r._M_val;
+ if (__l._M_msb == __r._M_msb)
+ return __l._M_val < __r._M_val;
+ else
+ return __r._M_msb;
}
friend constexpr bool
- operator>(const __max_diff_type& __l, const __max_diff_type& __r)
- noexcept
+ operator>(const __max_size_type& __l, const __max_size_type& __r) noexcept
{ return __r < __l; }
friend constexpr bool
- operator<=(const __max_diff_type& __l, const __max_diff_type& __r)
- noexcept
- { return !(__r < __l); }
+ operator<=(const __max_size_type& __l, const __max_size_type& __r) noexcept
+ { return !(__l > __r); }
friend constexpr bool
- operator>=(const __max_diff_type& __l, const __max_diff_type& __r)
- noexcept
- { return !(__l < __r); }
+ operator>=(const __max_size_type& __l, const __max_size_type& __r) noexcept
+ { return __r <= __l; }
- private:
#ifdef __SIZEOF_INT128__
- using rep = unsigned __int128;
+ using __rep = unsigned __int128;
#else
- using rep = unsigned long long;
+ using __rep = unsigned long long;
#endif
- rep _M_val = 0;
- bool _M_sign_bit = false;
+ private:
+ __rep _M_val = 0;
+ unsigned _M_msb : 1 = 0;
constexpr explicit
- __max_diff_type(rep __val, bool __sb) noexcept
- : _M_val(__val), _M_sign_bit(__sb)
+ __max_size_type(__rep __val, int __msb) noexcept
+ : _M_val(__val), _M_msb(__msb)
{ }
- friend class __max_size_type;
+ friend class __max_diff_type;
};
- class __max_size_type
+ class __max_diff_type
{
public:
- __max_size_type() = default;
+ __max_diff_type() = default;
template<integral _Tp>
constexpr
- __max_size_type(_Tp __i) noexcept
- : _M_val(__i), _M_msb(0)
+ __max_diff_type(_Tp __i) noexcept
+ : _M_rep(__i)
{ }
constexpr explicit
- __max_size_type(const __max_diff_type& __d)
- : _M_val(__d._M_val), _M_msb(__d._M_sign_bit)
+ __max_diff_type(const __max_size_type& __d) noexcept
+ : _M_rep(__d)
{ }
template<integral _Tp>
constexpr explicit operator _Tp() const noexcept
- { return _M_val; }
+ { return static_cast<_Tp>(_M_rep); }
constexpr explicit
- operator bool() const noexcept { return _M_val != 0; }
+ operator bool() const noexcept { return _M_rep != 0; }
- constexpr __max_size_type
+ constexpr __max_diff_type
operator+() const noexcept { return *this; }
- constexpr __max_size_type
+ constexpr __max_diff_type
operator-() const noexcept
- { return __max_size_type{_M_val, !_M_sign_bit}; }
+ { return __max_diff_type(-_M_rep); }
- constexpr __max_size_type
+ constexpr __max_diff_type
operator~() const noexcept
- { return __max_size_type{~_M_val, !_M_sign_bit}; }
+ { return __max_diff_type(~_M_rep); }
- constexpr __max_size_type&
- operator+=(const __max_size_type& __r) noexcept
+ constexpr __max_diff_type&
+ operator+=(const __max_diff_type& __r) noexcept
{
- if (_M_sign_bit == __r._M_sign_bit)
- _M_val += __r._M_val;
- else if (_M_val >= __r._M_val)
- _M_val -= __r._M_val;
+ _M_rep += __r._M_rep;
+ return *this;
+ }
+
+ constexpr __max_diff_type&
+ operator-=(const __max_diff_type& __r) noexcept
+ {
+ _M_rep -= __r._M_rep;
+ return *this;
+ }
+
+ constexpr __max_diff_type&
+ operator*=(const __max_diff_type& __r) noexcept
+ {
+ _M_rep *= __r._M_rep;
+ return *this;
+ }
+
+ constexpr __max_diff_type&
+ operator/=(const __max_diff_type& __r) noexcept
+ {
+ const auto __neg = *this < 0;
+ const auto __rneg = __r < 0;
+ if (!__neg && !__rneg)
+ _M_rep = _M_rep / __r._M_rep;
+ else if (__neg && __rneg)
+ _M_rep = -_M_rep / -__r._M_rep;
else
{
- _M_val = __r._M_val - _M_val;
- _M_sign_bit = !_M_sign_bit;
+ auto __rcopy = __r;
+ if (__neg)
+ _M_rep = -_M_rep;
+ if (__rneg)
+ __rcopy = -__rcopy;
+ const auto __remainder = _M_rep % __rcopy._M_rep;
+ _M_rep = -(_M_rep / __rcopy._M_rep);
+ if (__remainder != 0)
+ _M_rep = _M_rep - 1;
}
return *this;
}
- constexpr __max_size_type&
- operator-=(const __max_size_type& __r) noexcept
+ constexpr __max_diff_type&
+ operator%=(const __max_diff_type& __r) noexcept
{
- auto __rneg = __r;
- __rneg._M_sign_bit = !__r._M_sign_bit;
- return *this += __rneg;
+ *this = *this - (*this / __r) * __r;
+ return *this;
}
- constexpr __max_size_type&
- operator*=(const __max_size_type& __r) noexcept
+ constexpr __max_diff_type&
+ operator<<=(const __max_diff_type& __r) noexcept
{
- _M_val *= __r._M_val;
- _M_sign_bit ^= __r._M_sign_bit;
+ _M_rep.operator<<=(__r._M_rep);
return *this;
}
- constexpr __max_size_type&
- operator/=(const __max_size_type& __r) noexcept
+ constexpr __max_diff_type&
+ operator>>=(const __max_diff_type& __r) noexcept
{
- _M_val /= __r._M_val;
- _M_sign_bit ^= __r._M_sign_bit;
+ const auto __msb = _M_rep._M_msb;
+ _M_rep >>= __r._M_rep;
+ _M_rep._M_msb |= __msb;
return *this;
}
- constexpr __max_size_type&
- operator%=(const __max_size_type& __r) noexcept
+ constexpr __max_diff_type&
+ operator&=(const __max_diff_type& __r) noexcept
{
- _M_val /= __r._M_val;
+ _M_rep &= __r._M_rep;
return *this;
}
- constexpr __max_size_type&
- operator<<=(const __max_size_type& __r) noexcept
+ constexpr __max_diff_type&
+ operator|=(const __max_diff_type& __r) noexcept
{
- __glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
- __glibcxx_assert(__r._M_sign_bit == 0);
- _M_val <<= __r._M_val;
+ _M_rep |= __r._M_rep;
return *this;
}
- constexpr __max_size_type&
- operator>>=(const __max_size_type& __r) noexcept
+ constexpr __max_diff_type&
+ operator^=(const __max_diff_type& __r) noexcept
{
- __glibcxx_assert(__r._M_val < numeric_limits<rep>::digits);
- __glibcxx_assert(__r._M_sign_bit == 0);
- _M_val >>= __r._M_val;
+ _M_rep ^= __r._M_rep;
return *this;
}
- friend constexpr __max_size_type
- operator+(__max_size_type __l, const __max_size_type& __r) noexcept
+ friend constexpr __max_diff_type
+ operator+(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l += __r;
return __l;
}
- friend constexpr __max_size_type
- operator-(__max_size_type __l, const __max_size_type& __r) noexcept
+ friend constexpr __max_diff_type
+ operator-(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l -= __r;
return __l;
}
- friend constexpr __max_size_type
- operator*(__max_size_type __l, const __max_size_type& __r) noexcept
+ friend constexpr __max_diff_type
+ operator*(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l *= __r;
return __l;
}
- friend constexpr __max_size_type
- operator/(__max_size_type __l, const __max_size_type& __r) noexcept
+ friend constexpr __max_diff_type
+ operator/(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l /= __r;
return __l;
}
- friend constexpr __max_size_type
- operator%(__max_size_type __l, const __max_size_type& __r) noexcept
+ friend constexpr __max_diff_type
+ operator%(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l %= __r;
return __l;
}
- friend constexpr __max_size_type
- operator<<(__max_size_type __l, const __max_size_type& __r) noexcept
+ friend constexpr __max_diff_type
+ operator<<(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l <<= __r;
return __l;
}
- friend constexpr __max_size_type
- operator>>(__max_size_type __l, const __max_size_type& __r) noexcept
+ friend constexpr __max_diff_type
+ operator>>(__max_diff_type __l, const __max_diff_type& __r) noexcept
{
__l >>= __r;
return __l;
}
- // TODO & | ^ > <= >=
+ friend constexpr __max_diff_type
+ operator&(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ {
+ __l &= __r;
+ return __l;
+ }
+
+ friend constexpr __max_diff_type
+ operator|(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ {
+ __l |= __r;
+ return __l;
+ }
+
+ friend constexpr __max_diff_type
+ operator^(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ {
+ __l ^= __r;
+ return __l;
+ }
friend constexpr bool
- operator==(const __max_size_type& __l, const __max_size_type& __r)
+ operator==(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{
- return __l._M_val == __r._M_val && __l._M_msb == __r._M_msb;
+ return __l._M_rep == __r._M_rep;
}
friend constexpr bool
- operator!=(const __max_size_type& __l, const __max_size_type& __r)
+ operator!=(const __max_diff_type& __l, const __max_diff_type& __r)
noexcept
{ return !(__l == __r); }
- friend constexpr bool
- operator<(const __max_size_type& __l, const __max_size_type& __r)
- noexcept
+ constexpr bool
+ operator<(const __max_diff_type& __r) const noexcept
{
- if (__l._M_msb == __r._M_msb)
- return __l._M_val < __r._M_val;
+ const auto __lsign = _M_rep._M_msb;
+ const auto __rsign = __r._M_rep._M_msb;
+ if (__lsign ^ __rsign)
+ return __lsign;
else
- return __r._M_msb;
+ return _M_rep < __r._M_rep;
}
friend constexpr bool
- operator>(const __max_size_type& __l, const __max_size_type& __r)
- noexcept
+ operator>(const __max_diff_type& __l, const __max_diff_type& __r) noexcept
{ return __r < __l; }
+ friend constexpr bool
+ operator<=(const __max_diff_type& __l, const __max_diff_type& __r) noexcept
+ { return !(__r < __l); }
+
+ friend constexpr bool
+ operator>=(const __max_diff_type& __l, const __max_diff_type& __r) noexcept
+ { return !(__l < __r); }
+
private:
-#ifdef __SIZEOF_INT128__
- using rep = unsigned __int128;
-#else
- using rep = unsigned long long;
-#endif
- rep _M_val = 0;
- unsigned _M_msb : 1;
+ __max_size_type _M_rep = 0;
- constexpr explicit
- __max_size_type(rep __val, int __sb) noexcept
- : _M_val(__val), _M_sig_bit(__sb)
- { }
+ friend class __max_size_type;
};
+ static_assert(sizeof(__max_diff_type) == sizeof(__max_size_type));
+
constexpr __max_size_type
__to_unsigned_like(__max_size_type __t) noexcept
{ return __t; }
@@ -767,8 +866,6 @@ namespace ranges
__to_unsigned_like(__max_diff_type __t) noexcept
{ return __max_size_type(__t); }
-#endif // _GLIBCXX_INTEGER_LIKE_TYPES
-
template<integral _Tp>
constexpr make_unsigned_t<_Tp>
__to_unsigned_like(_Tp __t) noexcept
diff --git a/libstdc++-v3/testsuite/std/ranges/iota/difference_type.cc b/libstdc++-v3/testsuite/std/ranges/iota/difference_type.cc
index 4a342de..b8bb555 100644
--- a/libstdc++-v3/testsuite/std/ranges/iota/difference_type.cc
+++ b/libstdc++-v3/testsuite/std/ranges/iota/difference_type.cc
@@ -49,9 +49,141 @@ test02()
#endif
}
+void
+test03()
+{
+ using max_size_t = std::ranges::__detail::__max_size_type;
+ using max_diff_t = std::ranges::__detail::__max_diff_type;
+ using rep_t = max_size_t::__rep;
+
+ static_assert(max_size_t(7) % 3 == 1);
+ static_assert(max_size_t(7) % 4 == 3);
+
+ static_assert(-max_diff_t(1) == max_diff_t(-1));
+ static_assert(max_diff_t(3) % 2 == 1);
+ static_assert(max_diff_t(-3) / 2 == -2);
+ static_assert(max_diff_t(-3) % 2 == 1);
+ static_assert(max_diff_t(3) % -2 == -1);
+ static_assert(max_diff_t(-3) << 1 == -6);
+ static_assert(max_diff_t(-3) >> 1 == -2);
+ static_assert(max_diff_t(3) >> 1 == 1);
+ static_assert(max_diff_t(3) >> 2 == 0);
+
+ static_assert(max_diff_t(-5) / 3 == -2);
+ static_assert(max_diff_t(5) / -3 == -2);
+ static_assert(max_diff_t(-5) / -3 == 1);
+ static_assert(max_diff_t(5) / 3 == 1);
+
+ static_assert(max_diff_t(-6) / 3 == -2);
+ static_assert(max_diff_t(6) / -3 == -2);
+ static_assert(max_diff_t(-6) / -3 == 2);
+ static_assert(max_diff_t(6) / 3 == 2);
+
+ static_assert(~max_size_t(-3) == 2);
+ static_assert(~max_diff_t(-3) == 2);
+
+ static_assert(max_diff_t(1) < max_diff_t(3));
+ static_assert(max_diff_t(-1) < max_diff_t(3));
+ static_assert(max_diff_t(1) > max_diff_t(-3));
+ static_assert(max_diff_t(-1) > max_diff_t(-3));
+
+ constexpr max_size_t mu = std::numeric_limits<rep_t>::max();
+
+ static_assert(max_diff_t(mu)/-1 == -max_diff_t(mu));
+ static_assert(-max_diff_t(mu)/1 == -max_diff_t(mu));
+ static_assert(max_diff_t(mu)>>1 == max_diff_t(mu)/2);
+ static_assert(-max_diff_t(mu+1) == max_diff_t(mu+1));
+ static_assert(-(mu+1) == mu+1);
+ static_assert((mu+1)<<1 == 0);
+ static_assert(max_diff_t(mu+1)<<1 == 0);
+ static_assert(max_diff_t(mu+1)>>1 < 0);
+
+ static_assert(int(max_diff_t(mu+1)) == 0);
+ static_assert(rep_t(max_diff_t(mu+1)) == 0);
+ static_assert(int(max_diff_t(mu)) == -1);
+ static_assert(rep_t(max_diff_t(mu)) == rep_t(-1));
+
+ static_assert(2*mu+1 > 2*mu);
+ static_assert(~(2*mu+1) == 0);
+ static_assert(mu/mu == 1);
+ static_assert(2*mu > mu);
+ static_assert(2*mu-mu == mu);
+ static_assert((2*mu)/mu == 2);
+ static_assert((2*mu+1)/mu == 2);
+ static_assert((2*mu-1)/(mu-1) == 2);
+ static_assert((2*mu-1)/mu == 1);
+ static_assert((2*mu+-1)/mu == 1);
+ static_assert(2*mu-1 < 2*mu);
+ static_assert(2*mu-1 <= 2*mu);
+ static_assert(2*mu+1 > 2*mu);
+ static_assert(2*mu+1 >= 2*mu);
+ static_assert((2*mu)/1 == 2*mu);
+ static_assert(mu/mu-1 == 0);
+ static_assert(mu*0 == 0);
+ static_assert((2*mu-1)*0 == 0);
+ static_assert((2*mu-1)>>1 == mu-1);
+ static_assert(mu+-1+1 == mu);
+ static_assert(mu+1+-1 == mu);
+ static_assert(mu+1);
+ static_assert((2*mu)/2 == mu);
+ static_assert((2*mu)>>1 == mu);
+ static_assert((mu<<1)>>1 == mu);
+ static_assert(1/mu == 0);
+ static_assert(mu/1 == mu);
+ static_assert(((mu+1)|mu) == -1);
+ static_assert((mu+1)+(mu+1) < mu+1);
+
+ constexpr max_size_t ou = 1;
+ constexpr max_diff_t ns = -1;
+
+ static_assert(max_size_t(ns) == -1);
+ static_assert(-max_diff_t(ou) == -1);
+ static_assert(-max_diff_t(-ou) == 1);
+ static_assert(max_size_t(-max_diff_t(-ou)) == 1);
+ static_assert(ns*ns == max_diff_t(ou));
+ static_assert(max_size_t(ns)*max_size_t(ns) == ou);
+ static_assert(-max_diff_t(0) == max_diff_t(0));
+ static_assert(-ou-ou == -2*ou);
+
+ static_assert(int(ns) == -1);
+ static_assert(rep_t(ns) == rep_t(-1));
+
+ auto w = [] <bool b> (std::bool_constant<b>)
+ {
+ using type = std::conditional_t<b, max_diff_t, max_size_t>;
+ static_assert((type(2) | 1) == 3);
+ static_assert((type(2) | 3) == 3);
+ static_assert((type(2) ^ 1) == 3);
+ static_assert((type(2) ^ 3) == 1);
+ static_assert((type(2) & 1) == 0);
+ static_assert((type(2) & 2) == 2);
+ static_assert((type(2) & 3) == 2);
+ static_assert((type(2) & 0) == 0);
+ };
+ w(std::bool_constant<true>());
+ w(std::bool_constant<false>());
+
+ static_assert(max_size_t() == 0);
+ static_assert(max_diff_t() == 0);
+
+ auto f = [] (auto a) { a /= a; return a; };
+ static_assert(f(max_size_t(5)) == 1);
+ static_assert(f(max_size_t(-5)) == 1);
+ static_assert(f(max_diff_t(5)) == 1);
+
+ auto g = [] (auto a) { a >>= a; return a; };
+ static_assert(g(max_size_t(5)) == 0);
+ static_assert(g(max_diff_t(5)) == 0);
+
+ auto h = [] (auto a) { a <<= a; return a; };
+ static_assert(h(max_size_t(3)) == 24);
+ static_assert(h(max_diff_t(3)) == 24);
+}
+
int
main()
{
test01();
test02();
+ test03();
}
More information about the Libstdc++-cvs
mailing list