partial_sum.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. // Copyright Gonzalo Brito Gadeschi 2014
  6. //
  7. // Use, modification and distribution is subject to the
  8. // Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. //
  12. // Project home: https://github.com/ericniebler/range-v3
  13. //
  14. #ifndef RANGES_V3_NUMERIC_PARTIAL_SUM_HPP
  15. #define RANGES_V3_NUMERIC_PARTIAL_SUM_HPP
  16. #include <meta/meta.hpp>
  17. #include <range/v3/algorithm/result_types.hpp>
  18. #include <range/v3/functional/arithmetic.hpp>
  19. #include <range/v3/functional/compose.hpp>
  20. #include <range/v3/functional/identity.hpp>
  21. #include <range/v3/functional/invoke.hpp>
  22. #include <range/v3/iterator/concepts.hpp>
  23. #include <range/v3/iterator/traits.hpp>
  24. #include <range/v3/iterator/unreachable_sentinel.hpp>
  25. #include <range/v3/range/access.hpp>
  26. #include <range/v3/range/concepts.hpp>
  27. #include <range/v3/range/dangling.hpp>
  28. #include <range/v3/range/traits.hpp>
  29. #include <range/v3/utility/static_const.hpp>
  30. #include <range/v3/detail/prologue.hpp>
  31. namespace ranges
  32. {
  33. /// \addtogroup group-numerics
  34. /// @{
  35. /// \cond
  36. namespace detail
  37. {
  38. // Only needed for type-checking purposes:
  39. struct as_lvalue_fn
  40. {
  41. template<typename T>
  42. constexpr T & operator()(T && t) const noexcept
  43. {
  44. return t;
  45. }
  46. };
  47. template<typename I>
  48. using as_value_type_t = composed<as_lvalue_fn, coerce<iter_value_t<I>>>;
  49. } // namespace detail
  50. /// \endcond
  51. // axiom: BOp is associative over values of I.
  52. // clang-format off
  53. /// \concept indirect_semigroup_
  54. /// \brief The \c indirect_semigroup_ concept
  55. template(typename I, typename BOp)(
  56. concept (indirect_semigroup_)(I, BOp),
  57. copyable<iter_value_t<I>> AND
  58. indirectly_regular_binary_invocable_<
  59. composed<coerce<iter_value_t<I>>, BOp>,
  60. iter_value_t<I>*, I>
  61. );
  62. /// \concept indirect_semigroup
  63. /// \brief The \c indirect_semigroup concept
  64. template<typename I, typename BOp>
  65. CPP_concept indirect_semigroup =
  66. indirectly_readable<I> &&
  67. CPP_concept_ref(ranges::indirect_semigroup_, I, BOp);
  68. /// \concept partial_sum_constraints_
  69. /// \brief The \c partial_sum_constraints_ concept
  70. template(typename I, typename O, typename BOp, typename P)(
  71. concept (partial_sum_constraints_)(I, O, BOp, P),
  72. indirect_semigroup<
  73. projected<projected<I, detail::as_value_type_t<I>>, P>,
  74. BOp> AND
  75. output_iterator<
  76. O,
  77. iter_value_t<
  78. projected<projected<I, detail::as_value_type_t<I>>, P>> const &>
  79. );
  80. /// \concept partial_sum_constraints
  81. /// \brief The \c partial_sum_constraints concept
  82. template<typename I, typename O, typename BOp = plus, typename P = identity>
  83. CPP_concept partial_sum_constraints =
  84. input_iterator<I> &&
  85. CPP_concept_ref(ranges::partial_sum_constraints_, I, O, BOp, P);
  86. // clang-format on
  87. template<typename I, typename O>
  88. using partial_sum_result = detail::in_out_result<I, O>;
  89. struct partial_sum_fn
  90. {
  91. template(typename I, typename S1, typename O, typename S2, typename BOp = plus,
  92. typename P = identity)(
  93. requires sentinel_for<S1, I> AND sentinel_for<S2, O> AND
  94. partial_sum_constraints<I, O, BOp, P>)
  95. partial_sum_result<I, O> operator()(I first,
  96. S1 last,
  97. O result,
  98. S2 end_result,
  99. BOp bop = BOp{},
  100. P proj = P{}) const
  101. {
  102. using X = projected<projected<I, detail::as_value_type_t<I>>, P>;
  103. coerce<iter_value_t<I>> val_i;
  104. coerce<iter_value_t<X>> val_x;
  105. if(first != last && result != end_result)
  106. {
  107. auto && cur1 = val_i(*first);
  108. iter_value_t<X> t(invoke(proj, cur1));
  109. *result = t;
  110. for(++first, ++result; first != last && result != end_result;
  111. ++first, ++result)
  112. {
  113. auto && cur2 = val_i(*first);
  114. t = val_x(invoke(bop, t, invoke(proj, cur2)));
  115. *result = t;
  116. }
  117. }
  118. return {first, result};
  119. }
  120. template(typename I, typename S, typename O, typename BOp = plus,
  121. typename P = identity)(
  122. requires sentinel_for<S, I> AND partial_sum_constraints<I, O, BOp, P>)
  123. partial_sum_result<I, O> //
  124. operator()(I first, S last, O result, BOp bop = BOp{}, P proj = P{}) const
  125. {
  126. return (*this)(std::move(first),
  127. std::move(last),
  128. std::move(result),
  129. unreachable,
  130. std::move(bop),
  131. std::move(proj));
  132. }
  133. template(typename Rng, typename ORef, typename BOp = plus, typename P = identity,
  134. typename I = iterator_t<Rng>, typename O = uncvref_t<ORef>)(
  135. requires range<Rng> AND partial_sum_constraints<I, O, BOp, P>)
  136. partial_sum_result<borrowed_iterator_t<Rng>, O> //
  137. operator()(Rng && rng, ORef && result, BOp bop = BOp{}, P proj = P{}) const
  138. {
  139. return (*this)(begin(rng),
  140. end(rng),
  141. static_cast<ORef &&>(result),
  142. std::move(bop),
  143. std::move(proj));
  144. }
  145. template(typename Rng, typename ORng, typename BOp = plus, typename P = identity,
  146. typename I = iterator_t<Rng>, typename O = iterator_t<ORng>)(
  147. requires range<Rng> AND range<ORng> AND partial_sum_constraints<I, O, BOp, P>)
  148. partial_sum_result<borrowed_iterator_t<Rng>, borrowed_iterator_t<ORng>> //
  149. operator()(Rng && rng, ORng && result, BOp bop = BOp{}, P proj = P{}) const
  150. {
  151. return (*this)(begin(rng),
  152. end(rng),
  153. begin(result),
  154. end(result),
  155. std::move(bop),
  156. std::move(proj));
  157. }
  158. };
  159. RANGES_INLINE_VARIABLE(partial_sum_fn, partial_sum)
  160. /// @}
  161. } // namespace ranges
  162. #include <range/v3/detail/epilogue.hpp>
  163. #endif