/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // Copyright Gonzalo Brito Gadeschi 2014 // // 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_NUMERIC_PARTIAL_SUM_HPP #define RANGES_V3_NUMERIC_PARTIAL_SUM_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-numerics /// @{ /// \cond namespace detail { // Only needed for type-checking purposes: struct as_lvalue_fn { template constexpr T & operator()(T && t) const noexcept { return t; } }; template using as_value_type_t = composed>>; } // namespace detail /// \endcond // axiom: BOp is associative over values of I. // clang-format off CPP_def ( template(typename I, typename BOp) concept indirect_semigroup, readable && copyable> && indirectly_regular_binary_invocable_< composed>, BOp>, iter_value_t*, I> ); CPP_def ( template(typename I, typename O, typename BOp = plus, typename P = identity) (concept partial_sum_constraints)(I, O, BOp, P), input_iterator && indirect_semigroup< projected>, P>, BOp> && output_iterator< O, iter_value_t< projected>, P>> const &> ); // clang-format on template using partial_sum_result = detail::in_out_result; struct partial_sum_fn { template auto operator()(I first, S1 last, O result, S2 end_result, BOp bop = BOp{}, P proj = P{}) const -> CPP_ret(partial_sum_result)( // requires sentinel_for && sentinel_for && partial_sum_constraints) { using X = projected>, P>; coerce> val_i; coerce> val_x; if(first != last && result != end_result) { auto && cur1 = val_i(*first); iter_value_t t(invoke(proj, cur1)); *result = t; for(++first, ++result; first != last && result != end_result; ++first, ++result) { auto && cur2 = val_i(*first); t = val_x(invoke(bop, t, invoke(proj, cur2))); *result = t; } } return {first, result}; } template auto operator()(I first, S last, O result, BOp bop = BOp{}, P proj = P{}) const -> CPP_ret(partial_sum_result)( // requires sentinel_for && partial_sum_constraints) { return (*this)(std::move(first), std::move(last), std::move(result), unreachable, std::move(bop), std::move(proj)); } template, typename O = uncvref_t> auto operator()(Rng && rng, ORef && result, BOp bop = BOp{}, P proj = P{}) const -> CPP_ret(partial_sum_result, O>)( // requires range && partial_sum_constraints) { return (*this)(begin(rng), end(rng), static_cast(result), std::move(bop), std::move(proj)); } template, typename O = iterator_t> auto operator()(Rng && rng, ORng && result, BOp bop = BOp{}, P proj = P{}) const -> CPP_ret( partial_sum_result, safe_iterator_t>)( // requires range && range && partial_sum_constraints) { return (*this)(begin(rng), end(rng), begin(result), end(result), std::move(bop), std::move(proj)); } }; RANGES_INLINE_VARIABLE(partial_sum_fn, partial_sum) /// @} } // namespace ranges #endif