From bfa70306cba5fed54ba5bbe9f84ac8f3c6fc6682 Mon Sep 17 00:00:00 2001 From: eightfold <97198162+8ightfold@users.noreply.github.com> Date: Tue, 27 Jun 2023 23:14:53 -0400 Subject: [PATCH 1/2] Add adjacent_view Implements compile time sized sliding, returns a tuple. --- include/range/v3/view.hpp | 1 + include/range/v3/view/adjacent.hpp | 407 +++++++++++++++++++++++++++++ 2 files changed, 408 insertions(+) create mode 100644 include/range/v3/view/adjacent.hpp diff --git a/include/range/v3/view.hpp b/include/range/v3/view.hpp index 10d4aeee3..66e049979 100644 --- a/include/range/v3/view.hpp +++ b/include/range/v3/view.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include diff --git a/include/range/v3/view/adjacent.hpp b/include/range/v3/view/adjacent.hpp new file mode 100644 index 000000000..3cf22cb43 --- /dev/null +++ b/include/range/v3/view/adjacent.hpp @@ -0,0 +1,407 @@ +/// \file +// Range v3 library +// +// Copyright Eric Niebler 2013-present +// Copyright Tobias Mayer 2016 +// Copyright Casey Carter 2016 +// +// Created by Eightfold 2023 +// +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Project home: https://github.com/ericniebler/range-v3 +// + +#ifndef RANGES_V3_VIEW_ADJACENT_HPP +#define RANGES_V3_VIEW_ADJACENT_HPP + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace ranges +{ + /// \cond + namespace adjacent_view_detail + { + using sliding_view_detail::cache; + using sliding_view_detail::caching; + + template + using trailing = sliding_view_detail::trailing; + } // namespace adjacent_view_detail + /// \endcond + + template(typename Rng, detail::integer_like_ auto N, // + adjacent_view_detail::cache = adjacent_view_detail::caching::value)( + requires viewable_range AND (N > 0)) + struct adjacent_view; + + /// \cond + namespace adjacent_view_detail + { + template + using expansion_t = // + decltype(std::make_index_sequence{}); + + template + using identity_t = T; + + template + using tuple_fwd_t = // + std::tuple...>; + + template, typename = expansion_t> + struct adjacent_tie_; + + template + struct adjacent_tie_> + { + private: + using element_type_ = decltype(*std::declval&>()); + + public: + adjacent_tie_() = default; + + auto operator()(auto&& rng) const + -> tuple_fwd_t + { + auto counted = views::counted(rng, static_cast>(N)); + return tuple_fwd_t{counted[Ns]...}; + } + }; + + template + struct adjacent_tie_> + { + private: + using element_type_ = decltype(*std::declval&>()); + mutable std::array*, N> iter_storage_; + + public: + adjacent_tie_() + : iter_storage_{} + {} + auto operator()(auto&& rng) const + -> tuple_fwd_t + { + auto counted = views::counted(rng, static_cast>(N)); + for(auto&& [i, c] : views::zip(iter_storage_, counted)) i = &c; + return tuple_fwd_t{*iter_storage_[Ns]...}; + } + }; + + template + struct RANGES_EMPTY_BASES av_base + : view_adaptor, Rng, + is_finite::value ? finite : range_cardinality::value> + , private detail::non_propagating_cache, av_base, + !random_access_range> + { + CPP_assert(forward_range); + av_base() = default; + av_base(Rng rng, std::integral_constant) + : av_base::view_adaptor(std::move(rng)) + { + CPP_assert(0 < N); + } + CPP_auto_member + auto CPP_fun(size)()(const // + requires sized_range) + { + auto const count = ranges::size(this->base()); + auto constexpr n = static_cast>(n_); + return count < n ? 0 : count - n + 1; + } + CPP_auto_member + auto CPP_fun(size)()( + requires sized_range) + { + auto const count = ranges::size(this->base()); + auto constexpr n = static_cast>(n_); + return count < n ? 0 : count - n + 1; + } + + protected: + using difference_type_ = range_difference_t; + static constexpr auto n_ = static_cast(N); + + optional> & cache() & + { + return static_cast(*this); + } + optional> const & cache() const & + { + return static_cast(*this); + } + + private: + using cache_t = detail::non_propagating_cache, av_base>; + }; + } // namespace adjacent_view_detail + /// \endcond + + /// \addtogroup group-views + /// @{ + template(typename Rng, detail::integer_like_ auto N)( + requires viewable_range AND (N > 0)) + struct RANGES_EMPTY_BASES adjacent_view + : adjacent_view_detail::av_base + { + private: + friend range_access; + + iterator_t get_first() + { + auto & first = this->cache(); + if(!first) + { + first = ranges::next( + ranges::begin(this->base()), this->n_ - 1, ranges::end(this->base())); + } + return *first; + } + + struct RANGES_EMPTY_BASES adaptor + : adaptor_base + , adjacent_view_detail::trailing + { + private: + using base_t = adjacent_view_detail::trailing; + static constexpr auto n_ = static_cast>(N); + adjacent_view_detail::adjacent_tie_ t_; + + public: + adaptor() = default; + adaptor(adjacent_view * v) + : base_t{v->base()} + , t_() + {} + iterator_t begin(adjacent_view & v) + { + return v.get_first(); + } + auto read(iterator_t const & it) const + -> decltype(t_(base_t::get(it, n_))) + { + return t_(base_t::get(it, n_)); + } + void next(iterator_t & it) + { + ++it; + base_t::next(); + } + CPP_member + auto prev(iterator_t & it) // + -> CPP_ret(void)( + requires bidirectional_range) + { + base_t::prev(); + --it; + } + CPP_member + auto advance(iterator_t & it, range_difference_t n) + -> CPP_ret(void)( + requires random_access_range) + { + it += n; + } + }; + + adaptor begin_adaptor() + { + return {this}; + } + meta::if_c, adaptor, adaptor_base> end_adaptor() + { + return {this}; + } + + public: + using adjacent_view::av_base::av_base; + }; + + template(typename Rng, detail::integer_like_ auto N)( + requires viewable_range AND (N > 0)) + struct adjacent_view + : adjacent_view_detail::av_base + { + private: + friend range_access; + + iterator_t get_last() + { + auto & last = this->cache(); + if(!last) + { + last = ranges::prev( + ranges::end(this->base()), this->n_ - 1, ranges::begin(this->base())); + } + return *last; + } + + struct adaptor : adaptor_base + { + private: + static constexpr auto n_ = static_cast>(N); + adjacent_view_detail::adjacent_tie_ t_; + + public: + adaptor() = default; + adaptor(adjacent_view * v) + : t_() + {} + iterator_t end(adjacent_view & v) + { + return v.get_last(); + } + auto read(iterator_t const & it) const + -> decltype(t_(uncounted(it))) + { + return t_(uncounted(it)); + } + }; + + adaptor begin_adaptor() + { + return {this}; + } + adaptor end_adaptor() + { + return {this}; + } + + public: + using adjacent_view::av_base::av_base; + }; + + template(typename Rng, detail::integer_like_ auto N)( + requires viewable_range AND (N > 0)) + struct adjacent_view + : adjacent_view_detail::av_base + { + private: + friend range_access; + + template + struct adaptor : adaptor_base + { + private: + friend adaptor; + using CRng = meta::const_if_c; + static constexpr auto n_ = static_cast>(N); + adjacent_view_detail::adjacent_tie_ t_; + + public: + adaptor() = default; + template(bool Other)( + requires Const AND CPP_NOT(Other)) // + adaptor(adaptor that) + : t_(that.t_) + {} + iterator_t end(meta::const_if_c & v) const + { + auto const sz = ranges::distance(v.base()); + auto const offset = n_ - 1 < sz ? n_ - 1 : sz; + return ranges::begin(v.base()) + (sz - offset); + } + auto read(iterator_t const & it) const + -> decltype(t_(it)) + { + return t_(it); + } + }; + + adaptor()> begin_adaptor() + { + return {}; + } + CPP_member + auto begin_adaptor() const // + -> CPP_ret(adaptor)( + requires range) + { + return {}; + } + adaptor()> end_adaptor() + { + return {}; + } + CPP_member + auto end_adaptor() const // + -> CPP_ret(adaptor)( + requires range) + { + return {}; + } + + public: + using adjacent_view::av_base::av_base; + }; + + template + RANGES_INLINE_VAR constexpr bool enable_borrowed_range> = // + enable_borrowed_range; + +#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17 + template + adjacent_view(Rng &&, std::integral_constant) // + -> adjacent_view, N>; +#endif + + namespace views + { + // In: range + // Out: range, N>, where each inner range has $N$ elements. + struct adjacent_base_fn + { + template(typename Rng, auto N)( + requires viewable_range AND forward_range) + constexpr adjacent_view, N> // + operator()(Rng && rng, std::integral_constant n) const + { + return {all(static_cast(rng)), n}; + } + }; + + template(auto N)( + requires detail::integer_like_) + struct adjacent_fn + : adjacent_base_fn + { + using adjacent_base_fn::operator(); + + constexpr auto operator()() const + { + return make_view_closure(bind_back(adjacent_base_fn{}, + std::integral_constant{})); + } + }; + + /// \relates adjacent_fn + /// \ingroup group-views + template + RANGES_INLINE_VAR constexpr auto adjacent = adjacent_fn{}(); + } // namespace views + /// @} +} // namespace ranges + +#include + +#endif From 98509163d514b318c93562a059c1623674ca7a7e Mon Sep 17 00:00:00 2001 From: eightfold <97198162+8ightfold@users.noreply.github.com> Date: Tue, 27 Jun 2023 23:28:54 -0400 Subject: [PATCH 2/2] Update adjacent.hpp --- include/range/v3/view/adjacent.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/range/v3/view/adjacent.hpp b/include/range/v3/view/adjacent.hpp index 3cf22cb43..0ffa12b06 100644 --- a/include/range/v3/view/adjacent.hpp +++ b/include/range/v3/view/adjacent.hpp @@ -1,11 +1,7 @@ /// \file // Range v3 library // -// Copyright Eric Niebler 2013-present -// Copyright Tobias Mayer 2016 -// Copyright Casey Carter 2016 -// -// Created by Eightfold 2023 +// Copyright Alex Mills 2023 // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying