Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:09:55

0001 /// \file
0002 // Range v3 library
0003 //
0004 //  Copyright Mitsutaka Takeda 2018-present
0005 //
0006 //  Use, modification and distribution is subject to the
0007 //  Boost Software License, Version 1.0. (See accompanying
0008 //  file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // Project home: https://github.com/ericniebler/range-v3
0012 //
0013 
0014 #ifndef RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
0015 #define RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP
0016 
0017 #include <concepts/concepts.hpp>
0018 
0019 #include <range/v3/range_fwd.hpp>
0020 
0021 #include <range/v3/functional/arithmetic.hpp>
0022 #include <range/v3/functional/bind_back.hpp>
0023 #include <range/v3/functional/invoke.hpp>
0024 #include <range/v3/view/adaptor.hpp>
0025 #include <range/v3/view/view.hpp>
0026 
0027 #include <range/v3/detail/prologue.hpp>
0028 
0029 namespace ranges
0030 {
0031     // clang-format off
0032     /// \concept exclusive_scan_constraints_
0033     /// \brief The \c exclusive_scan_constraints_ concept
0034     template(typename Rng, typename T, typename Fun)(
0035     concept (exclusive_scan_constraints_)(Rng, T, Fun),
0036         invocable<Fun &, T, range_reference_t<Rng>> AND
0037         assignable_from<T &, invoke_result_t<Fun &, T, range_reference_t<Rng>>>
0038     );
0039     /// \concept exclusive_scan_constraints
0040     /// \brief The \c exclusive_scan_constraints concept
0041     template<typename Rng, typename T, typename Fun>
0042     CPP_concept exclusive_scan_constraints =
0043         viewable_range<Rng> && input_range<Rng> &&
0044         copy_constructible<T> &&
0045         CPP_concept_ref(ranges::exclusive_scan_constraints_, Rng, T, Fun);
0046     // clang-format on
0047 
0048     /// \addtogroup group-views
0049     /// @{
0050     template<typename Rng, typename T, typename Fun>
0051     struct exclusive_scan_view : view_adaptor<exclusive_scan_view<Rng, T, Fun>, Rng>
0052     {
0053     private:
0054         friend range_access;
0055         CPP_assert(exclusive_scan_constraints<Rng, T, Fun>);
0056 
0057         semiregular_box_t<T> init_;
0058         semiregular_box_t<Fun> fun_;
0059         using single_pass = meta::bool_<single_pass_iterator_<iterator_t<Rng>>>;
0060         using use_sentinel_t = meta::bool_<!common_range<Rng> || single_pass{}>;
0061 
0062         template<bool IsConst>
0063         struct adaptor : adaptor_base
0064         {
0065         private:
0066             friend struct adaptor<!IsConst>;
0067             using exclusive_scan_view_t = meta::const_if_c<IsConst, exclusive_scan_view>;
0068             using CRng = meta::const_if_c<IsConst, Rng>;
0069             semiregular_box_t<T> sum_;
0070             exclusive_scan_view_t * rng_;
0071 
0072             // clang-format off
0073             auto CPP_auto_fun(move_or_copy_init)(std::false_type)
0074             (
0075                 return (rng_->init_)
0076             )
0077 
0078             // If the base range is single-pass, we can move the init value.
0079             auto CPP_auto_fun(move_or_copy_init)(std::true_type)
0080             (
0081                 return std::move(rng_->init_)
0082             )
0083                 // clang-format on
0084                 public : using single_pass = exclusive_scan_view::single_pass;
0085             adaptor() = default;
0086             adaptor(exclusive_scan_view_t * rng)
0087               : rng_(rng)
0088             {}
0089             template(bool Other)(
0090                 requires IsConst AND CPP_NOT(Other)) //
0091             adaptor(adaptor<Other> that)
0092               : rng_(that.rng_)
0093             {}
0094             iterator_t<CRng> begin(exclusive_scan_view_t &)
0095             {
0096                 sum_ = move_or_copy_init(single_pass{});
0097                 return ranges::begin(rng_->base());
0098             }
0099             T read(iterator_t<CRng> const &) const
0100             {
0101                 return sum_;
0102             }
0103             void next(iterator_t<CRng> & it)
0104             {
0105                 RANGES_EXPECT(it != ranges::end(rng_->base()));
0106                 sum_ = invoke(rng_->fun_, static_cast<T &&>(std::move(sum_)), *it);
0107                 ++it;
0108             }
0109             void prev() = delete;
0110         };
0111 
0112         adaptor<false> begin_adaptor()
0113         {
0114             return {this};
0115         }
0116         meta::if_<use_sentinel_t, adaptor_base, adaptor<false>> end_adaptor()
0117         {
0118             return {this};
0119         }
0120         CPP_member
0121         auto begin_adaptor() const //
0122             -> CPP_ret(adaptor<true>)(
0123                 requires exclusive_scan_constraints<Rng const, T, Fun const>)
0124         {
0125             return {this};
0126         }
0127         CPP_member
0128         auto end_adaptor() const
0129             -> CPP_ret(meta::if_<use_sentinel_t, adaptor_base, adaptor<true>>)(
0130                 requires exclusive_scan_constraints<Rng const, T, Fun const>)
0131         {
0132             return {this};
0133         }
0134 
0135     public:
0136         exclusive_scan_view() = default;
0137         constexpr exclusive_scan_view(Rng rng, T init, Fun fun)
0138           : exclusive_scan_view::view_adaptor{std::move(rng)}
0139           , init_(std::move(init))
0140           , fun_(std::move(fun))
0141         {}
0142         CPP_auto_member
0143         auto CPP_fun(size)()(const
0144             requires sized_range<Rng const>)
0145         {
0146             return ranges::size(this->base());
0147         }
0148         CPP_auto_member
0149         auto CPP_fun(size)()(
0150             requires sized_range<Rng>)
0151         {
0152             return ranges::size(this->base());
0153         }
0154     };
0155 
0156 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0157     template(typename Rng, typename T, typename Fun)(
0158         requires copy_constructible<T> AND copy_constructible<Fun>)
0159     exclusive_scan_view(Rng &&, T, Fun) //
0160         -> exclusive_scan_view<views::all_t<Rng>, T, Fun>;
0161 #endif
0162 
0163     namespace views
0164     {
0165         struct exclusive_scan_base_fn
0166         {
0167             template(typename Rng, typename T, typename Fun = plus)(
0168                 requires exclusive_scan_constraints<Rng, T, Fun>)
0169             constexpr exclusive_scan_view<all_t<Rng>, T, Fun> //
0170             operator()(Rng && rng, T init, Fun fun = Fun{}) const
0171             {
0172                 return {all(static_cast<Rng &&>(rng)), std::move(init), std::move(fun)};
0173             }
0174         };
0175 
0176         struct exclusive_scan_fn : exclusive_scan_base_fn
0177         {
0178             using exclusive_scan_base_fn::operator();
0179 
0180             template<typename T, typename Fun = plus>
0181             constexpr auto operator()(T init, Fun fun = {}) const
0182             {
0183                 return make_view_closure(
0184                     bind_back(exclusive_scan_base_fn{}, std::move(init), std::move(fun)));
0185             }
0186         };
0187 
0188         /// \relates exclusive_scan_fn
0189         /// \ingroup group-views
0190         RANGES_INLINE_VARIABLE(exclusive_scan_fn, exclusive_scan)
0191     } // namespace views
0192     /// @}
0193 } // namespace ranges
0194 
0195 #include <range/v3/detail/epilogue.hpp>
0196 
0197 #endif // RANGES_V3_VIEW_EXCLUSIVE_SCAN_HPP