[gcc(refs/users/ppalka/heads/libstdcxx-constrained-algos)] WIP: incomplete implementation of integer-like class type
Patrick Palka
ppalka@gcc.gnu.org
Thu Jan 16 19:43:00 GMT 2020
https://gcc.gnu.org/g:f32ccb706a2a2d1f546becb5e1c76fa905d70b32
commit f32ccb706a2a2d1f546becb5e1c76fa905d70b32
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Wed Jan 15 14:37:45 2020 +0000
WIP: incomplete implementation of integer-like class type
As defined in [iterator.concept.winc]
Diff:
---
libstdc++-v3/include/bits/iterator_concepts.h | 5 +-
libstdc++-v3/include/bits/range_access.h | 422 ++++++++++++++++++++++++++
2 files changed, 426 insertions(+), 1 deletion(-)
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index bf58159..8ffda85 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -494,7 +494,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace ranges::__detail
{
-#if __SIZEOF_INT128__
+#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
diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index 8b546a5..82922a0 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -347,6 +347,428 @@ namespace ranges
namespace __detail
{
+#ifdef _GLIBCXX_INTEGER_LIKE_TYPES
+ class __max_diff_type
+ {
+ public:
+ __max_diff_type() = default;
+
+ template<signed_integral _Tp>
+ constexpr
+ __max_diff_type(_Tp __i) noexcept
+ : _M_val(__i < 0 ? rep(~__i) + rep(1) : __i), _M_sign_bit(__i < 0)
+ { }
+
+ template<unsigned_integral _Tp>
+ constexpr
+ __max_diff_type(_Tp __i) noexcept
+ : _M_val(__i), _M_sign_bit(false)
+ { }
+
+ 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>
+ constexpr explicit operator _Tp() const noexcept
+ { return _M_val; }
+
+ constexpr explicit
+ operator bool() const noexcept { return _M_val != 0; }
+
+ constexpr __max_diff_type
+ operator+() const noexcept { return *this; }
+
+ constexpr __max_diff_type
+ operator-() const noexcept
+ { return __max_diff_type{_M_val, !_M_sign_bit}; }
+
+ constexpr __max_diff_type
+ operator~() const noexcept
+ { return __max_diff_type{~_M_val, !_M_sign_bit}; }
+
+ 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;
+ else
+ {
+ _M_val = __r._M_val - _M_val;
+ _M_sign_bit = !_M_sign_bit;
+ }
+ return *this;
+ }
+
+ 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;
+ }
+
+ constexpr __max_diff_type&
+ operator*=(const __max_diff_type& __r) noexcept
+ {
+ _M_val *= __r._M_val;
+ _M_sign_bit = (_M_sign_bit != __r._M_sign_bit);
+ return *this;
+ }
+
+ constexpr __max_diff_type&
+ operator/=(const __max_diff_type& __r) noexcept
+ {
+ _M_val /= __r._M_val;
+ _M_sign_bit = (_M_sign_bit != __r._M_sign_bit);
+ return *this;
+ }
+
+ constexpr __max_diff_type&
+ operator%=(const __max_diff_type& __r) noexcept
+ {
+ _M_val /= __r._M_val;
+ return *this;
+ }
+
+ 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);
+ _M_val <<= __r._M_val;
+ return *this;
+ }
+
+ 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);
+ _M_val >>= __r._M_val;
+ return *this;
+ }
+
+ 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 __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 __max_diff_type
+ operator>>(__max_diff_type __l, const __max_diff_type& __r) noexcept
+ {
+ __l >>= __r;
+ return __l;
+ }
+
+ // TODO & | ^
+
+ friend constexpr bool
+ operator==(const __max_diff_type& __l, const __max_diff_type& __r)
+ noexcept
+ {
+ return __l._M_val == __r._M_val && __l._M_sign_bit == __r._M_sign_bit;
+ }
+
+ friend constexpr bool
+ operator!=(const __max_diff_type& __l, const __max_diff_type& __r)
+ noexcept
+ { return !(__l == __r); }
+
+ friend constexpr bool
+ operator<(const __max_diff_type& __l, const __max_diff_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;
+ }
+
+ 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 !(__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;
+ bool _M_sign_bit = false;
+
+ constexpr explicit
+ __max_diff_type(rep __val, bool __sb) noexcept
+ : _M_val(__val), _M_sign_bit(__sb)
+ { }
+
+ friend class __max_size_type;
+ };
+
+ class __max_size_type
+ {
+ public:
+ __max_size_type() = default;
+
+ template<integral _Tp>
+ constexpr
+ __max_size_type(_Tp __i) noexcept
+ : _M_val(__i), _M_msb(0)
+ { }
+
+ constexpr explicit
+ __max_size_type(const __max_diff_type& __d)
+ : _M_val(__d._M_val), _M_msb(__d._M_sign_bit)
+ { }
+
+ template<integral _Tp>
+ constexpr explicit operator _Tp() const noexcept
+ { return _M_val; }
+
+ constexpr explicit
+ operator bool() const noexcept { return _M_val != 0; }
+
+ constexpr __max_size_type
+ operator+() const noexcept { return *this; }
+
+ constexpr __max_size_type
+ operator-() const noexcept
+ { return __max_size_type{_M_val, !_M_sign_bit}; }
+
+ constexpr __max_size_type
+ operator~() const noexcept
+ { return __max_size_type{~_M_val, !_M_sign_bit}; }
+
+ 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
+ {
+ _M_val = __r._M_val - _M_val;
+ _M_sign_bit = !_M_sign_bit;
+ }
+ return *this;
+ }
+
+ 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;
+ }
+
+ constexpr __max_size_type&
+ operator*=(const __max_size_type& __r) noexcept
+ {
+ _M_val *= __r._M_val;
+ _M_sign_bit ^= __r._M_sign_bit;
+ return *this;
+ }
+
+ constexpr __max_size_type&
+ operator/=(const __max_size_type& __r) noexcept
+ {
+ _M_val /= __r._M_val;
+ _M_sign_bit ^= __r._M_sign_bit;
+ return *this;
+ }
+
+ constexpr __max_size_type&
+ operator%=(const __max_size_type& __r) noexcept
+ {
+ _M_val /= __r._M_val;
+ return *this;
+ }
+
+ 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 == 0);
+ _M_val <<= __r._M_val;
+ return *this;
+ }
+
+ 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 == 0);
+ _M_val >>= __r._M_val;
+ return *this;
+ }
+
+ friend constexpr __max_size_type
+ operator+(__max_size_type __l, const __max_size_type& __r) noexcept
+ {
+ __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 __max_size_type
+ operator*(__max_size_type __l, const __max_size_type& __r) noexcept
+ {
+ __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 __max_size_type
+ operator%(__max_size_type __l, const __max_size_type& __r) noexcept
+ {
+ __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 __max_size_type
+ operator>>(__max_size_type __l, const __max_size_type& __r) noexcept
+ {
+ __l >>= __r;
+ return __l;
+ }
+
+ // TODO & | ^ > <= >=
+
+ friend constexpr bool
+ operator==(const __max_size_type& __l, const __max_size_type& __r)
+ noexcept
+ {
+ return __l._M_val == __r._M_val && __l._M_msb == __r._M_msb;
+ }
+
+ friend constexpr bool
+ 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_msb == __r._M_msb)
+ return __l._M_val < __r._M_val;
+ else
+ return __r._M_msb;
+ }
+
+ friend constexpr bool
+ operator>(const __max_size_type& __l, const __max_size_type& __r)
+ noexcept
+ { return __r < __l; }
+
+ private:
+#ifdef __SIZEOF_INT128__
+ using rep = unsigned __int128;
+#else
+ using rep = unsigned long long;
+#endif
+ rep _M_val = 0;
+ unsigned _M_msb : 1;
+
+ constexpr explicit
+ __max_size_type(rep __val, int __sb) noexcept
+ : _M_val(__val), _M_sig_bit(__sb)
+ { }
+ };
+
+ constexpr __max_size_type
+ __to_unsigned_like(__max_size_type __t) noexcept
+ { return __t; }
+
+ constexpr __max_size_type
+ __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
More information about the Libstdc++-cvs
mailing list