// // immer: immutable data structures for C++ // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente // // This software is distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt // #pragma once #include #include #include namespace immer { /** * @defgroup algorithm * @{ */ /*@{*/ // Right now these algorithms dispatch directly to the vector // implementations unconditionally. This will be changed in the // future to support other kinds of containers. /*! * Apply operation `fn` for every contiguous *chunk* of data in the * range sequentially. Each time, `Fn` is passed two `value_type` * pointers describing a range over a part of the vector. This allows * iterating over the elements in the most efficient way. * * @rst * * .. tip:: This is a low level method. Most of the time, :doc:`other * wrapper algorithms ` should be used instead. * * @endrst */ template void for_each_chunk(const Range& r, Fn&& fn) { r.impl().for_each_chunk(std::forward(fn)); } template void for_each_chunk(const Iterator& first, const Iterator& last, Fn&& fn) { assert(&first.impl() == &last.impl()); first.impl().for_each_chunk( first.index(), last.index(), std::forward(fn)); } template void for_each_chunk(const T* first, const T* last, Fn&& fn) { std::forward(fn)(first, last); } /*! * Apply operation `fn` for every contiguous *chunk* of data in the * range sequentially, until `fn` returns `false`. Each time, `Fn` is * passed two `value_type` pointers describing a range over a part of * the vector. This allows iterating over the elements in the most * efficient way. * * @rst * * .. tip:: This is a low level method. Most of the time, :doc:`other * wrapper algorithms ` should be used instead. * * @endrst */ template bool for_each_chunk_p(const Range& r, Fn&& fn) { return r.impl().for_each_chunk_p(std::forward(fn)); } template bool for_each_chunk_p(const Iterator& first, const Iterator& last, Fn&& fn) { assert(&first.impl() == &last.impl()); return first.impl().for_each_chunk_p( first.index(), last.index(), std::forward(fn)); } template bool for_each_chunk_p(const T* first, const T* last, Fn&& fn) { return std::forward(fn)(first, last); } /*! * Equivalent of `std::accumulate` applied to the range `r`. */ template T accumulate(Range&& r, T init) { for_each_chunk(r, [&](auto first, auto last) { init = std::accumulate(first, last, init); }); return init; } template T accumulate(Range&& r, T init, Fn fn) { for_each_chunk(r, [&](auto first, auto last) { init = std::accumulate(first, last, init, fn); }); return init; } /*! * Equivalent of `std::accumulate` applied to the range @f$ [first, * last) @f$. */ template T accumulate(Iterator first, Iterator last, T init) { for_each_chunk(first, last, [&](auto first, auto last) { init = std::accumulate(first, last, init); }); return init; } template T accumulate(Iterator first, Iterator last, T init, Fn fn) { for_each_chunk(first, last, [&](auto first, auto last) { init = std::accumulate(first, last, init, fn); }); return init; } /*! * Equivalent of `std::for_each` applied to the range `r`. */ template Fn&& for_each(Range&& r, Fn&& fn) { for_each_chunk(r, [&](auto first, auto last) { for (; first != last; ++first) fn(*first); }); return std::forward(fn); } /*! * Equivalent of `std::for_each` applied to the range @f$ [first, * last) @f$. */ template Fn&& for_each(Iterator first, Iterator last, Fn&& fn) { for_each_chunk(first, last, [&](auto first, auto last) { for (; first != last; ++first) fn(*first); }); return std::forward(fn); } /*! * Equivalent of `std::copy` applied to the range `r`. */ template OutIter copy(Range&& r, OutIter out) { for_each_chunk( r, [&](auto first, auto last) { out = std::copy(first, last, out); }); return out; } /*! * Equivalent of `std::copy` applied to the range @f$ [first, * last) @f$. */ template OutIter copy(InIter first, InIter last, OutIter out) { for_each_chunk(first, last, [&](auto first, auto last) { out = std::copy(first, last, out); }); return out; } /*! * Equivalent of `std::all_of` applied to the range `r`. */ template bool all_of(Range&& r, Pred p) { return for_each_chunk_p( r, [&](auto first, auto last) { return std::all_of(first, last, p); }); } /*! * Equivalent of `std::all_of` applied to the range @f$ [first, last) * @f$. */ template bool all_of(Iter first, Iter last, Pred p) { return for_each_chunk_p(first, last, [&](auto first, auto last) { return std::all_of(first, last, p); }); } /** @} */ // group: algorithm } // namespace immer