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.

136 lines
5.2KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2004
  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. // Implementation based on the code in libc++
  15. // http://http://libcxx.llvm.org/
  16. #ifndef RANGES_V3_NUMERIC_ADJACENT_DIFFERENCE_HPP
  17. #define RANGES_V3_NUMERIC_ADJACENT_DIFFERENCE_HPP
  18. #include <meta/meta.hpp>
  19. #include <range/v3/algorithm/result_types.hpp>
  20. #include <range/v3/functional/arithmetic.hpp>
  21. #include <range/v3/functional/identity.hpp>
  22. #include <range/v3/functional/invoke.hpp>
  23. #include <range/v3/iterator/concepts.hpp>
  24. #include <range/v3/iterator/traits.hpp>
  25. #include <range/v3/iterator/unreachable_sentinel.hpp>
  26. #include <range/v3/range/access.hpp>
  27. #include <range/v3/range/concepts.hpp>
  28. #include <range/v3/range/dangling.hpp>
  29. #include <range/v3/range/traits.hpp>
  30. #include <range/v3/utility/static_const.hpp>
  31. namespace ranges
  32. {
  33. /// \addtogroup group-numerics
  34. /// @{
  35. // clang-format off
  36. CPP_def
  37. (
  38. template(typename I, typename O, typename BOp = minus, typename P = identity)
  39. (concept differenceable)(I, O, BOp, P),
  40. input_iterator<I> &&
  41. invocable<P&, iter_value_t<I>> &&
  42. copy_constructible<uncvref_t<invoke_result_t<P&, iter_value_t<I>>>> &&
  43. movable<uncvref_t<invoke_result_t<P&, iter_value_t<I>>>> &&
  44. output_iterator<O, invoke_result_t<P&, iter_value_t<I>>> &&
  45. invocable<BOp&, invoke_result_t<P&, iter_value_t<I>>, invoke_result_t<P&, iter_value_t<I>>> &&
  46. output_iterator<O, invoke_result_t<BOp&, invoke_result_t<P&, iter_value_t<I>>, invoke_result_t<P&, iter_value_t<I>>>>
  47. );
  48. // clang-format on
  49. template<typename I, typename O>
  50. using adjacent_difference_result = detail::in_out_result<I, O>;
  51. struct adjacent_difference_fn
  52. {
  53. template<typename I, typename S, typename O, typename S2, typename BOp = minus,
  54. typename P = identity>
  55. auto operator()(I first, S last, O result, S2 end_result, BOp bop = BOp{},
  56. P proj = P{}) const
  57. -> CPP_ret(adjacent_difference_result<I, O>)( //
  58. requires sentinel_for<S, I> && sentinel_for<S2, O> &&
  59. differenceable<I, O, BOp, P>)
  60. {
  61. // BUGBUG think about the use of coerce here.
  62. using V = iter_value_t<I>;
  63. using X = invoke_result_t<P &, V>;
  64. coerce<V> v;
  65. coerce<X> x;
  66. if(first != last && result != end_result)
  67. {
  68. auto t1(x(invoke(proj, v(*first))));
  69. *result = t1;
  70. for(++first, ++result; first != last && result != end_result;
  71. ++first, ++result)
  72. {
  73. auto t2(x(invoke(proj, v(*first))));
  74. *result = invoke(bop, t2, t1);
  75. t1 = std::move(t2);
  76. }
  77. }
  78. return {first, result};
  79. }
  80. template<typename I, typename S, typename O, typename BOp = minus,
  81. typename P = identity>
  82. auto operator()(I first, S last, O result, BOp bop = BOp{}, P proj = P{}) const
  83. -> CPP_ret(adjacent_difference_result<I, O>)( //
  84. requires sentinel_for<S, I> && differenceable<I, O, BOp, P>)
  85. {
  86. return (*this)(std::move(first),
  87. std::move(last),
  88. std::move(result),
  89. unreachable,
  90. std::move(bop),
  91. std::move(proj));
  92. }
  93. template<typename Rng, typename ORef, typename BOp = minus, typename P = identity,
  94. typename I = iterator_t<Rng>, typename O = uncvref_t<ORef>>
  95. auto operator()(Rng && rng, ORef && result, BOp bop = BOp{}, P proj = P{}) const
  96. -> CPP_ret(adjacent_difference_result<safe_iterator_t<Rng>, O>)( //
  97. requires range<Rng> && differenceable<I, O, BOp, P>)
  98. {
  99. return (*this)(begin(rng),
  100. end(rng),
  101. static_cast<ORef &&>(result),
  102. std::move(bop),
  103. std::move(proj));
  104. }
  105. template<typename Rng, typename ORng, typename BOp = minus, typename P = identity,
  106. typename I = iterator_t<Rng>, typename O = iterator_t<ORng>>
  107. auto operator()(Rng && rng, ORng && result, BOp bop = BOp{}, P proj = P{}) const
  108. -> CPP_ret(adjacent_difference_result<safe_iterator_t<Rng>,
  109. safe_iterator_t<ORng>>)( //
  110. requires range<Rng> && range<ORng> && differenceable<I, O, BOp, P>)
  111. {
  112. return (*this)(begin(rng),
  113. end(rng),
  114. begin(result),
  115. end(result),
  116. std::move(bop),
  117. std::move(proj));
  118. }
  119. };
  120. RANGES_INLINE_VARIABLE(adjacent_difference_fn, adjacent_difference)
  121. /// @}
  122. } // namespace ranges
  123. #endif