diff options
author | Martin Liska <mliska@suse.cz> | 2022-11-08 12:36:43 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-11-08 12:36:43 +0100 |
commit | 4b13c73bba935443be3207abf26f7ba05f79badc (patch) | |
tree | a6bb1525d07859fa8fc6f61dd13df7ddfd1ac254 /libstdc++-v3/include | |
parent | 33f5dde0cd15df9cf89b29280d4ff5fcf7b30e66 (diff) | |
parent | fa271afb58423014e2feef9f15c1a87428e64ddc (diff) | |
download | gcc-devel/sphinx.zip gcc-devel/sphinx.tar.gz gcc-devel/sphinx.tar.bz2 |
Merge branch 'master' into devel/sphinxdevel/sphinx
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/std/charconv | 61 | ||||
-rw-r--r-- | libstdc++-v3/include/std/ranges | 603 |
2 files changed, 664 insertions, 0 deletions
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index e9bf953..09163af 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -736,6 +736,27 @@ namespace __detail __value = __val; return __res; } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) +#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT + __extension__ from_chars_result + from_chars(const char* __first, const char* __last, __ieee128& __value, + chars_format __fmt = chars_format::general) noexcept; + + inline from_chars_result + from_chars(const char* __first, const char* __last, _Float128& __value, + chars_format __fmt = chars_format::general) noexcept + { + __extension__ __ieee128 __val; + from_chars_result __res = from_chars(__first, __last, __val, __fmt); + if (__res.ec == errc{}) + __value = __val; + return __res; + } +#else + from_chars_result + from_chars(const char* __first, const char* __last, _Float128& __value, + chars_format __fmt = chars_format::general) noexcept; +#endif #endif #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) \ @@ -851,6 +872,46 @@ namespace __detail return to_chars(__first, __last, static_cast<long double>(__value), __fmt, __precision); } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) +#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT + __extension__ to_chars_result + to_chars(char* __first, char* __last, __float128 __value) noexcept; + __extension__ to_chars_result + to_chars(char* __first, char* __last, __float128 __value, + chars_format __fmt) noexcept; + __extension__ to_chars_result + to_chars(char* __first, char* __last, __float128 __value, + chars_format __fmt, int __precision) noexcept; + + inline to_chars_result + to_chars(char* __first, char* __last, _Float128 __value) noexcept + { + __extension__ + return to_chars(__first, __last, static_cast<__float128>(__value)); + } + inline to_chars_result + to_chars(char* __first, char* __last, _Float128 __value, + chars_format __fmt) noexcept + { + __extension__ + return to_chars(__first, __last, static_cast<__float128>(__value), __fmt); + } + inline to_chars_result + to_chars(char* __first, char* __last, _Float128 __value, + chars_format __fmt, int __precision) noexcept + { + __extension__ + return to_chars(__first, __last, static_cast<__float128>(__value), __fmt, + __precision); + } +#else + to_chars_result to_chars(char* __first, char* __last, _Float128 __value) + noexcept; + to_chars_result to_chars(char* __first, char* __last, _Float128 __value, + chars_format __fmt) noexcept; + to_chars_result to_chars(char* __first, char* __last, _Float128 __value, + chars_format __fmt, int __precision) noexcept; +#endif #endif #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index a55e9e7..ba544e1 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -829,6 +829,9 @@ namespace __detail } // namespace __detail +// Shorthand for __detail::__maybe_const_t. +using __detail::__maybe_const_t; + namespace views::__adaptor { // True if the range adaptor _Adaptor can be applied with _Args. @@ -7973,6 +7976,606 @@ namespace views::__adaptor inline constexpr _Stride stride; } + + namespace __detail + { + template<bool _Const, typename _First, typename... _Vs> + concept __cartesian_product_is_random_access + = (random_access_range<__maybe_const_t<_Const, _First>> + && ... + && (random_access_range<__maybe_const_t<_Const, _Vs>> + && sized_range<__maybe_const_t<_Const, _Vs>>)); + + template<typename _Range> + concept __cartesian_product_common_arg + = common_range<_Range> || (sized_range<_Range> && random_access_range<_Range>); + + template<bool _Const, typename _First, typename... _Vs> + concept __cartesian_product_is_bidirectional + = (bidirectional_range<__maybe_const_t<_Const, _First>> + && ... + && (bidirectional_range<__maybe_const_t<_Const, _Vs>> + && __cartesian_product_common_arg<__maybe_const_t<_Const, _Vs>>)); + + template<typename _First, typename... _Vs> + concept __cartesian_product_is_common = __cartesian_product_common_arg<_First>; + + template<typename... _Vs> + concept __cartesian_product_is_sized = (sized_range<_Vs> && ...); + + template<bool _Const, template<typename> class FirstSent, typename _First, typename... _Vs> + concept __cartesian_is_sized_sentinel + = (sized_sentinel_for<FirstSent<__maybe_const_t<_Const, _First>>, + iterator_t<__maybe_const_t<_Const, _First>>> + && ... + && (sized_range<__maybe_const_t<_Const, _Vs>> + && sized_sentinel_for<iterator_t<__maybe_const_t<_Const, _Vs>>, + iterator_t<__maybe_const_t<_Const, _Vs>>>)); + + template<__cartesian_product_common_arg _Range> + constexpr auto + __cartesian_common_arg_end(_Range& __r) + { + if constexpr (common_range<_Range>) + return ranges::end(__r); + else + return ranges::begin(__r) + ranges::distance(__r); + } + } // namespace __detail + + template<input_range _First, forward_range... _Vs> + requires (view<_First> && ... && view<_Vs>) + class cartesian_product_view : public view_interface<cartesian_product_view<_First, _Vs...>> + { + tuple<_First, _Vs...> _M_bases; + + template<bool> class _Iterator; + + static auto + _S_difference_type() + { + // TODO: Implement the recommended practice of using the smallest + // sufficiently wide type according to the maximum sizes of the + // underlying ranges? + return common_type_t<ptrdiff_t, + range_difference_t<_First>, + range_difference_t<_Vs>...>{}; + } + + public: + cartesian_product_view() = default; + + constexpr explicit + cartesian_product_view(_First __first, _Vs... __rest) + : _M_bases(std::move(__first), std::move(__rest)...) + { } + + constexpr _Iterator<false> + begin() requires (!__detail::__simple_view<_First> || ... || !__detail::__simple_view<_Vs>) + { return _Iterator<false>(*this, __detail::__tuple_transform(ranges::begin, _M_bases)); } + + constexpr _Iterator<true> + begin() const requires (range<const _First> && ... && range<const _Vs>) + { return _Iterator<true>(*this, __detail::__tuple_transform(ranges::begin, _M_bases)); } + + constexpr _Iterator<false> + end() requires ((!__detail::__simple_view<_First> || ... || !__detail::__simple_view<_Vs>) + && __detail::__cartesian_product_is_common<_First, _Vs...>) + { + bool __empty_tail = [this]<size_t... _Is>(index_sequence<_Is...>) { + return (ranges::empty(std::get<1 + _Is>(_M_bases)) || ...); + }(make_index_sequence<sizeof...(_Vs)>{}); + + auto __it = __detail::__tuple_transform(ranges::begin, _M_bases); + if (!__empty_tail) + std::get<0>(__it) = __detail::__cartesian_common_arg_end(std::get<0>(_M_bases)); + return _Iterator<false>{*this, std::move(__it)}; + } + + constexpr _Iterator<true> + end() const requires __detail::__cartesian_product_is_common<const _First, const _Vs...> + { + bool __empty_tail = [this]<size_t... _Is>(index_sequence<_Is...>) { + return (ranges::empty(std::get<1 + _Is>(_M_bases)) || ...); + }(make_index_sequence<sizeof...(_Vs)>{}); + + auto __it = __detail::__tuple_transform(ranges::begin, _M_bases); + if (!__empty_tail) + std::get<0>(__it) = __detail::__cartesian_common_arg_end(std::get<0>(_M_bases)); + return _Iterator<true>{*this, std::move(__it)}; + } + + constexpr default_sentinel_t + end() const noexcept + { return default_sentinel; } + + constexpr auto + size() requires __detail::__cartesian_product_is_sized<_First, _Vs...> + { + using _ST = __detail::__make_unsigned_like_t<decltype(_S_difference_type())>; + return [&]<size_t... _Is>(index_sequence<_Is...>) { + auto __size = static_cast<_ST>(1); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral<_ST>) + { + bool __overflow + = (__builtin_mul_overflow(__size, + static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))), + &__size) + || ...); + __glibcxx_assert(!__overflow); + } + else +#endif + __size = (static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))) * ...); + return __size; + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + constexpr auto + size() const requires __detail::__cartesian_product_is_sized<const _First, const _Vs...> + { + using _ST = __detail::__make_unsigned_like_t<decltype(_S_difference_type())>; + return [&]<size_t... _Is>(index_sequence<_Is...>) { + auto __size = static_cast<_ST>(1); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral<_ST>) + { + bool __overflow + = (__builtin_mul_overflow(__size, + static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))), + &__size) + || ...); + __glibcxx_assert(!__overflow); + } + else +#endif + __size = (static_cast<_ST>(ranges::size(std::get<_Is>(_M_bases))) * ...); + return __size; + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + }; + + template<typename... _Vs> + cartesian_product_view(_Vs&&...) -> cartesian_product_view<views::all_t<_Vs>...>; + + template<input_range _First, forward_range... _Vs> + requires (view<_First> && ... && view<_Vs>) + template<bool _Const> + class cartesian_product_view<_First, _Vs...>::_Iterator + { + using _Parent = __maybe_const_t<_Const, cartesian_product_view>; + _Parent* _M_parent = nullptr; + __detail::__tuple_or_pair_t<iterator_t<__maybe_const_t<_Const, _First>>, + iterator_t<__maybe_const_t<_Const, _Vs>>...> _M_current; + + constexpr + _Iterator(_Parent& __parent, decltype(_M_current) __current) + : _M_parent(std::__addressof(__parent)), + _M_current(std::move(__current)) + { } + + static auto + _S_iter_concept() + { + if constexpr (__detail::__cartesian_product_is_random_access<_Const, _First, _Vs...>) + return random_access_iterator_tag{}; + else if constexpr (__detail::__cartesian_product_is_bidirectional<_Const, _First, _Vs...>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<__maybe_const_t<_Const, _First>>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend cartesian_product_view; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using value_type + = __detail::__tuple_or_pair_t<range_value_t<__maybe_const_t<_Const, _First>>, + range_value_t<__maybe_const_t<_Const, _Vs>>...>; + using reference + = __detail::__tuple_or_pair_t<range_reference_t<__maybe_const_t<_Const, _First>>, + range_reference_t<__maybe_const_t<_Const, _Vs>>...>; + using difference_type = decltype(cartesian_product_view::_S_difference_type()); + + _Iterator() requires forward_range<__maybe_const_t<_Const, _First>> = default; + + constexpr + _Iterator(_Iterator<!_Const> __i) + requires _Const + && (convertible_to<iterator_t<_First>, iterator_t<const _First>> + && ... && convertible_to<iterator_t<_Vs>, iterator_t<const _Vs>>) + : _M_parent(std::__addressof(__i._M_parent)), + _M_current(std::move(__i._M_current)) + { } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { + return *__i; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + _M_next(); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<__maybe_const_t<_Const, _First>> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires __detail::__cartesian_product_is_bidirectional<_Const, _First, _Vs...> + { + _M_prev(); + return *this; + } + + constexpr _Iterator + operator--(int) + requires __detail::__cartesian_product_is_bidirectional<_Const, _First, _Vs...> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { + _M_advance(__x); + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return *this += -__x; } + + constexpr reference + operator[](difference_type __n) const + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return *((*this) + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<iterator_t<__maybe_const_t<_Const, _First>>> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator==(const _Iterator& __x, default_sentinel_t) + { + return [&]<size_t... _Is>(index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) + == ranges::end(std::get<_Is>(__x._M_parent->_M_bases))) + || ...); + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _First, _Vs...> + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(_Iterator __x, difference_type __y) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return __x += __y; } + + friend constexpr _Iterator + operator+(difference_type __x, _Iterator __y) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return __y += __x; } + + friend constexpr _Iterator + operator-(_Iterator __x, difference_type __y) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { return __x -= __y; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires __detail::__cartesian_is_sized_sentinel<_Const, iterator_t, _First, _Vs...> + { return __x._M_distance_from(__y._M_current); } + + friend constexpr difference_type + operator-(const _Iterator& __i, default_sentinel_t) + requires __detail::__cartesian_is_sized_sentinel<_Const, sentinel_t, _First, _Vs...> + { + tuple __end_tuple = [&]<size_t... _Is>(index_sequence<_Is...>) { + return tuple{ranges::end(std::get<0>(__i._M_parent->_M_bases)), + ranges::begin(std::get<1 + _Is>(__i._M_parent->_M_bases))...}; + }(make_index_sequence<sizeof...(_Vs)>{}); + return __i._M_distance_from(__end_tuple); + } + + friend constexpr difference_type + operator-(default_sentinel_t, const _Iterator& __i) + requires __detail::__cartesian_is_sized_sentinel<_Const, sentinel_t, _First, _Vs...> + { return -(__i - default_sentinel); } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires (indirectly_swappable<iterator_t<__maybe_const_t<_Const, _First>>> + && ... + && indirectly_swappable<iterator_t<__maybe_const_t<_Const, _Vs>>>) + { + [&]<size_t... _Is>(index_sequence<_Is...>) { + (ranges::iter_swap(std::get<_Is>(__l._M_current), std::get<_Is>(__r._M_current)), ...); + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + private: + template<size_t _Nm = sizeof...(_Vs)> + constexpr void + _M_next() + { + auto& __it = std::get<_Nm>(_M_current); + ++__it; + if constexpr (_Nm > 0) + if (__it == ranges::end(std::get<_Nm>(_M_parent->_M_bases))) + { + __it = ranges::begin(std::get<_Nm>(_M_parent->_M_bases)); + _M_next<_Nm - 1>(); + } + } + + template<size_t _Nm = sizeof...(_Vs)> + constexpr void + _M_prev() + { + auto& __it = std::get<_Nm>(_M_current); + if (__it == ranges::begin(std::get<_Nm>(_M_parent->_M_bases))) + { + __it = __detail::__cartesian_common_arg_end(std::get<_Nm>(_M_parent->_M_bases)); + if constexpr (_Nm > 0) + _M_prev<_Nm - 1>(); + } + --__it; + } + + template<size_t _Nm = sizeof...(_Vs)> + constexpr void + _M_advance(difference_type __x) + requires __detail::__cartesian_product_is_random_access<_Const, _First, _Vs...> + { + if (__x == 1) + _M_next<_Nm>(); + else if (__x == -1) + _M_prev<_Nm>(); + else if (__x != 0) + { + // Constant time iterator advancement. + auto& __r = std::get<_Nm>(_M_parent->_M_bases); + auto& __it = std::get<_Nm>(_M_current); + if constexpr (_Nm == 0) + { +#ifdef _GLIBCXX_ASSERTIONS + auto __size = ranges::ssize(__r); + auto __begin = ranges::begin(__r); + auto __offset = __it - __begin; + __glibcxx_assert(__offset + __x >= 0 && __offset + __x <= __size); +#endif + __it += __x; + } + else + { + auto __size = ranges::ssize(__r); + auto __begin = ranges::begin(__r); + auto __offset = __it - __begin; + __offset += __x; + __x = __offset / __size; + __offset %= __size; + if (__offset < 0) + { + __offset = __size + __offset; + --__x; + } + __it = __begin + __offset; + _M_advance<_Nm - 1>(__x); + } + } + } + + template<typename _Tuple> + constexpr difference_type + _M_distance_from(const _Tuple& __t) const + { + return [&]<size_t... _Is>(index_sequence<_Is...>) { + auto __sum = static_cast<difference_type>(0); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral<difference_type>) + { + bool __overflow + = (__builtin_add_overflow(__sum, _M_scaled_distance<_Is>(__t), &__sum) + || ...); + __glibcxx_assert(!__overflow); + } + else +#endif + __sum = (_M_scaled_distance<_Is>(__t) + ...); + return __sum; + }(make_index_sequence<1 + sizeof...(_Vs)>{}); + } + + template<size_t _Nm, typename _Tuple> + constexpr difference_type + _M_scaled_distance(const _Tuple& __t) const + { + auto __dist = static_cast<difference_type>(std::get<_Nm>(_M_current) + - std::get<_Nm>(__t)); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral<difference_type>) + { + bool __overflow = __builtin_mul_overflow(__dist, _M_scaled_size<_Nm+1>(), &__dist); + __glibcxx_assert(!__overflow); + } + else +#endif + __dist *= _M_scaled_size<_Nm+1>(); + return __dist; + } + + template<size_t _Nm> + constexpr difference_type + _M_scaled_size() const + { + if constexpr (_Nm <= sizeof...(_Vs)) + { + auto __size = static_cast<difference_type>(ranges::size + (std::get<_Nm>(_M_parent->_M_bases))); +#ifdef _GLIBCXX_ASSERTIONS + if constexpr (integral<difference_type>) + { + bool __overflow = __builtin_mul_overflow(__size, _M_scaled_size<_Nm+1>(), &__size); + __glibcxx_assert(!__overflow); + } + else +#endif + __size *= _M_scaled_size<_Nm+1>(); + return __size; + } + else + return static_cast<difference_type>(1); + } + }; + + namespace views + { + namespace __detail + { + template<typename... _Ts> + concept __can_cartesian_product_view + = requires { cartesian_product_view<all_t<_Ts>...>(std::declval<_Ts>()...); }; + } + + struct _CartesianProduct + { + template<typename... _Ts> + requires (sizeof...(_Ts) == 0 || __detail::__can_cartesian_product_view<_Ts...>) + constexpr auto + operator() [[nodiscard]] (_Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::empty<tuple<>>; + else + return cartesian_product_view<all_t<_Ts>...>(std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _CartesianProduct cartesian_product; + } + + template<input_range _Vp> + requires view<_Vp> + class as_rvalue_view : public view_interface<as_rvalue_view<_Vp>> + { + _Vp _M_base = _Vp(); + + public: + as_rvalue_view() requires default_initializable<_Vp> = default; + + constexpr explicit + as_rvalue_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return move_iterator(ranges::begin(_M_base)); } + + constexpr auto + begin() const requires range<const _Vp> + { return move_iterator(ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp>) + return move_iterator(ranges::end(_M_base)); + else + return move_sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires range<const _Vp> + { + if constexpr (common_range<const _Vp>) + return move_iterator(ranges::end(_M_base)); + else + return move_sentinel(ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range<const _Vp> + { return ranges::size(_M_base); } + }; + + template<typename _Range> + as_rvalue_view(_Range&&) -> as_rvalue_view<views::all_t<_Range>>; + + template<typename _Tp> + inline constexpr bool enable_borrowed_range<as_rvalue_view<_Tp>> + = enable_borrowed_range<_Tp>; + + namespace views + { + namespace __detail + { + template<typename _Tp> + concept __can_as_rvalue_view = requires { as_rvalue_view(std::declval<_Tp>()); }; + } + + struct _AsRvalue : __adaptor::_RangeAdaptorClosure + { + template<viewable_range _Range> + requires __detail::__can_as_rvalue_view<_Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + if constexpr (same_as<range_rvalue_reference_t<_Range>, + range_reference_t<_Range>>) + return views::all(std::forward<_Range>(__r)); + else + return as_rvalue_view(std::forward<_Range>(__r)); + } + }; + + inline constexpr _AsRvalue as_rvalue; + } #endif // C++23 } // namespace ranges |