/// \file // Range v3 library // // Copyright Eric Niebler 2004 // 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 // // Implementation based on the code in libc++ // http://http://libcxx.llvm.org/ #ifndef RANGES_V3_NUMERIC_ADJACENT_DIFFERENCE_HPP #define RANGES_V3_NUMERIC_ADJACENT_DIFFERENCE_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-numerics /// @{ // clang-format off CPP_def ( template(typename I, typename O, typename BOp = minus, typename P = identity) (concept differenceable)(I, O, BOp, P), input_iterator && invocable> && copy_constructible>>> && movable>>> && output_iterator>> && invocable>, invoke_result_t>> && output_iterator>, invoke_result_t>>> ); // clang-format on template using adjacent_difference_result = detail::in_out_result; struct adjacent_difference_fn { template auto operator()(I first, S last, O result, S2 end_result, BOp bop = BOp{}, P proj = P{}) const -> CPP_ret(adjacent_difference_result)( // requires sentinel_for && sentinel_for && differenceable) { // BUGBUG think about the use of coerce here. using V = iter_value_t; using X = invoke_result_t

; coerce v; coerce x; if(first != last && result != end_result) { auto t1(x(invoke(proj, v(*first)))); *result = t1; for(++first, ++result; first != last && result != end_result; ++first, ++result) { auto t2(x(invoke(proj, v(*first)))); *result = invoke(bop, t2, t1); t1 = std::move(t2); } } return {first, result}; } template auto operator()(I first, S last, O result, BOp bop = BOp{}, P proj = P{}) const -> CPP_ret(adjacent_difference_result)( // requires sentinel_for && differenceable) { 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(adjacent_difference_result, O>)( // requires range && differenceable) { 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(adjacent_difference_result, safe_iterator_t>)( // requires range && range && differenceable) { return (*this)(begin(rng), end(rng), begin(result), end(result), std::move(bop), std::move(proj)); } }; RANGES_INLINE_VARIABLE(adjacent_difference_fn, adjacent_difference) /// @} } // namespace ranges #endif