You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
5.7KB

  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. namespace ranges
  31. {
  32. /// \addtogroup group-numerics
  33. /// @{
  34. /// \cond
  35. namespace detail
  36. {
  37. // Only needed for type-checking purposes:
  38. struct as_lvalue_fn
  39. {
  40. template<typename T>
  41. constexpr T & operator()(T && t) const noexcept
  42. {
  43. return t;
  44. }
  45. };
  46. template<typename I>
  47. using as_value_type_t = composed<as_lvalue_fn, coerce<iter_value_t<I>>>;
  48. } // namespace detail
  49. /// \endcond
  50. // axiom: BOp is associative over values of I.
  51. // clang-format off
  52. CPP_def
  53. (
  54. template(typename I, typename BOp)
  55. concept indirect_semigroup,
  56. readable<I> &&
  57. copyable<iter_value_t<I>> &&
  58. indirectly_regular_binary_invocable_<
  59. composed<coerce<iter_value_t<I>>, BOp>,
  60. iter_value_t<I>*, I>
  61. );
  62. CPP_def
  63. (
  64. template(typename I, typename O, typename BOp = plus, typename P = identity)
  65. (concept partial_sum_constraints)(I, O, BOp, P),
  66. input_iterator<I> &&
  67. indirect_semigroup<
  68. projected<projected<I, detail::as_value_type_t<I>>, P>,
  69. BOp> &&
  70. output_iterator<
  71. O,
  72. iter_value_t<
  73. projected<projected<I, detail::as_value_type_t<I>>, P>> const &>
  74. );
  75. // clang-format on
  76. template<typename I, typename O>
  77. using partial_sum_result = detail::in_out_result<I, O>;
  78. struct partial_sum_fn
  79. {
  80. template<typename I, typename S1, typename O, typename S2, typename BOp = plus,
  81. typename P = identity>
  82. auto operator()(I first, S1 last, O result, S2 end_result, BOp bop = BOp{},
  83. P proj = P{}) const -> CPP_ret(partial_sum_result<I, O>)( //
  84. requires sentinel_for<S1, I> && sentinel_for<S2, O> &&
  85. partial_sum_constraints<I, O, BOp, P>)
  86. {
  87. using X = projected<projected<I, detail::as_value_type_t<I>>, P>;
  88. coerce<iter_value_t<I>> val_i;
  89. coerce<iter_value_t<X>> val_x;
  90. if(first != last && result != end_result)
  91. {
  92. auto && cur1 = val_i(*first);
  93. iter_value_t<X> t(invoke(proj, cur1));
  94. *result = t;
  95. for(++first, ++result; first != last && result != end_result;
  96. ++first, ++result)
  97. {
  98. auto && cur2 = val_i(*first);
  99. t = val_x(invoke(bop, t, invoke(proj, cur2)));
  100. *result = t;
  101. }
  102. }
  103. return {first, result};
  104. }
  105. template<typename I, typename S, typename O, typename BOp = plus,
  106. typename P = identity>
  107. auto operator()(I first, S last, O result, BOp bop = BOp{}, P proj = P{}) const
  108. -> CPP_ret(partial_sum_result<I, O>)( //
  109. requires sentinel_for<S, I> && partial_sum_constraints<I, O, BOp, P>)
  110. {
  111. return (*this)(std::move(first),
  112. std::move(last),
  113. std::move(result),
  114. unreachable,
  115. std::move(bop),
  116. std::move(proj));
  117. }
  118. template<typename Rng, typename ORef, typename BOp = plus, typename P = identity,
  119. typename I = iterator_t<Rng>, typename O = uncvref_t<ORef>>
  120. auto operator()(Rng && rng, ORef && result, BOp bop = BOp{}, P proj = P{}) const
  121. -> CPP_ret(partial_sum_result<safe_iterator_t<Rng>, O>)( //
  122. requires range<Rng> && partial_sum_constraints<I, O, BOp, P>)
  123. {
  124. return (*this)(begin(rng),
  125. end(rng),
  126. static_cast<ORef &&>(result),
  127. std::move(bop),
  128. std::move(proj));
  129. }
  130. template<typename Rng, typename ORng, typename BOp = plus, typename P = identity,
  131. typename I = iterator_t<Rng>, typename O = iterator_t<ORng>>
  132. auto operator()(Rng && rng, ORng && result, BOp bop = BOp{}, P proj = P{}) const
  133. -> CPP_ret(
  134. partial_sum_result<safe_iterator_t<Rng>, safe_iterator_t<ORng>>)( //
  135. requires range<Rng> && range<ORng> &&
  136. partial_sum_constraints<I, O, BOp, P>)
  137. {
  138. return (*this)(begin(rng),
  139. end(rng),
  140. begin(result),
  141. end(result),
  142. std::move(bop),
  143. std::move(proj));
  144. }
  145. };
  146. RANGES_INLINE_VARIABLE(partial_sum_fn, partial_sum)
  147. /// @}
  148. } // namespace ranges
  149. #endif