init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP
#define RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(adjacent_find)
/// \brief function template \c adjacent_find
///
/// range-based version of the \c adjacent_find std algorithm
///
/// \pre `Rng` is a model of the `range` concept
/// \pre `C` is a model of the `BinaryPredicate` concept
template(typename I, typename S, typename C = equal_to, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<C, projected<I, P>>)
constexpr I RANGES_FUNC(adjacent_find)(I first, S last, C pred = C{}, P proj = P{})
{
if(first == last)
return first;
auto inext = first;
for(; ++inext != last; first = inext)
if(invoke(pred, invoke(proj, *first), invoke(proj, *inext)))
return first;
return inext;
}
/// \overload
template(typename Rng, typename C = equal_to, typename P = identity)(
requires forward_range<Rng> AND
indirect_relation<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(adjacent_find)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(adjacent_find)
namespace cpp20
{
using ranges::adjacent_find;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGE_ALGORITHM_ADJACENT_FIND_HPP

View File

@@ -0,0 +1,92 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler
// Copyright Christopher Di Bella
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP
#define RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP
#include <functional>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/adjacent_find.hpp>
#include <range/v3/algorithm/move.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/move.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(adjacent_remove_if)
/// \brief function \c adjacent_remove_if
///
/// range-based version of the \c adjacent_remove_if algorithm
///
/// \pre `Rng` is a model of the `forward_range` concept.
/// \pre `Pred` is a model of the `BinaryPredicate` concept.
template(typename I, typename S, typename Pred, typename Proj = identity)(
requires permutable<I> AND sentinel_for<S, I> AND
indirect_relation<Pred, projected<I, Proj>>)
constexpr I RANGES_FUNC(adjacent_remove_if)(I first, S last, Pred pred = {}, Proj proj = {})
{
first = adjacent_find(std::move(first), last, ranges::ref(pred), ranges::ref(proj));
if(first == last)
return first;
auto i = first;
for(auto j = ++i; ++j != last; ++i)
{
if(!invoke(pred, invoke(proj, *i), invoke(proj, *j)))
{
*first = iter_move(i);
++first;
}
}
*first = iter_move(i);
++first;
return first;
}
/// \overload
template(typename Rng, typename Pred, typename Proj = identity)(
requires forward_range<Rng> AND
indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> AND
permutable<iterator_t<Rng>>)
constexpr borrowed_iterator_t<Rng>
RANGES_FUNC(adjacent_remove_if)(Rng && rng, Pred pred, Proj proj = {}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(adjacent_remove_if)
namespace cpp20
{
using ranges::adjacent_remove_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP

View File

@@ -0,0 +1,69 @@
/// \file
// Range v3 library
//
// Copyright Andrew Sutton 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
//
#ifndef RANGES_V3_ALGORITHM_ALL_OF_HPP
#define RANGES_V3_ALGORITHM_ALL_OF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(all_of)
/// \brief function template \c all_of
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr bool RANGES_FUNC(all_of)(I first, S last, F pred, P proj = P{}) //
{
for(; first != last; ++first)
if(!invoke(pred, invoke(proj, *first)))
break;
return first == last;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(all_of)(Rng && rng, F pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(all_of)
namespace cpp20
{
using ranges::all_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,70 @@
/// \file
// Range v3 library
//
// Copyright Andrew Sutton 2014
// 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
//
#ifndef RANGES_V3_ALGORITHM_ANY_OF_HPP
#define RANGES_V3_ALGORITHM_ANY_OF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(any_of)
/// \brief function template \c any_of
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr bool RANGES_FUNC(any_of)(I first, S last, F pred, P proj = P{}) //
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
return true;
return false;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(any_of)(Rng && rng, F pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(any_of)
namespace cpp20
{
using ranges::any_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,92 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP
#define RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP
#include <functional>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/lower_bound_n.hpp>
#include <range/v3/algorithm/aux_/upper_bound_n.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/functional/reference_wrapper.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct equal_range_n_fn
{
template(typename I, typename V, typename R = less, typename P = identity)(
requires forward_iterator<I> AND
indirect_strict_weak_order<R, V const *, projected<I, P>>)
constexpr subrange<I> operator()(I first,
iter_difference_t<I> dist,
V const & val,
R pred = R{},
P proj = P{}) const
{
if(0 < dist)
{
do
{
auto half = dist / 2;
auto middle = ranges::next(first, half);
auto && v = *middle;
auto && pv = invoke(proj, (decltype(v) &&)v);
if(invoke(pred, pv, val))
{
first = std::move(++middle);
dist -= half + 1;
}
else if(invoke(pred, val, pv))
{
dist = half;
}
else
{
return {lower_bound_n(std::move(first),
half,
val,
ranges::ref(pred),
ranges::ref(proj)),
upper_bound_n(ranges::next(middle),
dist - (half + 1),
val,
ranges::ref(pred),
ranges::ref(proj))};
}
} while(0 != dist);
}
return {first, first};
}
};
RANGES_INLINE_VARIABLE(equal_range_n_fn, equal_range_n)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,82 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_AUX_LOWER_BOUND_N_HPP
#define RANGES_V3_ALGORITHM_AUX_LOWER_BOUND_N_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/partition_point_n.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
// [&](auto&& i){ return invoke(pred, i, val); }
template<typename Pred, typename Val>
struct lower_bound_predicate
{
Pred & pred_;
Val & val_;
template<typename T>
constexpr bool operator()(T && t) const
{
return invoke(pred_, static_cast<T &&>(t), val_);
}
};
template<typename Pred, typename Val>
constexpr lower_bound_predicate<Pred, Val> make_lower_bound_predicate(Pred & pred,
Val & val)
{
return {pred, val};
}
} // namespace detail
/// \endcond
namespace aux
{
struct lower_bound_n_fn
{
template(typename I, typename V, typename C = less, typename P = identity)(
requires forward_iterator<I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr I operator()(I first,
iter_difference_t<I> d,
V const & val,
C pred = C{},
P proj = P{}) const
{
return partition_point_n(std::move(first),
d,
detail::make_lower_bound_predicate(pred, val),
std::move(proj));
}
};
RANGES_INLINE_VARIABLE(lower_bound_n_fn, lower_bound_n)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,115 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
// Copyright (c) 2009 Alexander Stepanov and Paul McJones
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation. The authors make no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.
//
// Algorithms from
// Elements of Programming
// by Alexander Stepanov and Paul McJones
// Addison-Wesley Professional, 2009
#ifndef RANGES_V3_ALGORITHM_AUX_MERGE_N_HPP
#define RANGES_V3_ALGORITHM_AUX_MERGE_N_HPP
#include <tuple>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/copy_n.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
template<typename I0, typename I1, typename O>
using merge_n_result = detail::in1_in2_out_result<I0, I1, O>;
struct merge_n_fn
{
template(typename I0, typename I1, typename O, typename C = less,
typename P0 = identity, typename P1 = identity)(
requires mergeable<I0, I1, O, C, P0, P1>)
merge_n_result<I0, I1, O> operator()(I0 begin0,
iter_difference_t<I0> n0,
I1 begin1,
iter_difference_t<I1> n1,
O out,
C r = C{},
P0 p0 = P0{},
P1 p1 = P1{}) const
{
using T = merge_n_result<I0, I1, O>;
auto n0orig = n0;
auto n1orig = n1;
auto b0 = uncounted(begin0);
auto b1 = uncounted(begin1);
while(true)
{
if(0 == n0)
{
auto res = copy_n(b1, n1, out);
begin0 = recounted(begin0, b0, n0orig);
begin1 = recounted(begin1, res.in, n1orig);
return T{begin0, begin1, res.out};
}
if(0 == n1)
{
auto res = copy_n(b0, n0, out);
begin0 = recounted(begin0, res.in, n0orig);
begin1 = recounted(begin1, b1, n1orig);
return T{begin0, begin1, res.out};
}
if(invoke(r, invoke(p1, *b1), invoke(p0, *b0)))
{
*out = *b1;
++b1;
++out;
--n1;
}
else
{
*out = *b0;
++b0;
++out;
--n0;
}
}
}
};
RANGES_INLINE_VARIABLE(merge_n_fn, merge_n)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,74 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
// Copyright (c) 2009 Alexander Stepanov and Paul McJones
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation. The authors make no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.
//
// Algorithms from
// Elements of Programming
// by Alexander Stepanov and Paul McJones
// Addison-Wesley Professional, 2009
#ifndef RANGES_V3_ALGORITHM_AUX_MERGE_N_WITH_BUFFER_HPP
#define RANGES_V3_ALGORITHM_AUX_MERGE_N_WITH_BUFFER_HPP
#include <tuple>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/merge_n.hpp>
#include <range/v3/algorithm/copy_n.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct merge_n_with_buffer_fn
{
template(typename I, typename B, typename C = less, typename P = identity)(
requires same_as<iter_common_reference_t<I>,
iter_common_reference_t<B>> AND
indirectly_copyable<I, B> AND mergeable<B, I, I, C, P, P>)
I operator()(I begin0,
iter_difference_t<I> n0,
I begin1,
iter_difference_t<I> n1,
B buff,
C r = C{},
P p = P{}) const
{
copy_n(begin0, n0, buff);
return merge_n(buff, n0, begin1, n1, begin0, r, p, p).out;
}
};
RANGES_INLINE_VARIABLE(merge_n_with_buffer_fn, merge_n_with_buffer)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,65 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_AUX_PARTITION_POINT_N_HPP
#define RANGES_V3_ALGORITHM_AUX_PARTITION_POINT_N_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct partition_point_n_fn
{
template(typename I, typename C, typename P = identity)(
requires forward_iterator<I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr I operator()(I first,
iter_difference_t<I> d,
C pred,
P proj = P{}) const //
{
if(0 < d)
{
do
{
auto half = d / 2;
auto middle = next(uncounted(first), half);
if(invoke(pred, invoke(proj, *middle)))
{
first = recounted(first, std::move(++middle), half + 1);
d -= half + 1;
}
else
d = half;
} while(0 != d);
}
return first;
}
};
RANGES_INLINE_VARIABLE(partition_point_n_fn, partition_point_n)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,73 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
// Copyright (c) 2009 Alexander Stepanov and Paul McJones
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation. The authors make no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.
//
// Algorithms from
// Elements of Programming
// by Alexander Stepanov and Paul McJones
// Addison-Wesley Professional, 2009
#ifndef RANGES_V3_ALGORITHM_AUX_SORT_N_WITH_BUFFER_HPP
#define RANGES_V3_ALGORITHM_AUX_SORT_N_WITH_BUFFER_HPP
#include <tuple>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/merge_n_with_buffer.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace aux
{
struct sort_n_with_buffer_fn
{
template(typename I, typename B, typename C = less, typename P = identity)(
requires same_as<iter_common_reference_t<I>,
iter_common_reference_t<B>> AND
indirectly_copyable<I, B> AND mergeable<B, I, I, C, P, P>)
I operator()(I first, iter_difference_t<I> n, B buff, C r = C{}, P p = P{})
const
{
auto half = n / 2;
if(0 == half)
return next(first, n);
I m = (*this)(first, half, buff, r, p);
(*this)(m, n - half, buff, r, p);
return merge_n_with_buffer(first, half, m, n - half, buff, r, p);
}
};
RANGES_INLINE_VARIABLE(sort_n_with_buffer_fn, sort_n_with_buffer)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,87 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_AUX_UPPER_BOUND_N_HPP
#define RANGES_V3_ALGORITHM_AUX_UPPER_BOUND_N_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/partition_point_n.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
// [&](auto&& i){ return !invoke(pred, val, i); }
template<typename Pred, typename Val>
struct upper_bound_predicate
{
Pred & pred_;
Val & val_;
template<typename T>
constexpr bool operator()(T && t) const
{
return !invoke(pred_, val_, static_cast<T &&>(t));
}
};
template<typename Pred, typename Val>
constexpr upper_bound_predicate<Pred, Val> make_upper_bound_predicate(Pred & pred,
Val & val)
{
return {pred, val};
}
} // namespace detail
/// \endcond
namespace aux
{
struct upper_bound_n_fn
{
/// \brief template function upper_bound
///
/// range-based version of the `upper_bound` std algorithm
///
/// \pre `Rng` is a model of the `range` concept
template(typename I, typename V, typename C = less, typename P = identity)(
requires forward_iterator<I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr I operator()(I first,
iter_difference_t<I> d,
V const & val,
C pred = C{},
P proj = P{}) const
{
return partition_point_n(std::move(first),
d,
detail::make_upper_bound_predicate(pred, val),
std::move(proj));
}
};
RANGES_INLINE_VARIABLE(upper_bound_n_fn, upper_bound_n)
} // namespace aux
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,81 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_BINARY_SEARCH_HPP
#define RANGES_V3_ALGORITHM_BINARY_SEARCH_HPP
#include <functional>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/lower_bound.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(binary_search)
/// \brief function template \c binary_search
///
/// range-based version of the \c binary_search std algorithm
///
/// \pre `Rng` is a model of the `range` concept
template(typename I,
typename S,
typename V,
typename C = less,
typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr bool RANGES_FUNC(binary_search)(
I first, S last, V const & val, C pred = C{}, P proj = P{})
{
first =
lower_bound(std::move(first), last, val, ranges::ref(pred), ranges::ref(proj));
return first != last && !invoke(pred, val, invoke(proj, *first));
}
/// \overload
template(typename Rng, typename V, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(binary_search)(
Rng && rng, V const & val, C pred = C{}, P proj = P{}) //
{
static_assert(!is_infinite<Rng>::value,
"Trying to binary search an infinite range");
return (*this)(begin(rng), end(rng), val, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(binary_search)
namespace cpp20
{
using ranges::binary_search;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,60 @@
/// \file
// Range v3 library
//
// Copyright Johel Guerrero 2019
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_CONTAINS_HPP
#define RANGES_V3_ALGORITHM_CONTAINS_HPP
#include <utility>
#include <concepts/concepts.hpp>
#include <range/v3/algorithm/find.hpp>
#include <range/v3/detail/config.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(contains)
/// \brief function template \c contains
template(typename I, typename S, typename T, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<equal_to, projected<I, P>, const T *>)
constexpr bool RANGES_FUNC(contains)(I first, S last, const T & val, P proj = {})
{
return find(std::move(first), last, val, std::move(proj)) != last;
}
/// \overload
template(typename Rng, typename T, typename P = identity)(
requires input_range<Rng> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, const T *>)
constexpr bool RANGES_FUNC(contains)(Rng && rng, const T & val, P proj = {})
{
return (*this)(begin(rng), end(rng), val, std::move(proj));
}
RANGES_FUNC_END(contains)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ALGORITHM_CONTAINS_HPP

View File

@@ -0,0 +1,89 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_COPY_HPP
#define RANGES_V3_ALGORITHM_COPY_HPP
#include <functional>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/copy.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using copy_result = detail::in_out_result<I, O>;
RANGES_HIDDEN_DETAIL(namespace _copy CPP_PP_LBRACE())
RANGES_FUNC_BEGIN(copy)
/// \brief function template \c copy
template(typename I, typename S, typename O)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirectly_copyable<I, O>)
constexpr copy_result<I, O> RANGES_FUNC(copy)(I first, S last, O out) //
{
for(; first != last; ++first, ++out)
*out = *first;
return {first, out};
}
/// \overload
template(typename Rng, typename O)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr copy_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(copy)(Rng && rng, O out) //
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(copy)
RANGES_HIDDEN_DETAIL(CPP_PP_RBRACE())
#ifndef RANGES_DOXYGEN_INVOKED
struct copy_fn
: aux::copy_fn
, _copy::copy_fn
{
using aux::copy_fn::operator();
using _copy::copy_fn::operator();
};
RANGES_INLINE_VARIABLE(copy_fn, copy)
#endif
namespace cpp20
{
using ranges::copy_result;
using ranges::RANGES_HIDDEN_DETAIL(_copy::) copy;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,74 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_COPY_BACKWARD_HPP
#define RANGES_V3_ALGORITHM_COPY_BACKWARD_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using copy_backward_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(copy_backward)
/// \brief function template \c copy_backward
template(typename I, typename S, typename O)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
bidirectional_iterator<O> AND indirectly_copyable<I, O>)
constexpr copy_backward_result<I, O> RANGES_FUNC(copy_backward)(I first, S end_, O out)
{
I i = ranges::next(first, end_), last = i;
while(first != i)
*--out = *--i;
return {last, out};
}
/// \overload
template(typename Rng, typename O)(
requires bidirectional_range<Rng> AND bidirectional_iterator<O> AND
indirectly_copyable<iterator_t<Rng>, O>)
copy_backward_result<borrowed_iterator_t<Rng>, O> //
constexpr RANGES_FUNC(copy_backward)(Rng && rng, O out)
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(copy_backward)
namespace cpp20
{
using ranges::copy_backward;
using ranges::copy_backward_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,88 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_COPY_IF_HPP
#define RANGES_V3_ALGORITHM_COPY_IF_HPP
#include <functional>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using copy_if_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(copy_if)
/// \brief function template \c copy_if
template(typename I, typename S, typename O, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND
indirect_unary_predicate<F, projected<I, P>> AND
indirectly_copyable<I, O>)
constexpr copy_if_result<I, O> //
RANGES_FUNC(copy_if)(I first, S last, O out, F pred, P proj = P{}) //
{
for(; first != last; ++first)
{
auto && x = *first;
if(invoke(pred, invoke(proj, x)))
{
*out = (decltype(x) &&)x;
++out;
}
}
return {first, out};
}
/// \overload
template(typename Rng, typename O, typename F, typename P = identity)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr copy_if_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(copy_if)(Rng && rng, O out, F pred, P proj = P{})
{
return (*this)(
begin(rng), end(rng), std::move(out), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(copy_if)
namespace cpp20
{
using ranges::copy_if;
using ranges::copy_if_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,69 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_COPY_N_HPP
#define RANGES_V3_ALGORITHM_COPY_N_HPP
#include <functional>
#include <tuple>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using copy_n_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(copy_n)
/// \brief function template \c copy_n
template(typename I, typename O, typename P = identity)(
requires input_iterator<I> AND weakly_incrementable<O> AND
indirectly_copyable<I, O>)
constexpr copy_n_result<I, O> RANGES_FUNC(copy_n)(I first, iter_difference_t<I> n, O out)
{
RANGES_EXPECT(0 <= n);
auto norig = n;
auto b = uncounted(first);
for(; n != 0; ++b, ++out, --n)
*out = *b;
return {recounted(first, b, norig), out};
}
RANGES_FUNC_END(copy_n)
namespace cpp20
{
using ranges::copy_n;
using ranges::copy_n_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,72 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_COUNT_HPP
#define RANGES_V3_ALGORITHM_COUNT_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(count)
/// \brief function template \c count
template(typename I, typename S, typename V, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<equal_to, projected<I, P>, V const *>)
constexpr iter_difference_t<I> //
RANGES_FUNC(count)(I first, S last, V const & val, P proj = P{})
{
iter_difference_t<I> n = 0;
for(; first != last; ++first)
if(invoke(proj, *first) == val)
++n;
return n;
}
/// \overload
template(typename Rng, typename V, typename P = identity)(
requires input_range<Rng> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>)
constexpr iter_difference_t<iterator_t<Rng>> //
RANGES_FUNC(count)(Rng && rng, V const & val, P proj = P{})
{
return (*this)(begin(rng), end(rng), val, std::move(proj));
}
RANGES_FUNC_END(count)
namespace cpp20
{
using ranges::count;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,71 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_COUNT_IF_HPP
#define RANGES_V3_ALGORITHM_COUNT_IF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(count_if)
/// \brief function template \c count_if
template(typename I, typename S, typename R, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<R, projected<I, P>>)
constexpr iter_difference_t<I> RANGES_FUNC(count_if)(I first, S last, R pred, P proj = P{})
{
iter_difference_t<I> n = 0;
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
++n;
return n;
}
/// \overload
template(typename Rng, typename R, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<R, projected<iterator_t<Rng>, P>>)
constexpr iter_difference_t<iterator_t<Rng>> //
RANGES_FUNC(count_if)(Rng && rng, R pred, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(count_if)
namespace cpp20
{
using ranges::count_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,100 @@
/// \file
// Range v3 library
//
// Copyright Johel Guerrero 2019
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_ENDS_WITH_HPP
#define RANGES_V3_ALGORITHM_ENDS_WITH_HPP
#include <utility>
#include <concepts/concepts.hpp>
#include <range/v3/algorithm/equal.hpp>
#include <range/v3/detail/config.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(ends_with)
/// \brief function template \c ends_with
template(typename I0,
typename S0,
typename I1,
typename S1,
typename C = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires ((forward_iterator<I0> && sentinel_for<S0, I0>) ||
(input_iterator<I0> && sized_sentinel_for<S0, I0>)) AND
((forward_iterator<I1> && sentinel_for<S1, I1>) ||
(input_iterator<I1> && sized_sentinel_for<S1, I1>)) AND
indirectly_comparable<I0, I1, C, P0, P1>)
constexpr bool RANGES_FUNC(ends_with)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
const auto drop = distance(begin0, end0) - distance(begin1, end1);
if(drop < 0)
return false;
return equal(next(std::move(begin0), drop),
std::move(end0),
std::move(begin1),
std::move(end1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
/// \overload
template(typename Rng0,
typename Rng1,
typename C = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires (forward_range<Rng0> || (input_range<Rng0> && sized_range<Rng0>)) AND
(forward_range<Rng1> || (input_range<Rng1> && sized_range<Rng1>)) AND
indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>)
constexpr bool RANGES_FUNC(ends_with)(
Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) //
{
const auto drop = distance(rng0) - distance(rng1);
if(drop < 0)
return false;
return equal(next(begin(rng0), drop),
end(rng0),
begin(rng1),
end(rng1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(ends_with)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,175 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_EQUAL_HPP
#define RANGES_V3_ALGORITHM_EQUAL_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I0, typename S0, typename I1, typename S1, typename C,
typename P0, typename P1>
constexpr bool equal_nocheck(I0 begin0, S0 end0, I1 begin1, S1 end1, C pred,
P0 proj0, P1 proj1)
{
for(; begin0 != end0 && begin1 != end1; ++begin0, ++begin1)
if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1)))
return false;
return begin0 == end0 && begin1 == end1;
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(equal)
/// \brief function template \c equal
template(typename I0,
typename S0,
typename I1,
typename C = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND indirectly_comparable<I0, I1, C, P0, P1>)
RANGES_DEPRECATED(
"Use the variant of ranges::equal that takes an upper bound for "
"both sequences")
constexpr bool RANGES_FUNC(equal)(I0 begin0,
S0 end0,
I1 begin1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
for(; begin0 != end0; ++begin0, ++begin1)
if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1)))
return false;
return true;
}
/// \overload
template(typename I0,
typename S0,
typename I1,
typename S1,
typename C = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND sentinel_for<S1, I1> AND
indirectly_comparable<I0, I1, C, P0, P1>)
constexpr bool RANGES_FUNC(equal)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S0, I0> &&
sized_sentinel_for<S1, I1>))
if(distance(begin0, end0) != distance(begin1, end1))
return false;
return detail::equal_nocheck(std::move(begin0),
std::move(end0),
std::move(begin1),
std::move(end1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
/// \overload
template(typename Rng0,
typename I1Ref,
typename C = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires input_range<Rng0> AND input_iterator<uncvref_t<I1Ref>> AND
indirectly_comparable<iterator_t<Rng0>, uncvref_t<I1Ref>, C, P0, P1>)
RANGES_DEPRECATED(
"Use the variant of ranges::equal that takes an upper bound for "
"both sequences")
constexpr bool RANGES_FUNC(equal)(Rng0 && rng0,
I1Ref && begin1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
return (*this)(begin(rng0),
end(rng0),
(I1Ref &&) begin1,
std::move(pred),
std::move(proj0),
std::move(proj1));
RANGES_DIAGNOSTIC_POP
}
/// \overload
template(typename Rng0,
typename Rng1,
typename C = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires input_range<Rng0> AND input_range<Rng1> AND
indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>)
constexpr bool RANGES_FUNC(equal)(
Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) //
{
if(RANGES_CONSTEXPR_IF(sized_range<Rng0> && sized_range<Rng1>))
if(distance(rng0) != distance(rng1))
return false;
return detail::equal_nocheck(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(equal)
namespace cpp20
{
using ranges::equal;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,130 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP
#define RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/equal_range_n.hpp>
#include <range/v3/algorithm/aux_/lower_bound_n.hpp>
#include <range/v3/algorithm/upper_bound.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(equal_range)
/// \brief function template \c equal_range
template(typename I,
typename S,
typename V,
typename C = less,
typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr subrange<I> RANGES_FUNC(equal_range)(
I first, S last, V const & val, C pred = C{}, P proj = P{})
{
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S, I>))
{
auto const len = distance(first, last);
return aux::equal_range_n(
std::move(first), len, val, std::move(pred), std::move(proj));
}
// Probe exponentially for either end-of-range, an iterator that
// is past the equal range (i.e., denotes an element greater
// than val), or is in the equal range (denotes an element equal
// to val).
auto dist = iter_difference_t<I>{1};
while(true)
{
auto mid = first;
auto d = advance(mid, dist, last);
if(d || mid == last)
{
// at the end of the input range
dist -= d;
return aux::equal_range_n(
std::move(first), dist, val, ranges::ref(pred), ranges::ref(proj));
}
// if val < *mid, mid is after the target range.
auto && v = *mid;
auto && pv = invoke(proj, (decltype(v) &&)v);
if(invoke(pred, val, pv))
{
return aux::equal_range_n(
std::move(first), dist, val, ranges::ref(pred), ranges::ref(proj));
}
else if(!invoke(pred, pv, val))
{
// *mid == val: the lower bound is <= mid, and the upper bound is >
// mid.
return {
aux::lower_bound_n(
std::move(first), dist, val, ranges::ref(pred), ranges::ref(proj)),
upper_bound(std::move(mid),
std::move(last),
val,
ranges::ref(pred),
ranges::ref(proj))};
}
// *mid < val, mid is before the target range.
first = std::move(mid);
++first;
dist *= 2;
}
}
/// \overload
template(typename Rng, typename V, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
constexpr borrowed_subrange_t<Rng> //
RANGES_FUNC(equal_range)(Rng && rng, V const & val, C pred = C{}, P proj = P{}) //
{
if(RANGES_CONSTEXPR_IF(sized_range<Rng>))
{
auto const len = distance(rng);
return aux::equal_range_n(
begin(rng), len, val, std::move(pred), std::move(proj));
}
return (*this)(begin(rng), end(rng), val, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(equal_range)
namespace cpp20
{
using ranges::equal_range;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,62 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FILL_HPP
#define RANGES_V3_ALGORITHM_FILL_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fill)
/// \brief function template \c fill
template(typename O, typename S, typename V)(
requires output_iterator<O, V const &> AND sentinel_for<S, O>)
constexpr O RANGES_FUNC(fill)(O first, S last, V const & val) //
{
for(; first != last; ++first)
*first = val;
return first;
}
/// \overload
template(typename Rng, typename V)(
requires output_range<Rng, V const &>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(fill)(Rng && rng, V const & val)
{
return (*this)(begin(rng), end(rng), val);
}
RANGES_FUNC_END(fill)
namespace cpp20
{
using ranges::fill;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,59 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FILL_N_HPP
#define RANGES_V3_ALGORITHM_FILL_N_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fill_n)
/// \brief function template \c equal
template(typename O, typename V)(
requires output_iterator<O, V const &>)
constexpr O RANGES_FUNC(fill_n)(O first, iter_difference_t<O> n, V const & val)
{
RANGES_EXPECT(n >= 0);
auto norig = n;
auto b = uncounted(first);
for(; n != 0; ++b, --n)
*b = val;
return recounted(first, b, norig);
}
RANGES_FUNC_END(fill_n)
namespace cpp20
{
using ranges::fill_n;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,78 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FIND_HPP
#define RANGES_V3_ALGORITHM_FIND_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(find)
/// \brief template function \c find
///
/// range-based version of the \c find std algorithm
///
/// \pre `Rng` is a model of the `range` concept
/// \pre `I` is a model of the `input_iterator` concept
/// \pre `S` is a model of the `sentinel_for<I>` concept
/// \pre `P` is a model of the `invocable<iter_common_reference_t<I>>` concept
/// \pre The ResultType of `P` is equality_comparable with V
template(typename I, typename S, typename V, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<equal_to, projected<I, P>, V const *>)
constexpr I RANGES_FUNC(find)(I first, S last, V const & val, P proj = P{})
{
for(; first != last; ++first)
if(invoke(proj, *first) == val)
break;
return first;
}
/// \overload
template(typename Rng, typename V, typename P = identity)(
requires input_range<Rng> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(find)(Rng && rng, V const & val, P proj = P{})
{
return (*this)(begin(rng), end(rng), val, std::move(proj));
}
RANGES_FUNC_END(find)
namespace cpp20
{
using ranges::find;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,237 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FIND_END_HPP
#define RANGES_V3_ALGORITHM_FIND_END_HPP
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
template(typename I, typename S)(
requires input_iterator<I> AND sentinel_for<S, I>)
constexpr I next_to_if(I i, S s, std::true_type)
{
return ranges::next(i, s);
}
template(typename I, typename S)(
requires input_iterator<I> AND sentinel_for<S, I>)
constexpr S next_to_if(I, S s, std::false_type)
{
return s;
}
template(bool B, typename I, typename S)(
requires input_iterator<I> AND sentinel_for<S, I>)
constexpr meta::if_c<B, I, S> next_to_if(I i, S s)
{
return detail::next_to_if(std::move(i), std::move(s), meta::bool_<B>{});
}
template<typename I1, typename S1, typename I2, typename S2, typename R,
typename P>
constexpr subrange<I1> find_end_impl(I1 begin1, S1 end1, I2 begin2, S2 end2, R pred, P proj,
std::forward_iterator_tag, std::forward_iterator_tag)
{
bool found = false;
I1 res_begin, res_end;
if(begin2 == end2)
{
auto e1 = ranges::next(begin1, end1);
return {e1, e1};
}
while(true)
{
while(true)
{
if(begin1 == end1)
return {(found ? res_begin : begin1), (found ? res_end : begin1)};
if(invoke(pred, invoke(proj, *begin1), *begin2))
break;
++begin1;
}
auto tmp1 = begin1;
auto tmp2 = begin2;
while(true)
{
if(++tmp2 == end2)
{
res_begin = begin1++;
res_end = ++tmp1;
found = true;
break;
}
if(++tmp1 == end1)
return {(found ? res_begin : tmp1), (found ? res_end : tmp1)};
if(!invoke(pred, invoke(proj, *tmp1), *tmp2))
{
++begin1;
break;
}
}
}
}
template<typename I1, typename I2, typename R, typename P>
constexpr subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj,
std::bidirectional_iterator_tag,
std::bidirectional_iterator_tag)
{
// modeled after search algorithm (in reverse)
if(begin2 == end2)
return {end1, end1}; // Everything matches an empty sequence
I1 l1 = end1;
I2 l2 = end2;
--l2;
while(true)
{
// Find end element in sequence 1 that matches *(end2-1), with a mininum
// of loop checks
do
// return {end1,end1} if no element matches *begin2
if(begin1 == l1)
return {end1, end1};
while(!invoke(pred, invoke(proj, *--l1), *l2));
// *l1 matches *l2, now match elements before here
I1 m1 = l1;
I2 m2 = l2;
do
// If pattern exhausted, {m1,++l1} is the answer
// (works for 1 element pattern)
if(m2 == begin2)
return {m1, ++l1};
// Otherwise if source exhausted, pattern not found
else if(m1 == begin1)
return {end1, end1};
// if there is a mismatch, restart with a new l1
// else there is a match, check next elements
while(invoke(pred, invoke(proj, *--m1), *--m2));
}
}
template<typename I1, typename I2, typename R, typename P>
constexpr subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj,
std::random_access_iterator_tag,
std::random_access_iterator_tag)
{
// Take advantage of knowing source and pattern lengths. Stop short when
// source is smaller than pattern
auto len2 = end2 - begin2;
if(len2 == 0)
return {end1, end1};
auto len1 = end1 - begin1;
if(len1 < len2)
return {end1, end1};
I1 const start =
begin1 + (len2 - 1); // End of pattern match can't go before here
I1 l1 = end1;
I2 l2 = end2;
--l2;
while(true)
{
do
if(start == l1)
return {end1, end1};
while(!invoke(pred, invoke(proj, *--l1), *l2));
I1 m1 = l1;
I2 m2 = l2;
do
if(m2 == begin2)
return {m1, ++l1};
// no need to check range on m1 because s guarantees we have enough source
while(invoke(pred, invoke(proj, *--m1), *--m2));
}
}
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(find_end)
/// \brief function template \c find_end
template(typename I1,
typename S1,
typename I2,
typename S2,
typename R = equal_to,
typename P = identity)(
requires forward_iterator<I1> AND sentinel_for<S1, I1> AND
forward_iterator<I2> AND sentinel_for<S2, I2> AND
indirect_relation<R, projected<I1, P>, I2>)
constexpr subrange<I1> RANGES_FUNC(find_end)(
I1 begin1, S1 end1, I2 begin2, S2 end2, R pred = R{}, P proj = P{}) //
{
constexpr bool Bidi =
bidirectional_iterator<I1> && bidirectional_iterator<I2>;
return detail::find_end_impl(begin1,
detail::next_to_if<Bidi>(begin1, end1),
begin2,
detail::next_to_if<Bidi>(begin2, end2),
std::move(pred),
std::move(proj),
iterator_tag_of<I1>(),
iterator_tag_of<I2>());
}
/// \overload
template(typename Rng1,
typename Rng2,
typename R = equal_to,
typename P = identity)(
requires forward_range<Rng1> AND forward_range<Rng2> AND
indirect_relation<R, projected<iterator_t<Rng1>, P>, iterator_t<Rng2>>)
constexpr borrowed_subrange_t<Rng1> RANGES_FUNC(find_end)(
Rng1 && rng1, Rng2 && rng2, R pred = R{}, P proj = P{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(pred),
std::move(proj));
}
RANGES_FUNC_END(find_end)
namespace cpp20
{
using ranges::find_end;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,103 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FIND_FIRST_OF_HPP
#define RANGES_V3_ALGORITHM_FIND_FIRST_OF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(find_first_of)
// Rationale: return I0 instead of pair<I0,I1> because find_first_of need
// not actually compute the end of [I1,S0); therefore, it is not necessarily
// losing information. E.g., if begin0 == end0, we can return begin0 immediately.
// If we returned pair<I0,I1>, we would need to do an O(N) scan to find the
// end position.
/// \brief function template \c find_first_of
template(typename I0,
typename S0,
typename I1,
typename S1,
typename R = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
forward_iterator<I1> AND sentinel_for<S1, I1> AND
indirect_relation<R, projected<I0, P0>, projected<I1, P1>>)
constexpr I0 RANGES_FUNC(find_first_of)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
R pred = R{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
for(; begin0 != end0; ++begin0)
for(auto tmp = begin1; tmp != end1; ++tmp)
if(invoke(pred, invoke(proj0, *begin0), invoke(proj1, *tmp)))
return begin0;
return begin0;
}
/// \overload
template(typename Rng0,
typename Rng1,
typename R = equal_to,
typename P0 = identity,
typename P1 = identity)(
requires input_range<Rng0> AND forward_range<Rng1> AND
indirect_relation<R,
projected<iterator_t<Rng0>, P0>,
projected<iterator_t<Rng1>, P1>>)
constexpr borrowed_iterator_t<Rng0> RANGES_FUNC(find_first_of)(
Rng0 && rng0, Rng1 && rng1, R pred = R{}, P0 proj0 = P0{}, P1 proj1 = P1{}) //
{
return (*this)(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(find_first_of)
namespace cpp20
{
using ranges::find_first_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,79 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FIND_IF_HPP
#define RANGES_V3_ALGORITHM_FIND_IF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(find_if)
/// \brief template function \c find
///
/// range-based version of the \c find std algorithm
///
/// \pre `Rng` is a model of the `range` concept
/// \pre `I` is a model of the `input_iterator` concept
/// \pre `S` is a model of the `sentinel_for<I>` concept
/// \pre `P` is a model of the `invocable<V>` concept, where `V` is the
/// value type of I.
/// \pre `F` models `predicate<X>`, where `X` is the result type
/// of `invocable<P, V>`
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr I RANGES_FUNC(find_if)(I first, S last, F pred, P proj = P{})
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
break;
return first;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(find_if)(Rng && rng, F pred, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(find_if)
namespace cpp20
{
using ranges::find_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,80 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FIND_IF_NOT_HPP
#define RANGES_V3_ALGORITHM_FIND_IF_NOT_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(find_if_not)
/// \brief template function \c find_if_not
///
/// range-based version of the \c find_if_not std algorithm
///
/// \pre `Rng` is a model of the `range` concept
/// \pre `I` is a model of the `input_iterator` concept
/// \pre `S` is a model of the `sentinel_for<I>` concept
/// \pre `P` is a model of the `invocable<V>` concept, where `V` is the
/// value type of I.
/// \pre `F` models `predicate<X>`, where `X` is the result type
/// of `invocable<P, V>`
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr I RANGES_FUNC(find_if_not)(I first, S last, F pred, P proj = P{})
{
for(; first != last; ++first)
if(!invoke(pred, invoke(proj, *first)))
break;
return first;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(find_if_not)(Rng && rng, F pred, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(find_if_not)
namespace cpp20
{
using ranges::find_if_not;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,19 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2021-present
//
// 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
#ifndef RANGES_V3_ALGORITHM_FOLD_HPP
#define RANGES_V3_ALGORITHM_FOLD_HPP
#include <range/v3/algorithm/fold_left.hpp>
#include <range/v3/algorithm/fold_right.hpp>
#endif

View File

@@ -0,0 +1,125 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2021-present
//
// 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
#ifndef RANGES_V3_ALGORITHM_FOLD_LEFT_HPP
#define RANGES_V3_ALGORITHM_FOLD_LEFT_HPP
#include <meta/meta.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/utility/optional.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
// clang-format off
/// \concept indirectly_binary_left_foldable_impl
/// \brief The \c indirectly_binary_left_foldable_impl concept
template<class F, class T, class I, class U>
CPP_concept indirectly_binary_left_foldable_impl =
movable<T> &&
movable<U> &&
convertible_to<T, U> &&
invocable<F&, U, iter_reference_t<I>> &&
assignable_from<U&, invoke_result_t<F&, U, iter_reference_t<I>>>;
/// \concept indirectly_binary_left_foldable
/// \brief The \c indirectly_binary_left_foldable concept
template<class F, class T, class I>
CPP_concept indirectly_binary_left_foldable =
copy_constructible<F> &&
indirectly_readable<I> &&
invocable<F&, T, iter_reference_t<I>> &&
convertible_to<invoke_result_t<F&, T, iter_reference_t<I>>,
std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>> &&
indirectly_binary_left_foldable_impl<F, T, I, std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>>;
// clang-format on
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fold_left)
template(typename I, typename S, typename T, typename Op)(
requires sentinel_for<S, I> AND input_iterator<I> AND
indirectly_binary_left_foldable<Op, T, I>) //
constexpr auto
RANGES_FUNC(fold_left)(I first, S last, T init, Op op)
{
using U = std::decay_t<invoke_result_t<Op &, T, iter_reference_t<I>>>;
if(first == last)
{
return U(std::move(init));
}
U accum = invoke(op, std::move(init), *first);
for(++first; first != last; ++first)
{
accum = invoke(op, std::move(accum), *first);
}
return accum;
}
template(typename Rng, typename T, typename Op)(
requires input_range<Rng> AND
indirectly_binary_left_foldable<Op, T, iterator_t<Rng>>) //
constexpr auto
RANGES_FUNC(fold_left)(Rng && rng, T init, Op op)
{
return (*this)(begin(rng), end(rng), std::move(init), std::move(op));
}
RANGES_FUNC_END(fold_left)
RANGES_FUNC_BEGIN(fold_left_first)
template(typename I, typename S, typename Op)(
requires sentinel_for<S, I> AND input_iterator<I> AND
indirectly_binary_left_foldable<Op, iter_value_t<I>, I>
AND constructible_from<iter_value_t<I>, iter_reference_t<I>>) //
constexpr auto
RANGES_FUNC(fold_left_first)(I first, S last, Op op)
{
using U = invoke_result_t<fold_left_fn, I, S, iter_value_t<I>, Op>;
if(first == last)
{
return optional<U>();
}
iter_value_t<I> init = *first;
++first;
return optional<U>(
in_place,
fold_left_fn{}(std::move(first), std::move(last), std::move(init), op));
}
template(typename R, typename Op)(
requires input_range<R> AND
indirectly_binary_left_foldable<Op, range_value_t<R>, iterator_t<R>>
AND constructible_from<range_value_t<R>, range_reference_t<R>>) //
constexpr auto
RANGES_FUNC(fold_left_first)(R && rng, Op op)
{
return (*this)(begin(rng), end(rng), std::move(op));
}
RANGES_FUNC_END(fold_left_first)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,126 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2021-present
//
// 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
#ifndef RANGES_V3_ALGORITHM_FOLD_RIGHT_HPP
#define RANGES_V3_ALGORITHM_FOLD_RIGHT_HPP
#include <meta/meta.hpp>
#include <range/v3/algorithm/fold_left.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/utility/optional.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
namespace detail
{
template<typename F>
struct flipped
{
F f;
template(class T, class U)(requires invocable<F &, U, T>) //
invoke_result_t<F &, U, T>
operator()(T &&, U &&);
};
} // namespace detail
// clang-format off
/// \concept indirectly_binary_right_foldable
/// \brief The \c indirectly_binary_right_foldable concept
template<class F, class T, class I>
CPP_concept indirectly_binary_right_foldable =
indirectly_binary_left_foldable<detail::flipped<F>, T, I>;
// clang-format on
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(fold_right)
template(typename I, typename S, typename T, typename Op)(
requires sentinel_for<S, I> AND bidirectional_iterator<I> AND
indirectly_binary_right_foldable<Op, T, I>) //
constexpr auto
RANGES_FUNC(fold_right)(I first, S last, T init, Op op)
{
using U = std::decay_t<invoke_result_t<Op &, iter_reference_t<I>, T>>;
if(first == last)
{
return U(std::move(init));
}
I tail = next(first, last);
U accum = invoke(op, *--tail, std::move(init));
while(first != tail)
{
accum = invoke(op, *--tail, std::move(accum));
}
return accum;
}
template(typename Rng, typename T, typename Op)(
requires bidirectional_range<Rng> AND
indirectly_binary_right_foldable<Op, T, iterator_t<Rng>>) //
constexpr auto
RANGES_FUNC(fold_right)(Rng && rng, T init, Op op)
{
return (*this)(begin(rng), end(rng), std::move(init), std::move(op));
}
RANGES_FUNC_END(fold_right)
RANGES_FUNC_BEGIN(fold_right_last)
template(typename I, typename S, typename Op)(
requires sentinel_for<S, I> AND bidirectional_iterator<I> AND
indirectly_binary_right_foldable<Op, iter_value_t<I>, I>
AND constructible_from<iter_value_t<I>, iter_reference_t<I>>) //
constexpr auto
RANGES_FUNC(fold_right_last)(I first, S last, Op op)
{
using U = invoke_result_t<fold_right_fn, I, S, iter_value_t<I>, Op>;
if(first == last)
{
return optional<U>();
}
I tail = prev(next(first, std::move(last)));
return optional<U>(
in_place,
fold_right_fn{}(
std::move(first), tail, iter_value_t<I>(*tail), std::move(op)));
}
template(typename R, typename Op)(
requires bidirectional_range<R> AND
indirectly_binary_right_foldable<Op, range_value_t<R>, iterator_t<R>>
AND constructible_from<range_value_t<R>, range_reference_t<R>>) //
constexpr auto
RANGES_FUNC(fold_right_last)(R && rng, Op op)
{
return (*this)(begin(rng), end(rng), std::move(op));
}
RANGES_FUNC_END(fold_right_last)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,78 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FOR_EACH_HPP
#define RANGES_V3_ALGORITHM_FOR_EACH_HPP
#include <functional>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/functional/reference_wrapper.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename F>
using for_each_result = detail::in_fun_result<I, F>;
RANGES_FUNC_BEGIN(for_each)
/// \brief function template \c for_each
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirectly_unary_invocable<F, projected<I, P>>)
constexpr for_each_result<I, F> RANGES_FUNC(for_each)(I first, S last, F fun, P proj = P{})
{
for(; first != last; ++first)
{
invoke(fun, invoke(proj, *first));
}
return {detail::move(first), detail::move(fun)};
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>)
constexpr for_each_result<borrowed_iterator_t<Rng>, F> //
RANGES_FUNC(for_each)(Rng && rng, F fun, P proj = P{})
{
return {(*this)(begin(rng), end(rng), ref(fun), detail::move(proj)).in,
detail::move(fun)};
}
RANGES_FUNC_END(for_each)
namespace cpp20
{
using ranges::for_each;
using ranges::for_each_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,77 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Rostislav Khlebnikov 2017
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_FOR_EACH_N_HPP
#define RANGES_V3_ALGORITHM_FOR_EACH_N_HPP
#include <functional>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(for_each_n)
/// \brief function template \c for_each_n
template(typename I, typename F, typename P = identity)(
requires input_iterator<I> AND
indirectly_unary_invocable<F, projected<I, P>>)
constexpr I RANGES_FUNC(for_each_n)(I first, iter_difference_t<I> n, F fun, P proj = P{})
{
RANGES_EXPECT(0 <= n);
auto norig = n;
auto b = uncounted(first);
for(; 0 < n; ++b, --n)
invoke(fun, invoke(proj, *b));
return recounted(first, b, norig);
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(for_each_n)(
Rng && rng, range_difference_t<Rng> n, F fun, P proj = P{})
{
if(sized_range<Rng>)
RANGES_EXPECT(n <= distance(rng));
return (*this)(begin(rng), n, detail::move(fun), detail::move(proj));
}
RANGES_FUNC_END(for_each_n)
namespace cpp20
{
using ranges::for_each_n;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,73 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_GENERATE_HPP
#define RANGES_V3_ALGORITHM_GENERATE_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/functional/reference_wrapper.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename O, typename F>
using generate_result = detail::out_fun_result<O, F>;
RANGES_FUNC_BEGIN(generate)
/// \brief function template \c generate_n
template(typename O, typename S, typename F)(
requires invocable<F &> AND output_iterator<O, invoke_result_t<F &>> AND
sentinel_for<S, O>)
constexpr generate_result<O, F> RANGES_FUNC(generate)(O first, S last, F fun) //
{
for(; first != last; ++first)
*first = invoke(fun);
return {detail::move(first), detail::move(fun)};
}
/// \overload
template(typename Rng, typename F)(
requires invocable<F &> AND output_range<Rng, invoke_result_t<F &>>)
constexpr generate_result<borrowed_iterator_t<Rng>, F> //
RANGES_FUNC(generate)(Rng && rng, F fun)
{
return {(*this)(begin(rng), end(rng), ref(fun)).out, detail::move(fun)};
}
RANGES_FUNC_END(generate)
namespace cpp20
{
using ranges::generate;
using ranges::generate_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,67 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_GENERATE_N_HPP
#define RANGES_V3_ALGORITHM_GENERATE_N_HPP
#include <tuple>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename O, typename F>
using generate_n_result = detail::out_fun_result<O, F>;
RANGES_FUNC_BEGIN(generate_n)
/// \brief function template \c generate_n
template(typename O, typename F)(
requires invocable<F &> AND output_iterator<O, invoke_result_t<F &>>)
constexpr generate_n_result<O, F> //
RANGES_FUNC(generate_n)(O first, iter_difference_t<O> n, F fun)
{
RANGES_EXPECT(n >= 0);
auto norig = n;
auto b = uncounted(first);
for(; 0 != n; ++b, --n)
*b = invoke(fun);
return {recounted(first, b, norig), detail::move(fun)};
}
RANGES_FUNC_END(generate_n)
namespace cpp20
{
using ranges::generate_n;
using ranges::generate_n_result;
} // namespace cpp20
// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,436 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_HEAP_ALGORITHM_HPP
#define RANGES_V3_ALGORITHM_HEAP_ALGORITHM_HPP
#include <functional>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
struct is_heap_until_n_fn
{
template(typename I, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I operator()(I const begin_,
iter_difference_t<I> const n_,
C pred = C{},
P proj = P{}) const
{
RANGES_EXPECT(0 <= n_);
iter_difference_t<I> p = 0, c = 1;
I pp = begin_;
while(c < n_)
{
I cp = begin_ + c;
if(invoke(pred, invoke(proj, *pp), invoke(proj, *cp)))
return cp;
++c;
++cp;
if(c == n_ || invoke(pred, invoke(proj, *pp), invoke(proj, *cp)))
return cp;
++p;
++pp;
c = 2 * p + 1;
}
return begin_ + n_;
}
};
RANGES_INLINE_VARIABLE(is_heap_until_n_fn, is_heap_until_n)
struct is_heap_n_fn
{
template(typename I, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr bool operator()(I first,
iter_difference_t<I> n,
C pred = C{},
P proj = P{}) const
{
return is_heap_until_n(first, n, std::move(pred), std::move(proj)) ==
first + n;
}
};
RANGES_INLINE_VARIABLE(is_heap_n_fn, is_heap_n)
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(is_heap_until)
/// \brief function template \c is_heap_until
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I RANGES_FUNC(is_heap_until)(I first, S last, C pred = C{}, P proj = P{})
{
return detail::is_heap_until_n(std::move(first),
distance(first, last),
std::move(pred),
std::move(proj));
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(is_heap_until)(Rng && rng, C pred = C{}, P proj = P{})
{
return detail::is_heap_until_n(
begin(rng), distance(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(is_heap_until)
namespace cpp20
{
using ranges::is_heap_until;
}
RANGES_FUNC_BEGIN(is_heap)
/// \brief function template \c is_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr bool RANGES_FUNC(is_heap)(I first, S last, C pred = C{}, P proj = P{}) //
{
return detail::is_heap_n(std::move(first),
distance(first, last),
std::move(pred),
std::move(proj));
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(is_heap)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return detail::is_heap_n(
begin(rng), distance(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(is_heap)
namespace cpp20
{
using ranges::is_heap;
}
/// @}
/// \cond
namespace detail
{
struct sift_up_n_fn
{
template<typename I, typename C = less, typename P = identity>
constexpr void operator()(I first,
iter_difference_t<I> len,
C pred = C{},
P proj = P{}) const
{
if(len > 1)
{
I last = first + len;
len = (len - 2) / 2;
I i = first + len;
if(invoke(pred, invoke(proj, *i), invoke(proj, *--last)))
{
iter_value_t<I> v = iter_move(last);
do
{
*last = iter_move(i);
last = i;
if(len == 0)
break;
len = (len - 1) / 2;
i = first + len;
} while(invoke(pred, invoke(proj, *i), invoke(proj, v)));
*last = std::move(v);
}
}
}
};
RANGES_INLINE_VARIABLE(sift_up_n_fn, sift_up_n)
struct sift_down_n_fn
{
template<typename I, typename C = less, typename P = identity>
constexpr void operator()(I first,
iter_difference_t<I> len,
I start,
C pred = C{},
P proj = P{}) const
{
// left-child of start is at 2 * start + 1
// right-child of start is at 2 * start + 2
auto child = start - first;
if(len < 2 || (len - 2) / 2 < child)
return;
child = 2 * child + 1;
I child_i = first + child;
if((child + 1) < len &&
invoke(pred, invoke(proj, *child_i), invoke(proj, *(child_i + 1))))
{
// right-child exists and is greater than left-child
++child_i;
++child;
}
// check if we are in heap-order
if(invoke(pred, invoke(proj, *child_i), invoke(proj, *start)))
// we are, start is larger than it's largest child
return;
iter_value_t<I> top = iter_move(start);
do
{
// we are not in heap-order, swap the parent with it's largest child
*start = iter_move(child_i);
start = child_i;
if((len - 2) / 2 < child)
break;
// recompute the child based off of the updated parent
child = 2 * child + 1;
child_i = first + child;
if((child + 1) < len &&
invoke(pred, invoke(proj, *child_i), invoke(proj, *(child_i + 1))))
{
// right-child exists and is greater than left-child
++child_i;
++child;
}
// check if we are in heap-order
} while(!invoke(pred, invoke(proj, *child_i), invoke(proj, top)));
*start = std::move(top);
}
};
RANGES_INLINE_VARIABLE(sift_down_n_fn, sift_down_n)
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(push_heap)
/// \brief function template \c push_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(push_heap)(I first, S last, C pred = C{}, P proj = P{})
{
auto n = distance(first, last);
detail::sift_up_n(first, n, std::move(pred), std::move(proj));
return first + n;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(push_heap)(Rng && rng, C pred = C{}, P proj = P{}) //
{
iterator_t<Rng> first = ranges::begin(rng);
auto n = distance(rng);
detail::sift_up_n(first, n, std::move(pred), std::move(proj));
return first + n;
}
RANGES_FUNC_END(push_heap)
namespace cpp20
{
using ranges::push_heap;
}
/// @}
/// \cond
namespace detail
{
struct pop_heap_n_fn
{
template(typename I, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sortable<I, C, P>)
constexpr void operator()(I first,
iter_difference_t<I> len,
C pred = C{},
P proj = P{}) const
{
if(len > 1)
{
ranges::iter_swap(first, first + (len - 1));
detail::sift_down_n(
first, len - 1, first, std::move(pred), std::move(proj));
}
}
};
RANGES_INLINE_VARIABLE(pop_heap_n_fn, pop_heap_n)
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(pop_heap)
/// \brief function template \c pop_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(pop_heap)(I first, S last, C pred = C{}, P proj = P{})
{
auto n = distance(first, last);
detail::pop_heap_n(first, n, std::move(pred), std::move(proj));
return first + n;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(pop_heap)(Rng && rng, C pred = C{}, P proj = P{})
{
iterator_t<Rng> first = ranges::begin(rng);
auto n = distance(rng);
detail::pop_heap_n(first, n, std::move(pred), std::move(proj));
return first + n;
}
RANGES_FUNC_END(pop_heap)
namespace cpp20
{
using ranges::pop_heap;
}
RANGES_FUNC_BEGIN(make_heap)
/// \brief function template \c make_heap
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(make_heap)(I first, S last, C pred = C{}, P proj = P{})
{
iter_difference_t<I> const n = distance(first, last);
if(n > 1)
// start from the first parent, there is no need to consider children
for(auto start = (n - 2) / 2; start >= 0; --start)
detail::sift_down_n(
first, n, first + start, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(make_heap)(Rng && rng, C pred = C{}, P proj = P{})
{
iterator_t<Rng> first = ranges::begin(rng);
auto const n = distance(rng);
if(n > 1)
// start from the first parent, there is no need to consider children
for(auto start = (n - 2) / 2; start >= 0; --start)
detail::sift_down_n(
first, n, first + start, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
RANGES_FUNC_END(make_heap)
namespace cpp20
{
using ranges::make_heap;
}
RANGES_FUNC_BEGIN(sort_heap)
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr I RANGES_FUNC(sort_heap)(I first, S last, C pred = C{}, P proj = P{})
{
iter_difference_t<I> const n = distance(first, last);
for(auto i = n; i > 1; --i)
detail::pop_heap_n(first, i, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng &> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(sort_heap)(Rng && rng, C pred = C{}, P proj = P{})
{
iterator_t<Rng> first = ranges::begin(rng);
auto const n = distance(rng);
for(auto i = n; i > 1; --i)
detail::pop_heap_n(first, i, ranges::ref(pred), ranges::ref(proj));
return first + n;
}
RANGES_FUNC_END(sort_heap)
namespace cpp20
{
using ranges::sort_heap;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,303 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_INPLACE_MERGE_HPP
#define RANGES_V3_ALGORITHM_INPLACE_MERGE_HPP
#include <functional>
#include <memory>
#include <new>
#include <type_traits>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/lower_bound.hpp>
#include <range/v3/algorithm/merge.hpp>
#include <range/v3/algorithm/min.hpp>
#include <range/v3/algorithm/move.hpp>
#include <range/v3/algorithm/rotate.hpp>
#include <range/v3/algorithm/upper_bound.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/functional/not_fn.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/move_iterators.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/reverse_iterator.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/memory.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
struct merge_adaptive_fn
{
private:
template<typename I, typename C, typename P>
static void impl(I first, I middle, I last, iter_difference_t<I> len1,
iter_difference_t<I> len2, iter_value_t<I> * const buf,
C & pred, P & proj)
{
auto tmpbuf = make_raw_buffer(buf);
if(len1 <= len2)
{
auto p = ranges::move(first, middle, tmpbuf.begin()).out;
merge(make_move_iterator(buf),
make_move_iterator(p.base().base()),
make_move_iterator(std::move(middle)),
make_move_iterator(std::move(last)),
std::move(first),
std::ref(pred),
std::ref(proj),
std::ref(proj));
}
else
{
auto p = ranges::move(middle, last, tmpbuf.begin()).out;
using RBi = ranges::reverse_iterator<I>;
using Rv = ranges::reverse_iterator<iter_value_t<I> *>;
merge(make_move_iterator(RBi{std::move(middle)}),
make_move_iterator(RBi{std::move(first)}),
make_move_iterator(Rv{p.base().base()}),
make_move_iterator(Rv{buf}),
RBi{std::move(last)},
not_fn(std::ref(pred)),
std::ref(proj),
std::ref(proj));
}
}
public:
template(typename I, typename C = less, typename P = identity)(
requires bidirectional_iterator<I> AND sortable<I, C, P>)
void operator()(I first, I middle, I last, iter_difference_t<I> len1,
iter_difference_t<I> len2, iter_value_t<I> * buf,
std::ptrdiff_t buf_size, C pred = C{}, P proj = P{}) const
{
using D = iter_difference_t<I>;
while(true)
{
// if middle == last, we're done
if(len2 == 0)
return;
// shrink [first, middle) as much as possible (with no moves),
// returning if it shrinks to 0
for(; true; ++first, --len1)
{
if(len1 == 0)
return;
if(invoke(pred, invoke(proj, *middle), invoke(proj, *first)))
break;
}
if(len1 <= buf_size || len2 <= buf_size)
{
merge_adaptive_fn::impl(std::move(first),
std::move(middle),
std::move(last),
len1,
len2,
buf,
pred,
proj);
return;
}
// first < middle < end
// *first > *middle
// partition [first, m1) [m1, middle) [middle, m2) [m2, last) such
// that
// all elements in:
// [first, m1) <= [middle, m2)
// [middle, m2) < [m1, middle)
// [m1, middle) <= [m2, last)
// and m1 or m2 is in the middle of its range
I m1; // "median" of [first, middle)
I m2; // "median" of [middle, last)
D len11; // distance(first, m1)
D len21; // distance(middle, m2)
// binary search smaller range
if(len1 < len2)
{ // len >= 1, len2 >= 2
len21 = len2 / 2;
m2 = next(middle, len21);
m1 = upper_bound(first,
middle,
invoke(proj, *m2),
std::ref(pred),
std::ref(proj));
len11 = distance(first, m1);
}
else
{
if(len1 == 1)
{ // len1 >= len2 && len2 > 0, therefore len2 == 1
// It is known *first > *middle
ranges::iter_swap(first, middle);
return;
}
// len1 >= 2, len2 >= 1
len11 = len1 / 2;
m1 = next(first, len11);
m2 = lower_bound(middle,
last,
invoke(proj, *m1),
std::ref(pred),
std::ref(proj));
len21 = distance(middle, m2);
}
D len12 = len1 - len11; // distance(m1, middle)
D len22 = len2 - len21; // distance(m2, last)
// [first, m1) [m1, middle) [middle, m2) [m2, last)
// swap middle two partitions
middle = rotate(m1, std::move(middle), m2).begin();
// len12 and len21 now have swapped meanings
// merge smaller range with recursive call and larger with tail
// recursion elimination
if(len11 + len21 < len12 + len22)
{
(*this)(std::move(first),
std::move(m1),
middle,
len11,
len21,
buf,
buf_size,
std::ref(pred),
std::ref(proj));
first = std::move(middle);
middle = std::move(m2);
len1 = len12;
len2 = len22;
}
else
{
(*this)(middle,
std::move(m2),
std::move(last),
len12,
len22,
buf,
buf_size,
std::ref(pred),
std::ref(proj));
last = std::move(middle);
middle = std::move(m1);
len1 = len11;
len2 = len21;
}
}
}
};
RANGES_INLINE_VARIABLE(merge_adaptive_fn, merge_adaptive)
struct inplace_merge_no_buffer_fn
{
template(typename I, typename C = less, typename P = identity)(
requires bidirectional_iterator<I> AND sortable<I, C, P>)
void operator()(I first, I middle, I last, iter_difference_t<I> len1,
iter_difference_t<I> len2, C pred = C{}, P proj = P{}) const
{
merge_adaptive(std::move(first),
std::move(middle),
std::move(last),
len1,
len2,
static_cast<iter_value_t<I> *>(nullptr),
0,
std::move(pred),
std::move(proj));
}
};
RANGES_INLINE_VARIABLE(inplace_merge_no_buffer_fn, inplace_merge_no_buffer)
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(inplace_merge)
// TODO reimplement to only need forward iterators
/// \brief function template \c inplace_merge
template(typename I, typename S, typename C = less, typename P = identity)(
requires bidirectional_iterator<I> AND sortable<I, C, P>)
I RANGES_FUNC(inplace_merge)(
I first, I middle, S last, C pred = C{}, P proj = P{})
{
using value_type = iter_value_t<I>;
auto len1 = distance(first, middle);
auto len2_and_end = enumerate(middle, last);
auto buf_size = ranges::min(len1, len2_and_end.first);
std::pair<value_type *, std::ptrdiff_t> buf{nullptr, 0};
std::unique_ptr<value_type, detail::return_temporary_buffer> h;
if(detail::is_trivially_copy_assignable_v<value_type> && 8 < buf_size)
{
buf = detail::get_temporary_buffer<value_type>(buf_size);
h.reset(buf.first);
}
detail::merge_adaptive(std::move(first),
std::move(middle),
len2_and_end.second,
len1,
len2_and_end.first,
buf.first,
buf.second,
std::move(pred),
std::move(proj));
return len2_and_end.second;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires bidirectional_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
borrowed_iterator_t<Rng> RANGES_FUNC(inplace_merge)(
Rng && rng, iterator_t<Rng> middle, C pred = C{}, P proj = P{})
{
return (*this)(begin(rng),
std::move(middle),
end(rng),
std::move(pred),
std::move(proj));
}
RANGES_FUNC_END(inplace_merge)
namespace cpp20
{
using ranges::inplace_merge;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,80 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===-------------------------- algorithm ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_IS_PARTITIONED_HPP
#define RANGES_V3_ALGORITHM_IS_PARTITIONED_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(is_partitioned)
/// \brief function template \c is_partitioned
template(typename I, typename S, typename C, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr bool RANGES_FUNC(is_partitioned)(I first, S last, C pred, P proj = P{}) //
{
for(; first != last; ++first)
if(!invoke(pred, invoke(proj, *first)))
break;
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
return false;
return true;
}
/// \overload
template(typename Rng, typename C, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(is_partitioned)(Rng && rng, C pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(is_partitioned)
namespace cpp20
{
using ranges::is_partitioned;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,77 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
// 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_ALGORITHM_IS_SORTED_HPP
#define RANGES_V3_ALGORITHM_IS_SORTED_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/is_sorted_until.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(is_sorted)
/// \brief template function \c is_sorted
///
/// range-based version of the \c is_sorted std algorithm
///
/// Works on forward_ranges
///
/// \pre `Rng` is a model of the `forward_range` concept
/// \pre `I` is a model of the `forward_iterator` concept
/// \pre `S` and `I` model the `sentinel_for<S, I>` concept
/// \pre `R` and `projected<I, P>` model the `indirect_strict_weak_order<R,
/// projected<I, P>>` concept
///
template(typename I, typename S, typename R = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<R, projected<I, P>>)
constexpr bool RANGES_FUNC(is_sorted)(I first, S last, R rel = R{}, P proj = P{})
{
return is_sorted_until(
std::move(first), last, std::move(rel), std::move(proj)) == last;
}
/// \overload
template(typename Rng, typename R = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<R, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(is_sorted)(Rng && rng, R rel = R{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(rel), std::move(proj));
}
RANGES_FUNC_END(is_sorted)
namespace cpp20
{
using ranges::is_sorted;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,89 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
// 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_ALGORITHM_IS_SORTED_UNTIL_HPP
#define RANGES_V3_ALGORITHM_IS_SORTED_UNTIL_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(is_sorted_until)
/// \brief template function \c is_sorted_until
///
/// range-based version of the \c is_sorted_until std algorithm
///
/// Works on forward_ranges
///
/// \pre `Rng` is a model of the `forward_range` concept
/// \pre `I` is a model of the `forward_iterator` concept
/// \pre `S` and `I` model the `sentinel_for<S, I>` concept
/// \pre `R` and `projected<I, P>` model the `indirect_strict_weak_order<R,
/// projected<I, P>>` concept
///
template(typename I, typename S, typename R = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<R, projected<I, P>>)
constexpr I RANGES_FUNC(is_sorted_until)(I first, S last, R pred = R{}, P proj = P{})
{
auto i = first;
if(first != last)
{
while(++i != last)
{
if(invoke(pred, invoke(proj, *i), invoke(proj, *first)))
return i;
first = i;
}
}
return i;
}
/// \overload
template(typename Rng, typename R = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<R, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(is_sorted_until)(Rng && rng, R pred = R{}, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(is_sorted_until)
namespace cpp20
{
using ranges::is_sorted_until;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,102 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP
#define RANGES_V3_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(lexicographical_compare)
/// \brief function template \c lexicographical_compare
template(typename I0,
typename S0,
typename I1,
typename S1,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND sentinel_for<S1, I1> AND
indirect_strict_weak_order<C, projected<I0, P0>, projected<I1, P1>>)
constexpr bool RANGES_FUNC(lexicographical_compare)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{})
{
for(; begin1 != end1; ++begin0, ++begin1)
{
if(begin0 == end0 ||
invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1)))
return true;
if(invoke(pred, invoke(proj1, *begin1), invoke(proj0, *begin0)))
return false;
}
return false;
}
/// \overload
template(typename Rng0,
typename Rng1,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires input_range<Rng0> AND input_range<Rng1> AND
indirect_strict_weak_order<C,
projected<iterator_t<Rng0>, P0>,
projected<iterator_t<Rng1>, P1>>)
constexpr bool RANGES_FUNC(lexicographical_compare)(Rng0 && rng0,
Rng1 && rng1,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
return (*this)(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(lexicographical_compare)
namespace cpp20
{
using ranges::lexicographical_compare;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,81 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_LOWER_BOUND_HPP
#define RANGES_V3_ALGORITHM_LOWER_BOUND_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/lower_bound_n.hpp>
#include <range/v3/algorithm/partition_point.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(lower_bound)
/// \brief function template \c lower_bound
template(typename I,
typename S,
typename V,
typename C = less,
typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr I RANGES_FUNC(lower_bound)(I first,
S last,
V const & val,
C pred = C{},
P proj = P{})
{
return partition_point(std::move(first),
std::move(last),
detail::make_lower_bound_predicate(pred, val),
std::move(proj));
}
/// \overload
template(typename Rng, typename V, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(lower_bound)(Rng && rng, V const & val, C pred = C{}, P proj = P{})
{
return partition_point(
rng, detail::make_lower_bound_predicate(pred, val), std::move(proj));
}
RANGES_FUNC_END(lower_bound)
namespace cpp20
{
using ranges::lower_bound;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,90 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2015
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MAX_HPP
#define RANGES_V3_ALGORITHM_MAX_HPP
#include <initializer_list>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(max)
/// \brief function template \c max
template(typename T, typename C = less, typename P = identity)(
requires indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T const & RANGES_FUNC(max)(
T const & a, T const & b, C pred = C{}, P proj = P{}) //
{
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? a : b;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires input_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>)
constexpr range_value_t<Rng> //
RANGES_FUNC(max)(Rng && rng, C pred = C{}, P proj = P{}) //
{
auto first = ranges::begin(rng);
auto last = ranges::end(rng);
RANGES_EXPECT(first != last);
range_value_t<Rng> result = *first;
while(++first != last)
{
auto && tmp = *first;
if(invoke(pred, invoke(proj, result), invoke(proj, tmp)))
result = (decltype(tmp) &&)tmp;
}
return result;
}
/// \overload
template(typename T, typename C = less, typename P = identity)(
requires copyable<T> AND
indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T RANGES_FUNC(max)(
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(rng, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(max)
namespace cpp20
{
using ranges::max;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,72 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MAX_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_MAX_ELEMENT_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(max_element)
/// \brief function template \c max_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I RANGES_FUNC(max_element)(I first, S last, C pred = C{}, P proj = P{})
{
if(first != last)
for(auto tmp = next(first); tmp != last; ++tmp)
if(invoke(pred, invoke(proj, *first), invoke(proj, *tmp)))
first = tmp;
return first;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(max_element)(Rng && rng, C pred = C{}, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(max_element)
namespace cpp20
{
using ranges::max_element;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,136 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
// Copyright (c) 2009 Alexander Stepanov and Paul McJones
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without
// fee, provided that the above copyright notice appear in all copies
// and that both that copyright notice and this permission notice
// appear in supporting documentation. The authors make no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.
//
// Algorithms from
// Elements of Programming
// by Alexander Stepanov and Paul McJones
// Addison-Wesley Professional, 2009
#ifndef RANGES_V3_ALGORITHM_MERGE_HPP
#define RANGES_V3_ALGORITHM_MERGE_HPP
#include <tuple>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/copy.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I0, typename I1, typename O>
using merge_result = detail::in1_in2_out_result<I0, I1, O>;
RANGES_FUNC_BEGIN(merge)
/// \brief function template \c merge
template(typename I0,
typename S0,
typename I1,
typename S1,
typename O,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires sentinel_for<S0, I0> AND sentinel_for<S1, I1> AND
mergeable<I0, I1, O, C, P0, P1>)
constexpr merge_result<I0, I1, O> RANGES_FUNC(merge)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
O out,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
for(; begin0 != end0 && begin1 != end1; ++out)
{
if(invoke(pred, invoke(proj1, *begin1), invoke(proj0, *begin0)))
{
*out = *begin1;
++begin1;
}
else
{
*out = *begin0;
++begin0;
}
}
auto t0 = ranges::copy(begin0, end0, out);
auto t1 = ranges::copy(begin1, end1, t0.out);
return {t0.in, t1.in, t1.out};
}
/// \overload
template(typename Rng0,
typename Rng1,
typename O,
typename C = less,
typename P0 = identity,
typename P1 = identity)(
requires range<Rng0> AND range<Rng1> AND
mergeable<iterator_t<Rng0>, iterator_t<Rng1>, O, C, P0, P1>)
constexpr merge_result<borrowed_iterator_t<Rng0>, borrowed_iterator_t<Rng1>, O>
RANGES_FUNC(merge)(Rng0 && rng0,
Rng1 && rng1,
O out,
C pred = C{},
P0 proj0 = P0{},
P1 proj1 = P1{})
{
return (*this)(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(out),
std::move(pred),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(merge)
namespace cpp20
{
using ranges::merge;
using ranges::merge_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,90 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2015
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MIN_HPP
#define RANGES_V3_ALGORITHM_MIN_HPP
#include <initializer_list>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(min)
/// \brief function template \c min
template(typename T, typename C = less, typename P = identity)(
requires indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T const & RANGES_FUNC(min)(
T const & a, T const & b, C pred = C{}, P proj = P{}) //
{
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? b : a;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires input_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>)
constexpr range_value_t<Rng> //
RANGES_FUNC(min)(Rng && rng, C pred = C{}, P proj = P{}) //
{
auto first = ranges::begin(rng);
auto last = ranges::end(rng);
RANGES_EXPECT(first != last);
range_value_t<Rng> result = *first;
while(++first != last)
{
auto && tmp = *first;
if(invoke(pred, invoke(proj, tmp), invoke(proj, result)))
result = (decltype(tmp) &&)tmp;
}
return result;
}
/// \overload
template(typename T, typename C = less, typename P = identity)(
requires copyable<T> AND
indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr T RANGES_FUNC(min)(
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(rng, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(min)
namespace cpp20
{
using ranges::min;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,72 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MIN_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_MIN_ELEMENT_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(min_element)
/// \brief function template \c min_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr I RANGES_FUNC(min_element)(I first, S last, C pred = C{}, P proj = P{})
{
if(first != last)
for(auto tmp = next(first); tmp != last; ++tmp)
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *first)))
first = tmp;
return first;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(min_element)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(min_element)
namespace cpp20
{
using ranges::min_element;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,130 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2015
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MINMAX_HPP
#define RANGES_V3_ALGORITHM_MINMAX_HPP
#include <initializer_list>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename T>
using minmax_result = detail::min_max_result<T, T>;
RANGES_FUNC_BEGIN(minmax)
/// \brief function template \c minmax
template(typename T, typename C = less, typename P = identity)(
requires indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr minmax_result<T const &> RANGES_FUNC(minmax)(
T const & a, T const & b, C pred = C{}, P proj = P{}) //
{
using R = minmax_result<T const &>;
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? R{b, a} : R{a, b};
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires input_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>)
constexpr minmax_result<range_value_t<Rng>> //
RANGES_FUNC(minmax)(Rng && rng, C pred = C{}, P proj = P{}) //
{
using R = minmax_result<range_value_t<Rng>>;
auto first = ranges::begin(rng);
auto last = ranges::end(rng);
RANGES_EXPECT(first != last);
auto result = R{*first, *first};
if(++first != last)
{
{
auto && tmp = *first;
if(invoke(pred, invoke(proj, tmp), invoke(proj, result.min)))
result.min = (decltype(tmp) &&)tmp;
else
result.max = (decltype(tmp) &&)tmp;
}
while(++first != last)
{
range_value_t<Rng> tmp1 = *first;
if(++first == last)
{
if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min)))
result.min = std::move(tmp1);
else if(!invoke(
pred, invoke(proj, tmp1), invoke(proj, result.max)))
result.max = std::move(tmp1);
break;
}
auto && tmp2 = *first;
if(invoke(pred, invoke(proj, tmp2), invoke(proj, tmp1)))
{
if(invoke(pred, invoke(proj, tmp2), invoke(proj, result.min)))
result.min = (decltype(tmp2) &&)tmp2;
if(!invoke(pred, invoke(proj, tmp1), invoke(proj, result.max)))
result.max = std::move(tmp1);
}
else
{
if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min)))
result.min = std::move(tmp1);
if(!invoke(pred, invoke(proj, tmp2), invoke(proj, result.max)))
result.max = (decltype(tmp2) &&)tmp2;
}
}
}
return result;
}
/// \overload
template(typename T, typename C = less, typename P = identity)(
requires copyable<T> AND
indirect_strict_weak_order<C, projected<T const *, P>>)
constexpr minmax_result<T> RANGES_FUNC(minmax)(
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(rng, std::move(pred), std::move(proj));
}
RANGES_FUNC_END(minmax)
namespace cpp20
{
using ranges::minmax;
using ranges::minmax_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,112 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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_ALGORITHM_MINMAX_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_MINMAX_ELEMENT_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I>
using minmax_element_result = detail::min_max_result<I, I>;
RANGES_FUNC_BEGIN(minmax_element)
/// \brief function template \c minmax_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, projected<I, P>>)
constexpr minmax_element_result<I> //
RANGES_FUNC(minmax_element)(I first, S last, C pred = C{}, P proj = P{}) //
{
minmax_element_result<I> result{first, first};
if(first == last || ++first == last)
return result;
if(invoke(pred, invoke(proj, *first), invoke(proj, *result.min)))
result.min = first;
else
result.max = first;
while(++first != last)
{
I tmp = first;
if(++first == last)
{
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *result.min)))
result.min = tmp;
else if(!invoke(pred, invoke(proj, *tmp), invoke(proj, *result.max)))
result.max = tmp;
break;
}
else
{
if(invoke(pred, invoke(proj, *first), invoke(proj, *tmp)))
{
if(invoke(pred, invoke(proj, *first), invoke(proj, *result.min)))
result.min = first;
if(!invoke(pred, invoke(proj, *tmp), invoke(proj, *result.max)))
result.max = tmp;
}
else
{
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *result.min)))
result.min = tmp;
if(!invoke(pred, invoke(proj, *first), invoke(proj, *result.max)))
result.max = first;
}
}
}
return result;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>)
constexpr minmax_element_result<borrowed_iterator_t<Rng>> //
RANGES_FUNC(minmax_element)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(minmax_element)
namespace cpp20
{
using ranges::minmax_element;
using ranges::minmax_element_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,175 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MISMATCH_HPP
#define RANGES_V3_ALGORITHM_MISMATCH_HPP
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I1, typename I2>
using mismatch_result = detail::in1_in2_result<I1, I2>;
RANGES_FUNC_BEGIN(mismatch)
/// \brief function template \c mismatch
template(typename I1,
typename S1,
typename I2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND
indirect_relation<C, projected<I1, P1>, projected<I2, P2>>)
RANGES_DEPRECATED(
"Use the variant of ranges::mismatch that takes an upper bound for "
"both sequences")
mismatch_result<I1, I2> RANGES_FUNC(mismatch)(I1 begin1,
S1 end1,
I2 begin2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
for(; begin1 != end1; ++begin1, ++begin2)
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
break;
return {begin1, begin2};
}
/// \overload
template(typename I1,
typename S1,
typename I2,
typename S2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND sentinel_for<S2, I2> AND
indirect_relation<C, projected<I1, P1>, projected<I2, P2>>)
constexpr mismatch_result<I1, I2> RANGES_FUNC(mismatch)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
for(; begin1 != end1 && begin2 != end2; ++begin1, ++begin2)
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
break;
return {begin1, begin2};
}
/// \overload
template(typename Rng1,
typename I2Ref,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)( //s
requires input_range<Rng1> AND input_iterator<uncvref_t<I2Ref>> AND
indirect_relation<C,
projected<iterator_t<Rng1>, P1>,
projected<uncvref_t<I2Ref>, P2>>)
RANGES_DEPRECATED(
"Use the variant of ranges::mismatch that takes an upper bound for "
"both sequences")
mismatch_result<borrowed_iterator_t<Rng1>, uncvref_t<I2Ref>>
RANGES_FUNC(mismatch)(Rng1 && rng1,
I2Ref && begin2,
C pred = C{}, // see below [*]
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
return (*this)(begin(rng1),
end(rng1),
static_cast<uncvref_t<I2Ref> &&>(begin2),
std::move(pred),
std::move(proj1),
std::move(proj2));
RANGES_DIAGNOSTIC_POP
}
/// \overload
template(typename Rng1,
typename Rng2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires input_range<Rng1> AND input_range<Rng2> AND
indirect_relation<C,
projected<iterator_t<Rng1>, P1>,
projected<iterator_t<Rng2>, P2>>)
constexpr mismatch_result<borrowed_iterator_t<Rng1>, borrowed_iterator_t<Rng2>> //
RANGES_FUNC(mismatch)(Rng1 && rng1,
Rng2 && rng2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(mismatch)
namespace cpp20
{
using ranges::mismatch;
using ranges::mismatch_result;
} // namespace cpp20
// [*] In this case, the 'begin2' iterator is taken by universal reference. Why? So
// that we can properly distinguish this case:
// int x[] = {1,2,3,4};
// int y[] = {1,2,3,4};
// mismatch(x, y);
// Had 'begin2' been taken by value as is customary, this call could match as either
// two ranges, or a range and an iterator, where the iterator is the array, decayed
// to a pointer. Yuk!
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,88 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MOVE_HPP
#define RANGES_V3_ALGORITHM_MOVE_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/move.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using move_result = detail::in_out_result<I, O>;
RANGES_HIDDEN_DETAIL(namespace _move CPP_PP_LBRACE())
RANGES_FUNC_BEGIN(move)
/// \brief function template \c move
template(typename I, typename S, typename O)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirectly_movable<I, O>)
constexpr move_result<I, O> RANGES_FUNC(move)(I first, S last, O out) //
{
for(; first != last; ++first, ++out)
*out = iter_move(first);
return {first, out};
}
/// \overload
template(typename Rng, typename O)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirectly_movable<iterator_t<Rng>, O>)
constexpr move_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(move)(Rng && rng, O out) //
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(move)
RANGES_HIDDEN_DETAIL(CPP_PP_RBRACE())
#ifndef RANGES_DOXYGEN_INVOKED
struct RANGES_EMPTY_BASES move_fn
: aux::move_fn
, _move::move_fn
{
using aux::move_fn::operator();
using _move::move_fn::operator();
};
RANGES_INLINE_VARIABLE(move_fn, move)
#endif
namespace cpp20
{
using ranges::move_result;
using ranges::RANGES_HIDDEN_DETAIL(_move::) move;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,75 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_MOVE_BACKWARD_HPP
#define RANGES_V3_ALGORITHM_MOVE_BACKWARD_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using move_backward_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(move_backward)
/// \brief function template \c move_backward
template(typename I, typename S, typename O)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
bidirectional_iterator<O> AND indirectly_movable<I, O>)
constexpr move_backward_result<I, O> RANGES_FUNC(move_backward)(I first, S end_, O out) //
{
I i = ranges::next(first, end_), last = i;
while(first != i)
*--out = iter_move(--i);
return {last, out};
}
/// \overload
template(typename Rng, typename O)(
requires bidirectional_range<Rng> AND bidirectional_iterator<O> AND
indirectly_movable<iterator_t<Rng>, O>)
constexpr move_backward_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(move_backward)(Rng && rng, O out) //
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(move_backward)
namespace cpp20
{
using ranges::move_backward;
using ranges::move_backward_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,70 @@
/// \file
// Range v3 library
//
// Copyright Andrew Sutton 2014
// 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
//
#ifndef RANGES_V3_ALGORITHM_NONE_OF_HPP
#define RANGES_V3_ALGORITHM_NONE_OF_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(none_of)
/// \brief function template \c none_of
template(typename I, typename S, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<F, projected<I, P>>)
constexpr bool RANGES_FUNC(none_of)(I first, S last, F pred, P proj = P{}) //
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
return false;
return true;
}
/// \overload
template(typename Rng, typename F, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>)
constexpr bool RANGES_FUNC(none_of)(Rng && rng, F pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(none_of)
namespace cpp20
{
using ranges::none_of;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,337 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_NTH_ELEMENT_HPP
#define RANGES_V3_ALGORITHM_NTH_ELEMENT_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/min_element.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/optional.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
// stable, 2-3 compares, 0-2 swaps
template(typename I, typename C, typename P)(
requires forward_iterator<I> AND indirect_relation<C, projected<I, P>>)
unsigned sort3(I x, I y, I z, C & pred, P & proj)
{
unsigned r = 0;
if(!invoke(pred, invoke(proj, *y), invoke(proj, *x))) // if x <= y
{
if(!invoke(pred, invoke(proj, *z), invoke(proj, *y))) // if y <= z
return r; // x <= y && y <= z
// x <= y && y > z
ranges::iter_swap(y, z); // x <= z && y < z
r = 1;
if(invoke(pred, invoke(proj, *y), invoke(proj, *x))) // if x > y
{
ranges::iter_swap(x, y); // x < y && y <= z
r = 2;
}
return r; // x <= y && y < z
}
if(invoke(pred, invoke(proj, *z), invoke(proj, *y))) // x > y, if y > z
{
ranges::iter_swap(x, z); // x < y && y < z
r = 1;
return r;
}
ranges::iter_swap(x, y); // x > y && y <= z
r = 1; // x < y && x <= z
if(invoke(pred, invoke(proj, *z), invoke(proj, *y))) // if y > z
{
ranges::iter_swap(y, z); // x <= y && y < z
r = 2;
}
return r;
} // x <= y && y <= z
template(typename I, typename C, typename P)(
requires bidirectional_iterator<I> AND indirect_relation<C, projected<I, P>>)
void selection_sort(I first, I last, C & pred, P & proj)
{
RANGES_EXPECT(first != last);
for(I lm1 = ranges::prev(last); first != lm1; ++first)
{
I i = ranges::min_element(first, last, std::ref(pred), std::ref(proj));
if(i != first)
ranges::iter_swap(first, i);
}
}
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(nth_element)
/// \brief function template \c nth_element
template(typename I, typename S, typename C = less, typename P = identity)(
requires random_access_iterator<I> AND sortable<I, C, P>)
constexpr I RANGES_FUNC(nth_element)(
I first, I nth, S end_, C pred = C{}, P proj = P{}) //
{
I last = ranges::next(nth, end_), end_orig = last;
// C is known to be a reference type
using difference_type = iter_difference_t<I>;
difference_type const limit = 7;
while(true)
{
if(nth == last)
return end_orig;
difference_type len = last - first;
switch(len)
{
case 0:
case 1:
return end_orig;
case 2:
if(invoke(pred, invoke(proj, *--last), invoke(proj, *first)))
ranges::iter_swap(first, last);
return end_orig;
case 3:
{
I m = first;
detail::sort3(first, ++m, --last, pred, proj);
return end_orig;
}
}
if(len <= limit)
{
detail::selection_sort(first, last, pred, proj);
return end_orig;
}
// len > limit >= 3
I m = first + len / 2;
I lm1 = last;
unsigned n_swaps = detail::sort3(first, m, --lm1, pred, proj);
// *m is median
// partition [first, m) < *m and *m <= [m, last)
//(this inhibits tossing elements equivalent to m around unnecessarily)
I i = first;
I j = lm1;
// j points beyond range to be tested, *lm1 is known to be <= *m
// The search going up is known to be guarded but the search coming down
// isn't. Prime the downward search with a guard.
if(!invoke(pred, invoke(proj, *i), invoke(proj, *m))) // if *first == *m
{
// *first == *m, *first doesn't go in first part
// manually guard downward moving j against i
while(true)
{
if(i == --j)
{
// *first == *m, *m <= all other elements
// Parition instead into [first, i) == *first and *first < [i,
// last)
++i; // first + 1
j = last;
if(!invoke(
pred,
invoke(proj, *first),
invoke(
proj,
*--j))) // we need a guard if *first == *(last-1)
{
while(true)
{
if(i == j)
return end_orig; // [first, last) all equivalent
// elements
if(invoke(
pred, invoke(proj, *first), invoke(proj, *i)))
{
ranges::iter_swap(i, j);
++n_swaps;
++i;
break;
}
++i;
}
}
// [first, i) == *first and *first < [j, last) and j == last -
// 1
if(i == j)
return end_orig;
while(true)
{
while(
!invoke(pred, invoke(proj, *first), invoke(proj, *i)))
++i;
while(invoke(
pred, invoke(proj, *first), invoke(proj, *--j)))
;
if(i >= j)
break;
ranges::iter_swap(i, j);
++n_swaps;
++i;
}
// [first, i) == *first and *first < [i, last)
// The first part is sorted,
if(nth < i)
return end_orig;
// nth_element the second part
// nth_element<C>(i, nth, last, pred);
first = i;
continue;
}
if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
{
ranges::iter_swap(i, j);
++n_swaps;
break; // found guard for downward moving j, now use unguarded
// partition
}
}
}
++i;
// j points beyond range to be tested, *lm1 is known to be <= *m
// if not yet partitioned...
if(i < j)
{
// known that *(i - 1) < *m
while(true)
{
// m still guards upward moving i
while(invoke(pred, invoke(proj, *i), invoke(proj, *m)))
++i;
// It is now known that a guard exists for downward moving j
while(!invoke(pred, invoke(proj, *--j), invoke(proj, *m)))
;
if(i >= j)
break;
ranges::iter_swap(i, j);
++n_swaps;
// It is known that m != j
// If m just moved, follow it
if(m == i)
m = j;
++i;
}
}
// [first, i) < *m and *m <= [i, last)
if(i != m && invoke(pred, invoke(proj, *m), invoke(proj, *i)))
{
ranges::iter_swap(i, m);
++n_swaps;
}
// [first, i) < *i and *i <= [i+1, last)
if(nth == i)
return end_orig;
const auto optional_return = [&]() -> ranges::optional<I> {
if(n_swaps == 0)
{
// We were given a perfectly partitioned sequence. Coincidence?
if(nth < i)
{
// Check for [first, i) already sorted
j = m = first;
while(++j != i)
{
if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
// not yet sorted, so sort
return ranges::nullopt;
m = j;
}
// [first, i) sorted
return end_orig;
}
else
{
// Check for [i, last) already sorted
j = m = i;
while(++j != last)
{
if(invoke(pred, invoke(proj, *j), invoke(proj, *m)))
// not yet sorted, so sort
return ranges::nullopt;
m = j;
}
// [i, last) sorted
return end_orig;
}
}
return ranges::nullopt;
}();
if(optional_return)
{
return *optional_return;
}
// nth_element on range containing nth
if(nth < i)
{
// nth_element<C>(first, nth, i, pred);
last = i;
}
else
{
// nth_element<C>(i+1, nth, last, pred);
first = ++i;
}
}
return end_orig;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires random_access_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(nth_element)(
Rng && rng, iterator_t<Rng> nth, C pred = C{}, P proj = P{}) //
{
return (*this)(
begin(rng), std::move(nth), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(nth_element)
namespace cpp20
{
using ranges::nth_element;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,87 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_PARTIAL_SORT_HPP
#define RANGES_V3_ALGORITHM_PARTIAL_SORT_HPP
#include <functional>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/heap_algorithm.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(partial_sort)
/// \brief function template \c partial_sort
template(typename I, typename S, typename C = less, typename P = identity)(
requires sortable<I, C, P> AND random_access_iterator<I> AND
sentinel_for<S, I>)
constexpr I RANGES_FUNC(partial_sort)(
I first, I middle, S last, C pred = C{}, P proj = P{}) //
{
make_heap(first, middle, ranges::ref(pred), ranges::ref(proj));
auto const len = middle - first;
I i = middle;
for(; i != last; ++i)
{
if(invoke(pred, invoke(proj, *i), invoke(proj, *first)))
{
iter_swap(i, first);
detail::sift_down_n(
first, len, first, ranges::ref(pred), ranges::ref(proj));
}
}
sort_heap(first, middle, ranges::ref(pred), ranges::ref(proj));
return i;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires sortable<iterator_t<Rng>, C, P> AND random_access_range<Rng>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(partial_sort)(
Rng && rng, iterator_t<Rng> middle, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng),
std::move(middle),
end(rng),
std::move(pred),
std::move(proj));
}
RANGES_FUNC_END(partial_sort)
namespace cpp20
{
using ranges::partial_sort;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,123 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_PARTIAL_SORT_COPY_HPP
#define RANGES_V3_ALGORITHM_PARTIAL_SORT_COPY_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/heap_algorithm.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(partial_sort_copy)
/// \brief function template \c partial_sort_copy
template(typename I,
typename SI,
typename O,
typename SO,
typename C = less,
typename PI = identity,
typename PO = identity)(
requires input_iterator<I> AND sentinel_for<SI, I> AND
random_access_iterator<O> AND sentinel_for<SO, O> AND
indirectly_copyable<I, O> AND sortable<O, C, PO> AND
indirect_strict_weak_order<C, projected<I, PI>, projected<O, PO>>)
constexpr O RANGES_FUNC(partial_sort_copy)(I first,
SI last,
O out_begin,
SO out_end,
C pred = C{},
PI in_proj = PI{},
PO out_proj = PO{}) //
{
O r = out_begin;
if(r != out_end)
{
for(; first != last && r != out_end; ++first, ++r)
*r = *first;
make_heap(out_begin, r, ranges::ref(pred), ranges::ref(out_proj));
auto len = r - out_begin;
for(; first != last; ++first)
{
auto && x = *first;
if(invoke(pred, invoke(in_proj, x), invoke(out_proj, *out_begin)))
{
*out_begin = (decltype(x) &&)x;
detail::sift_down_n(out_begin,
len,
out_begin,
ranges::ref(pred),
ranges::ref(out_proj));
}
}
sort_heap(out_begin, r, ranges::ref(pred), ranges::ref(out_proj));
}
return r;
}
/// \overload
template(typename InRng,
typename OutRng,
typename C = less,
typename PI = identity,
typename PO = identity)(
requires input_range<InRng> AND random_access_range<OutRng> AND
indirectly_copyable<iterator_t<InRng>, iterator_t<OutRng>> AND
sortable<iterator_t<OutRng>, C, PO> AND
indirect_strict_weak_order<C,
projected<iterator_t<InRng>, PI>,
projected<iterator_t<OutRng>, PO>>)
constexpr borrowed_iterator_t<OutRng> RANGES_FUNC(partial_sort_copy)(InRng && in_rng,
OutRng && out_rng,
C pred = C{},
PI in_proj = PI{},
PO out_proj = PO{}) //
{
return (*this)(begin(in_rng),
end(in_rng),
begin(out_rng),
end(out_rng),
std::move(pred),
std::move(in_proj),
std::move(out_proj));
}
RANGES_FUNC_END(partial_sort_copy)
namespace cpp20
{
using ranges::partial_sort_copy;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,137 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===-------------------------- algorithm ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_PARTITION_HPP
#define RANGES_V3_ALGORITHM_PARTITION_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I, typename S, typename C, typename P>
constexpr I partition_impl(I first, S last, C pred, P proj, std::forward_iterator_tag)
{
while(true)
{
if(first == last)
return first;
if(!invoke(pred, invoke(proj, *first)))
break;
++first;
}
for(I p = first; ++p != last;)
{
if(invoke(pred, invoke(proj, *p)))
{
ranges::iter_swap(first, p);
++first;
}
}
return first;
}
template<typename I, typename S, typename C, typename P>
constexpr I partition_impl(I first, S end_, C pred, P proj, std::bidirectional_iterator_tag)
{
I last = ranges::next(first, end_);
while(true)
{
while(true)
{
if(first == last)
return first;
if(!invoke(pred, invoke(proj, *first)))
break;
++first;
}
do
{
if(first == --last)
return first;
} while(!invoke(pred, invoke(proj, *last)));
ranges::iter_swap(first, last);
++first;
}
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(partition)
/// \brief function template \c partition
template(typename I, typename S, typename C, typename P = identity)(
requires permutable<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr I RANGES_FUNC(partition)(I first, S last, C pred, P proj = P{})
{
return detail::partition_impl(std::move(first),
std::move(last),
std::move(pred),
std::move(proj),
iterator_tag_of<I>());
}
/// \overload
template(typename Rng, typename C, typename P = identity)(
requires forward_range<Rng> AND permutable<iterator_t<Rng>> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(partition)(Rng && rng, C pred, P proj = P{})
{
return detail::partition_impl(begin(rng),
end(rng),
std::move(pred),
std::move(proj),
iterator_tag_of<iterator_t<Rng>>());
}
RANGES_FUNC_END(partition)
namespace cpp20
{
using ranges::partition;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,109 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_PARTITION_COPY_HPP
#define RANGES_V3_ALGORITHM_PARTITION_COPY_HPP
#include <tuple>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O0, typename O1>
using partition_copy_result = detail::in_out1_out2_result<I, O0, O1>;
RANGES_FUNC_BEGIN(partition_copy)
/// \brief function template \c partition_copy
template(typename I,
typename S,
typename O0,
typename O1,
typename C,
typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O0> AND weakly_incrementable<O1> AND
indirectly_copyable<I, O0> AND indirectly_copyable<I, O1> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr partition_copy_result<I, O0, O1> RANGES_FUNC(partition_copy)(
I first, S last, O0 o0, O1 o1, C pred, P proj = P{})
{
for(; first != last; ++first)
{
auto && x = *first;
if(invoke(pred, invoke(proj, x)))
{
*o0 = (decltype(x) &&)x;
++o0;
}
else
{
*o1 = (decltype(x) &&)x;
++o1;
}
}
return {first, o0, o1};
}
/// \overload
template(typename Rng,
typename O0,
typename O1,
typename C,
typename P = identity)(
requires input_range<Rng> AND weakly_incrementable<O0> AND
weakly_incrementable<O1> AND indirectly_copyable<iterator_t<Rng>, O0> AND
indirectly_copyable<iterator_t<Rng>, O1> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr partition_copy_result<borrowed_iterator_t<Rng>, O0, O1> //
RANGES_FUNC(partition_copy)(Rng && rng, O0 o0, O1 o1, C pred, P proj = P{})
{
return (*this)(begin(rng),
end(rng),
std::move(o0),
std::move(o1),
std::move(pred),
std::move(proj));
}
RANGES_FUNC_END(partition_copy)
namespace cpp20
{
using ranges::partition_copy;
using ranges::partition_copy_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,108 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
//===-------------------------- algorithm ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_PARTITION_POINT_HPP
#define RANGES_V3_ALGORITHM_PARTITION_POINT_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/partition_point_n.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(partition_point)
/// \brief function template \c partition_point
template(typename I, typename S, typename C, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr I RANGES_FUNC(partition_point)(I first, S last, C pred, P proj = P{})
{
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S, I>))
{
auto len = distance(first, std::move(last));
return aux::partition_point_n(
std::move(first), len, std::move(pred), std::move(proj));
}
// Probe exponentially for either last-of-range or an iterator
// that is past the partition point (i.e., does not satisfy pred).
auto len = iter_difference_t<I>{1};
while(true)
{
auto mid = first;
auto d = advance(mid, len, last);
if(mid == last || !invoke(pred, invoke(proj, *mid)))
{
len -= d;
return aux::partition_point_n(
std::move(first), len, ranges::ref(pred), ranges::ref(proj));
}
first = std::move(mid);
len *= 2;
}
}
/// \overload
template(typename Rng, typename C, typename P = identity)(
requires forward_range<Rng> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(partition_point)(Rng && rng, C pred, P proj = P{}) //
{
if(RANGES_CONSTEXPR_IF(sized_range<Rng>))
{
auto len = distance(rng);
return aux::partition_point_n(
begin(rng), len, std::move(pred), std::move(proj));
}
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(partition_point)
namespace cpp20
{
using ranges::partition_point;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,374 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===-------------------------- algorithm ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_PERMUTATION_HPP
#define RANGES_V3_ALGORITHM_PERMUTATION_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/mismatch.hpp>
#include <range/v3/algorithm/reverse.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I1, typename S1, typename I2, typename S2, typename C,
typename P1, typename P2>
constexpr bool is_permutation_impl(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
C pred,
P1 proj1,
P2 proj2)
{
// shorten sequences as much as possible by lopping off any equal parts
const auto mismatch =
ranges::mismatch(begin1, end1, begin2, end2, pred, proj1, proj2);
begin1 = mismatch.in1;
begin2 = mismatch.in2;
if(begin1 == end1 || begin2 == end2)
{
return begin1 == end1 && begin2 == end2;
}
// begin1 != end1 && begin2 != end2 && *begin1 != *begin2
auto l1 = distance(begin1, end1);
auto l2 = distance(begin2, end2);
if(l1 != l2)
return false;
// For each element in [f1, l1) see if there are the same number of
// equal elements in [f2, l2)
for(I1 i = begin1; i != end1; ++i)
{
// Have we already counted the number of *i in [f1, l1)?
const auto should_continue = [&] {
for(I1 j = begin1; j != i; ++j)
if(invoke(pred, invoke(proj1, *j), invoke(proj1, *i)))
return true;
return false;
}();
if(should_continue)
{
continue;
}
// Count number of *i in [f2, l2)
iter_difference_t<I2> c2 = 0;
for(I2 j = begin2; j != end2; ++j)
if(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))
++c2;
if(c2 == 0)
return false;
// Count number of *i in [i, l1) (we can start with 1)
iter_difference_t<I1> c1 = 1;
for(I1 j = next(i); j != end1; ++j)
if(invoke(pred, invoke(proj1, *i), invoke(proj1, *j)))
++c1;
if(c1 != c2)
return false;
}
return true;
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(is_permutation)
/// \brief function template \c is_permutation
template(typename I1,
typename S1,
typename I2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires forward_iterator<I1> AND sentinel_for<S1, I1> AND
forward_iterator<I2> AND indirectly_comparable<I1, I2, C, P1, P2>)
RANGES_DEPRECATED(
"Use the variant of ranges::is_permutation that takes an upper bound "
"for both sequences")
bool RANGES_FUNC(is_permutation)(I1 begin1,
S1 end1,
I2 begin2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
// shorten sequences as much as possible by lopping off any equal parts
for(; begin1 != end1; ++begin1, ++begin2)
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
goto not_done;
return true;
not_done:
// begin1 != end1 && *begin1 != *begin2
auto l1 = distance(begin1, end1);
if(l1 == 1)
return false;
I2 end2 = next(begin2, l1);
// For each element in [f1, l1) see if there are the same number of
// equal elements in [f2, l2)
for(I1 i = begin1; i != end1; ++i)
{
// Have we already counted the number of *i in [f1, l1)?
for(I1 j = begin1; j != i; ++j)
if(invoke(pred, invoke(proj1, *j), invoke(proj1, *i)))
goto next_iter;
{
// Count number of *i in [f2, l2)
iter_difference_t<I2> c2 = 0;
for(I2 j = begin2; j != end2; ++j)
if(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))
++c2;
if(c2 == 0)
return false;
// Count number of *i in [i, l1) (we can start with 1)
iter_difference_t<I1> c1 = 1;
for(I1 j = next(i); j != end1; ++j)
if(invoke(pred, invoke(proj1, *i), invoke(proj1, *j)))
++c1;
if(c1 != c2)
return false;
}
next_iter:;
}
return true;
}
/// \overload
template(typename I1,
typename S1,
typename I2,
typename S2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires forward_iterator<I1> AND sentinel_for<S1, I1> AND
forward_iterator<I2> AND sentinel_for<S2, I2> AND
indirectly_comparable<I1, I2, C, P1, P2>)
constexpr bool RANGES_FUNC(is_permutation)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S1, I1> &&
sized_sentinel_for<S2, I2>))
{
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
return distance(begin1, end1) == distance(begin2, end2) &&
(*this)(std::move(begin1),
std::move(end1),
std::move(begin2),
std::move(pred),
std::move(proj1),
std::move(proj2));
RANGES_DIAGNOSTIC_POP
}
return detail::is_permutation_impl(std::move(begin1),
std::move(end1),
std::move(begin2),
std::move(end2),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
/// \overload
template(typename Rng1,
typename I2Ref,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires forward_range<Rng1> AND forward_iterator<uncvref_t<I2Ref>> AND
indirectly_comparable<iterator_t<Rng1>, uncvref_t<I2Ref>, C, P1, P2>)
RANGES_DEPRECATED(
"Use the variant of ranges::is_permutation that takes an upper bound "
"for both sequences")
bool RANGES_FUNC(is_permutation)(Rng1 && rng1,
I2Ref && begin2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
return (*this)(begin(rng1),
end(rng1),
(I2Ref &&) begin2,
std::move(pred),
std::move(proj1),
std::move(proj2));
RANGES_DIAGNOSTIC_POP
}
/// \overload
template(typename Rng1,
typename Rng2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires forward_range<Rng1> AND forward_range<Rng2> AND
indirectly_comparable<iterator_t<Rng1>, iterator_t<Rng2>, C, P1, P2>)
constexpr bool RANGES_FUNC(is_permutation)(
Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) //
{
if(RANGES_CONSTEXPR_IF(sized_range<Rng1> && sized_range<Rng2>))
{
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
return distance(rng1) == distance(rng2) && (*this)(begin(rng1),
end(rng1),
begin(rng2),
std::move(pred),
std::move(proj1),
std::move(proj2));
RANGES_DIAGNOSTIC_POP
}
return detail::is_permutation_impl(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(is_permutation)
RANGES_FUNC_BEGIN(next_permutation)
/// \brief function template \c next_permutation
template(typename I, typename S, typename C = less, typename P = identity)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr bool RANGES_FUNC(next_permutation)(I first, S end_, C pred = C{}, P proj = P{}) //
{
if(first == end_)
return false;
I last = ranges::next(first, end_), i = last;
if(first == --i)
return false;
while(true)
{
I ip1 = i;
if(invoke(pred, invoke(proj, *--i), invoke(proj, *ip1)))
{
I j = last;
while(!invoke(pred, invoke(proj, *i), invoke(proj, *--j)))
;
ranges::iter_swap(i, j);
ranges::reverse(ip1, last);
return true;
}
if(i == first)
{
ranges::reverse(first, last);
return false;
}
}
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires bidirectional_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr bool RANGES_FUNC(next_permutation)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(next_permutation)
RANGES_FUNC_BEGIN(prev_permutation)
/// \brief function template \c prev_permutation
template(typename I, typename S, typename C = less, typename P = identity)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
sortable<I, C, P>)
constexpr bool RANGES_FUNC(prev_permutation)(I first, S end_, C pred = C{}, P proj = P{}) //
{
if(first == end_)
return false;
I last = ranges::next(first, end_), i = last;
if(first == --i)
return false;
while(true)
{
I ip1 = i;
if(invoke(pred, invoke(proj, *ip1), invoke(proj, *--i)))
{
I j = last;
while(!invoke(pred, invoke(proj, *--j), invoke(proj, *i)))
;
ranges::iter_swap(i, j);
ranges::reverse(ip1, last);
return true;
}
if(i == first)
{
ranges::reverse(first, last);
return false;
}
}
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires bidirectional_range<Rng> AND sortable<iterator_t<Rng>, C, P>)
constexpr bool RANGES_FUNC(prev_permutation)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(prev_permutation)
namespace cpp20
{
using ranges::is_permutation;
using ranges::next_permutation;
using ranges::prev_permutation;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,82 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REMOVE_HPP
#define RANGES_V3_ALGORITHM_REMOVE_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/find.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(remove)
/// \brief function template \c remove
template(typename I, typename S, typename T, typename P = identity)(
requires permutable<I> AND sentinel_for<S, I> AND
indirect_relation<equal_to, projected<I, P>, T const *>)
constexpr I RANGES_FUNC(remove)(I first, S last, T const & val, P proj = P{})
{
first = find(std::move(first), last, val, ranges::ref(proj));
if(first != last)
{
for(I i = next(first); i != last; ++i)
{
if(!(invoke(proj, *i) == val))
{
*first = iter_move(i);
++first;
}
}
}
return first;
}
/// \overload
template(typename Rng, typename T, typename P = identity)(
requires forward_range<Rng> AND permutable<iterator_t<Rng>> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T const *>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(remove)(Rng && rng, T const & val, P proj = P{})
{
return (*this)(begin(rng), end(rng), val, std::move(proj));
}
RANGES_FUNC_END(remove)
namespace cpp20
{
using ranges::remove;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,86 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REMOVE_COPY_HPP
#define RANGES_V3_ALGORITHM_REMOVE_COPY_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using remove_copy_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(remove_copy)
/// \brief function template \c remove_copy
template(typename I, typename S, typename O, typename T, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND
indirect_relation<equal_to, projected<I, P>, T const *> AND
indirectly_copyable<I, O>)
constexpr remove_copy_result<I, O> RANGES_FUNC(remove_copy)(
I first, S last, O out, T const & val, P proj = P{}) //
{
for(; first != last; ++first)
{
auto && x = *first;
if(!(invoke(proj, x) == val))
{
*out = (decltype(x) &&)x;
++out;
}
}
return {first, out};
}
/// \overload
template(typename Rng, typename O, typename T, typename P = identity)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T const *> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr remove_copy_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(remove_copy)(Rng && rng, O out, T const & val, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(out), val, std::move(proj));
}
RANGES_FUNC_END(remove_copy)
namespace cpp20
{
using ranges::remove_copy;
using ranges::remove_copy_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,86 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REMOVE_COPY_IF_HPP
#define RANGES_V3_ALGORITHM_REMOVE_COPY_IF_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using remove_copy_if_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(remove_copy_if)
/// \brief function template \c remove_copy_if
template(typename I, typename S, typename O, typename C, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirect_unary_predicate<C, projected<I, P>> AND
indirectly_copyable<I, O>)
constexpr remove_copy_if_result<I, O> //
RANGES_FUNC(remove_copy_if)(I first, S last, O out, C pred, P proj = P{}) //
{
for(; first != last; ++first)
{
auto && x = *first;
if(!(invoke(pred, invoke(proj, x))))
{
*out = (decltype(x) &&)x;
++out;
}
}
return {first, out};
}
/// \overload
template(typename Rng, typename O, typename C, typename P = identity)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr remove_copy_if_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(remove_copy_if)(Rng && rng, O out, C pred, P proj = P{}) //
{
return (*this)(
begin(rng), end(rng), std::move(out), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(remove_copy_if)
namespace cpp20
{
using ranges::remove_copy_if;
using ranges::remove_copy_if_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,81 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REMOVE_IF_HPP
#define RANGES_V3_ALGORITHM_REMOVE_IF_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/find_if.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(remove_if)
/// \brief function template \c remove_if
template(typename I, typename S, typename C, typename P = identity)(
requires permutable<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr I RANGES_FUNC(remove_if)(I first, S last, C pred, P proj = P{})
{
first = find_if(std::move(first), last, ranges::ref(pred), ranges::ref(proj));
if(first != last)
{
for(I i = next(first); i != last; ++i)
{
if(!(invoke(pred, invoke(proj, *i))))
{
*first = iter_move(i);
++first;
}
}
}
return first;
}
/// \overload
template(typename Rng, typename C, typename P = identity)(
requires forward_range<Rng> AND permutable<iterator_t<Rng>> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(remove_if)(Rng && rng, C pred, P proj = P{})
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(remove_if)
namespace cpp20
{
using ranges::remove_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,74 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REPLACE_HPP
#define RANGES_V3_ALGORITHM_REPLACE_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(replace)
/// \brief function template \c replace
template(typename I, typename S, typename T1, typename T2, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirectly_writable<I, T2 const &> AND
indirect_relation<equal_to, projected<I, P>, T1 const *>)
constexpr I RANGES_FUNC(replace)(
I first, S last, T1 const & old_value, T2 const & new_value, P proj = {}) //
{
for(; first != last; ++first)
if(invoke(proj, *first) == old_value)
*first = new_value;
return first;
}
/// \overload
template(typename Rng, typename T1, typename T2, typename P = identity)(
requires input_range<Rng> AND
indirectly_writable<iterator_t<Rng>, T2 const &> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T1 const *>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(replace)(
Rng && rng, T1 const & old_value, T2 const & new_value, P proj = {}) //
{
return (*this)(begin(rng), end(rng), old_value, new_value, std::move(proj));
}
RANGES_FUNC_END(replace)
namespace cpp20
{
using ranges::replace;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,102 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REPLACE_COPY_HPP
#define RANGES_V3_ALGORITHM_REPLACE_COPY_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using replace_copy_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(replace_copy)
/// \brief function template \c replace_copy
template(typename I,
typename S,
typename O,
typename T1,
typename T2,
typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
output_iterator<O, T2 const &> AND indirectly_copyable<I, O> AND
indirect_relation<equal_to, projected<I, P>, T1 const *>)
constexpr replace_copy_result<I, O> RANGES_FUNC(replace_copy)(I first,
S last,
O out,
T1 const & old_value,
T2 const & new_value,
P proj = {}) //
{
for(; first != last; ++first, ++out)
{
auto && x = *first;
if(invoke(proj, x) == old_value)
*out = new_value;
else
*out = (decltype(x) &&)x;
}
return {first, out};
}
/// \overload
template(typename Rng,
typename O,
typename T1,
typename T2,
typename P = identity)(
requires input_range<Rng> AND output_iterator<O, T2 const &> AND
indirectly_copyable<iterator_t<Rng>, O> AND
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T1 const *>)
constexpr replace_copy_result<borrowed_iterator_t<Rng>, O> RANGES_FUNC(replace_copy)(
Rng && rng, O out, T1 const & old_value, T2 const & new_value, P proj = {}) //
{
return (*this)(begin(rng),
end(rng),
std::move(out),
old_value,
new_value,
std::move(proj));
}
RANGES_FUNC_END(replace_copy)
namespace cpp20
{
using ranges::replace_copy;
using ranges::replace_copy_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,95 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REPLACE_COPY_IF_HPP
#define RANGES_V3_ALGORITHM_REPLACE_COPY_IF_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using replace_copy_if_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(replace_copy_if)
/// \brief function template \c replace_copy_if
template(typename I,
typename S,
typename O,
typename C,
typename T,
typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
output_iterator<O, T const &> AND
indirect_unary_predicate<C, projected<I, P>> AND
indirectly_copyable<I, O>)
constexpr replace_copy_if_result<I, O> RANGES_FUNC(replace_copy_if)(
I first, S last, O out, C pred, T const & new_value, P proj = {}) //
{
for(; first != last; ++first, ++out)
{
auto && x = *first;
if(invoke(pred, invoke(proj, x)))
*out = new_value;
else
*out = (decltype(x) &&)x;
}
return {first, out};
}
/// \overload
template(typename Rng, typename O, typename C, typename T, typename P = identity)(
requires input_range<Rng> AND output_iterator<O, T const &> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr replace_copy_if_result<borrowed_iterator_t<Rng>, O> RANGES_FUNC(replace_copy_if)(
Rng && rng, O out, C pred, T const & new_value, P proj = {}) //
{
return (*this)(begin(rng),
end(rng),
std::move(out),
std::move(pred),
new_value,
std::move(proj));
}
RANGES_FUNC_END(replace_copy_if)
namespace cpp20
{
using ranges::replace_copy_if;
using ranges::replace_copy_if_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,75 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REPLACE_IF_HPP
#define RANGES_V3_ALGORITHM_REPLACE_IF_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(replace_if)
/// \brief function template \c replace_if
template(typename I, typename S, typename C, typename T, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>> AND
indirectly_writable<I, T const &>)
constexpr I RANGES_FUNC(replace_if)(
I first, S last, C pred, T const & new_value, P proj = P{}) //
{
for(; first != last; ++first)
if(invoke(pred, invoke(proj, *first)))
*first = new_value;
return first;
}
/// \overload
template(typename Rng, typename C, typename T, typename P = identity)(
requires input_range<Rng> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> AND
indirectly_writable<iterator_t<Rng>, T const &>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(replace_if)(
Rng && rng, C pred, T const & new_value, P proj = P{}) //
{
return (*this)(
begin(rng), end(rng), std::move(pred), new_value, std::move(proj));
}
RANGES_FUNC_END(replace_if)
namespace cpp20
{
using ranges::replace_if;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,169 @@
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
#ifndef RANGES_V3_ALGORITHM_RESULT_TYPES_HPP
#define RANGES_V3_ALGORITHM_RESULT_TYPES_HPP
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
// Extensions: the dangling story actually works, and result structs
// are conditionally equality_comparable
#define RANGES_ALGO_RESULT_AUX_2(C, T1, M1, T2, M2) \
template(typename X, typename Y)( \
requires convertible_to<T1 const &, X> AND convertible_to<T2 const &, Y>) \
operator C<X, Y>() const & \
{ \
return {M1, M2}; \
} \
template(typename X, typename Y)( \
requires convertible_to<T1, X> AND convertible_to<T2, Y>) \
operator C<X, Y>() && \
{ \
return {static_cast<T1 &&>(M1), static_cast<T2 &&>(M2)}; \
} \
CPP_broken_friend_member \
friend constexpr auto operator==(C<T1, T2> const & x, C<T1, T2> const & y) \
-> CPP_broken_friend_ret(bool)( \
requires equality_comparable<T1> && equality_comparable<T2>) \
{ \
return x.M1 == y.M1 && x.M2 == y.M2; \
} \
CPP_broken_friend_member \
friend constexpr auto operator!=(C<T1, T2> const & x, C<T1, T2> const & y) \
-> CPP_broken_friend_ret(bool)( \
requires equality_comparable<T1> && equality_comparable<T2>) \
{ \
return !(x == y); \
} \
/**/
#define RANGES_ALGO_RESULT_AUX_3(C, T1, M1, T2, M2, T3, M3) \
template(typename X, typename Y, typename Z)( \
requires convertible_to<T1 const &, X> AND convertible_to<T2 const &, Y> AND \
convertible_to<T3 const &, Z>) \
operator C<X, Y, Z>() const & \
{ \
return {M1, M2, M3}; \
} \
template(typename X, typename Y, typename Z)( \
requires convertible_to<T1, X> AND convertible_to<T2, Y> AND \
convertible_to<T3, Z>) \
operator C<X, Y, Z>() && \
{ \
return {static_cast<T1 &&>(M1), static_cast<T2 &&>(M2), static_cast<T3 &&>(M3)}; \
} \
CPP_broken_friend_member \
friend constexpr auto operator==(C<T1, T2, T3> const & x, C<T1, T2, T3> const & y) \
-> CPP_broken_friend_ret(bool)( \
requires equality_comparable<T1> && equality_comparable<T2> && \
equality_comparable<T3>) \
{ \
return x.M1 == y.M1 && x.M2 == y.M2 && x.M3 == y.M3; \
} \
CPP_broken_friend_member \
friend constexpr auto operator!=(C<T1, T2, T3> const & x, C<T1, T2, T3> const & y) \
-> CPP_broken_friend_ret(bool)( \
requires equality_comparable<T1> && equality_comparable<T2> && \
equality_comparable<T3>) \
{ \
return !(x == y); \
} \
/**/
template<typename I, typename O>
struct in_out_result
{
I in;
O out;
RANGES_ALGO_RESULT_AUX_2(in_out_result, I, in, O, out)
};
template<typename I1, typename O>
struct in1_out_result
{
I1 in1;
O out;
RANGES_ALGO_RESULT_AUX_2(in1_out_result, I1, in1, O, out)
};
template<typename I1, typename I2>
struct in1_in2_result
{
I1 in1;
I2 in2;
RANGES_ALGO_RESULT_AUX_2(in1_in2_result, I1, in1, I2, in2)
};
template<typename I, typename Fun>
struct in_fun_result
{
I in;
Fun fun;
RANGES_ALGO_RESULT_AUX_2(in_fun_result, I, in, Fun, fun)
};
template<typename O, typename Fun>
struct out_fun_result
{
O out;
Fun fun;
RANGES_ALGO_RESULT_AUX_2(out_fun_result, O, out, Fun, fun)
};
template<typename T, typename U>
struct min_max_result
{
T min;
U max;
RANGES_ALGO_RESULT_AUX_2(min_max_result, T, min, U, max)
};
template<typename I1, typename I2, typename O>
struct in1_in2_out_result
{
I1 in1;
I2 in2;
O out;
RANGES_ALGO_RESULT_AUX_3(in1_in2_out_result, I1, in1, I2, in2, O, out)
};
template<typename I, typename O1, typename O2>
struct in_out1_out2_result
{
I in;
O1 out1;
O2 out2;
RANGES_ALGO_RESULT_AUX_3(in_out1_out2_result, I, in, O1, out1, O2, out2)
};
} // namespace detail
/// \endcond
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,91 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REVERSE_HPP
#define RANGES_V3_ALGORITHM_REVERSE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I>
constexpr void reverse_impl(I first, I last, std::bidirectional_iterator_tag)
{
while(first != last)
{
if(first == --last)
break;
ranges::iter_swap(first, last);
++first;
}
}
template<typename I>
constexpr void reverse_impl(I first, I last, std::random_access_iterator_tag)
{
if(first != last)
for(; first < --last; ++first)
ranges::iter_swap(first, last);
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(reverse)
/// \brief function template \c reverse
template(typename I, typename S)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND permutable<I>)
constexpr I RANGES_FUNC(reverse)(I first, S end_)
{
I last = ranges::next(first, end_);
detail::reverse_impl(first, last, iterator_tag_of<I>{});
return last;
}
/// \overload
template(typename Rng, typename I = iterator_t<Rng>)(
requires bidirectional_range<Rng> AND permutable<I>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(reverse)(Rng && rng) //
{
return (*this)(begin(rng), end(rng));
}
RANGES_FUNC_END(reverse)
namespace cpp20
{
using ranges::reverse;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,75 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_REVERSE_COPY_HPP
#define RANGES_V3_ALGORITHM_REVERSE_COPY_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using reverse_copy_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(reverse_copy)
/// \brief function template \c reverse_copy
template(typename I, typename S, typename O)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirectly_copyable<I, O>)
constexpr reverse_copy_result<I, O> RANGES_FUNC(reverse_copy)(I first, S end_, O out) //
{
I last = ranges::next(first, end_), res = last;
for(; first != last; ++out)
*out = *--last;
return {res, out};
}
/// \overload
template(typename Rng, typename O)(
requires bidirectional_range<Rng> AND weakly_incrementable<O> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr reverse_copy_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(reverse_copy)(Rng && rng, O out) //
{
return (*this)(begin(rng), end(rng), std::move(out));
}
RANGES_FUNC_END(reverse_copy)
namespace cpp20
{
using ranges::reverse_copy;
using ranges::reverse_copy_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,234 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_ROTATE_HPP
#define RANGES_V3_ALGORITHM_ROTATE_HPP
#include <type_traits>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/move.hpp>
#include <range/v3/algorithm/move_backward.hpp>
#include <range/v3/algorithm/swap_ranges.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/move.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I> // Forward
constexpr subrange<I> rotate_left(I first, I last)
{
iter_value_t<I> tmp = iter_move(first);
I lm1 = ranges::move(next(first), last, first).out;
*lm1 = std::move(tmp);
return {lm1, last};
}
template<typename I> // Bidirectional
constexpr subrange<I> rotate_right(I first, I last)
{
I lm1 = prev(last);
iter_value_t<I> tmp = iter_move(lm1);
I fp1 = move_backward(first, lm1, last).out;
*first = std::move(tmp);
return {fp1, last};
}
template<typename I, typename S> // Forward
constexpr subrange<I> rotate_forward(I first, I middle, S last)
{
I i = middle;
while(true)
{
ranges::iter_swap(first, i);
++first;
if(++i == last)
break;
if(first == middle)
middle = i;
}
I r = first;
if(first != middle)
{
I j = middle;
while(true)
{
ranges::iter_swap(first, j);
++first;
if(++j == last)
{
if(first == middle)
break;
j = middle;
}
else if(first == middle)
middle = j;
}
}
return {r, i};
}
template<typename D>
constexpr D gcd(D x, D y)
{
do
{
D t = x % y;
x = y;
y = t;
} while(y);
return x;
}
template<typename I> // Random
constexpr subrange<I> rotate_gcd(I first, I middle, I last)
{
auto const m1 = middle - first;
auto const m2 = last - middle;
if(m1 == m2)
{
swap_ranges(first, middle, middle);
return {middle, last};
}
auto const g = detail::gcd(m1, m2);
for(I p = first + g; p != first;)
{
iter_value_t<I> t = iter_move(--p);
I p1 = p;
I p2 = p1 + m1;
do
{
*p1 = iter_move(p2);
p1 = p2;
auto const d = last - p2;
if(m1 < d)
p2 += m1;
else
p2 = first + (m1 - d);
} while(p2 != p);
*p1 = std::move(t);
}
return {first + m2, last};
}
template<typename I, typename S>
constexpr subrange<I> rotate_(I first, I middle, S last, std::forward_iterator_tag)
{
return detail::rotate_forward(first, middle, last);
}
template<typename I>
constexpr subrange<I> rotate_(I first, I middle, I last, std::forward_iterator_tag)
{
using value_type = iter_value_t<I>;
if(detail::is_trivially_move_assignable_v<value_type>)
{
if(next(first) == middle)
return detail::rotate_left(first, last);
}
return detail::rotate_forward(first, middle, last);
}
template<typename I>
constexpr subrange<I> rotate_(I first, I middle, I last, std::bidirectional_iterator_tag)
{
using value_type = iter_value_t<I>;
if(detail::is_trivially_move_assignable_v<value_type>)
{
if(next(first) == middle)
return detail::rotate_left(first, last);
if(next(middle) == last)
return detail::rotate_right(first, last);
}
return detail::rotate_forward(first, middle, last);
}
template<typename I>
constexpr subrange<I> rotate_(I first, I middle, I last, std::random_access_iterator_tag)
{
using value_type = iter_value_t<I>;
if(detail::is_trivially_move_assignable_v<value_type>)
{
if(next(first) == middle)
return detail::rotate_left(first, last);
if(next(middle) == last)
return detail::rotate_right(first, last);
return detail::rotate_gcd(first, middle, last);
}
return detail::rotate_forward(first, middle, last);
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(rotate)
/// \brief function template \c rotate
template(typename I, typename S)(
requires permutable<I> AND sentinel_for<S, I>)
constexpr subrange<I> RANGES_FUNC(rotate)(I first, I middle, S last) //
{
if(first == middle)
{
first = ranges::next(std::move(first), last);
return {first, first};
}
if(middle == last)
{
return {first, middle};
}
return detail::rotate_(first, middle, last, iterator_tag_of<I>{});
}
/// \overload
template(typename Rng, typename I = iterator_t<Rng>)(
requires range<Rng> AND permutable<I>)
constexpr borrowed_subrange_t<Rng> RANGES_FUNC(rotate)(Rng && rng, I middle) //
{
return (*this)(begin(rng), std::move(middle), end(rng));
}
RANGES_FUNC_END(rotate)
namespace cpp20
{
using ranges::rotate;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,76 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_ROTATE_COPY_HPP
#define RANGES_V3_ALGORITHM_ROTATE_COPY_HPP
#include <functional>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/copy.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using rotate_copy_result = detail::in_out_result<I, O>;
RANGES_FUNC_BEGIN(rotate_copy)
/// \brief function template \c rotate_copy
template(typename I, typename S, typename O, typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirectly_copyable<I, O>)
constexpr rotate_copy_result<I, O> //
RANGES_FUNC(rotate_copy)(I first, I middle, S last, O out) //
{
auto res = ranges::copy(middle, std::move(last), std::move(out));
return {std::move(res.in),
ranges::copy(std::move(first), middle, std::move(res.out)).out};
}
/// \overload
template(typename Rng, typename O, typename P = identity)(
requires range<Rng> AND weakly_incrementable<O> AND
indirectly_copyable<iterator_t<Rng>, O>)
constexpr rotate_copy_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(rotate_copy)(Rng && rng, iterator_t<Rng> middle, O out) //
{
return (*this)(begin(rng), std::move(middle), end(rng), std::move(out));
}
RANGES_FUNC_END(rotate_copy)
namespace cpp20
{
using ranges::rotate_copy;
using ranges::rotate_copy_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,250 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_SAMPLE_HPP
#define RANGES_V3_ALGORITHM_SAMPLE_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/copy_n.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/random.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using sample_result = detail::in_out_result<I, O>;
/// \cond
namespace detail
{
template<typename I, typename S, typename O, typename Gen>
sample_result<I, O> sample_sized_impl(I first,
S last,
iter_difference_t<I> pop_size,
O out,
iter_difference_t<O> sample_size,
Gen && gen)
{
if(pop_size > 0 && sample_size > 0)
{
std::uniform_int_distribution<iter_difference_t<I>> dist;
using param_t = typename decltype(dist)::param_type;
for(; first != last; ++first)
{
if(sample_size >= pop_size)
return copy_n(std::move(first), pop_size, std::move(out));
if(dist(gen, param_t{0, --pop_size}) < sample_size)
{
*out = *first;
++out;
if(--sample_size == 0)
break;
}
}
}
return {std::move(first), std::move(out)};
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(sample)
/// \brief function template \c sample
template(typename I,
typename S,
typename O,
typename Gen = detail::default_random_engine &)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND indirectly_copyable<I, O> AND
uniform_random_bit_generator<std::remove_reference_t<Gen>> AND
(random_access_iterator<O> || forward_iterator<I> ||
sized_sentinel_for<S, I>))
sample_result<I, O> RANGES_FUNC(sample)(I first,
S last,
O out,
iter_difference_t<O> const n,
Gen && gen = detail::get_random_engine())
{
if(RANGES_CONSTEXPR_IF(forward_iterator<I> || sized_sentinel_for<S, I>)) //
{
auto const k = distance(first, last);
return detail::sample_sized_impl(std::move(first),
std::move(last),
k,
std::move(out),
n,
static_cast<Gen &&>(gen));
}
else
{
// out is random-access here; calls to advance(out,n) and
// next(out,n) are O(1).
if(n > 0)
{
for(iter_difference_t<O> i = 0; i < n; (void)++i, ++first)
{
if(first == last)
{
advance(out, i);
goto done;
}
*next(out, i) = *first;
}
std::uniform_int_distribution<iter_difference_t<O>> dist;
using param_t = typename decltype(dist)::param_type;
for(auto pop_size = n; first != last; (void)++first, ++pop_size)
{
auto const i = dist(gen, param_t{0, pop_size});
if(i < n)
*next(out, i) = *first;
}
advance(out, n);
}
done:
return {std::move(first), std::move(out)};
}
}
/// \overload
template(typename I,
typename S,
typename ORng,
typename Gen = detail::default_random_engine &)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<iterator_t<ORng>> AND
indirectly_copyable<I, iterator_t<ORng>> AND
uniform_random_bit_generator<std::remove_reference_t<Gen>> AND
(forward_range<ORng> || sized_range<ORng>) AND
(random_access_iterator<iterator_t<ORng>> || forward_iterator<I> ||
sized_sentinel_for<S, I>))
sample_result<I, borrowed_iterator_t<ORng>> RANGES_FUNC(sample)(
I first,
S last,
ORng && out,
Gen && gen = detail::get_random_engine()) //
{
if(RANGES_CONSTEXPR_IF(forward_iterator<I> || sized_sentinel_for<S, I>)) //
{
auto k = distance(first, last);
return detail::sample_sized_impl(std::move(first),
std::move(last),
k,
begin(out),
distance(out),
static_cast<Gen &&>(gen));
}
else
{
return (*this)(std::move(first),
std::move(last),
begin(out),
distance(out),
static_cast<Gen &&>(gen));
}
}
/// \overload
template(typename Rng,
typename O,
typename Gen = detail::default_random_engine &)(
requires input_range<Rng> AND weakly_incrementable<O> AND
indirectly_copyable<iterator_t<Rng>, O> AND
uniform_random_bit_generator<std::remove_reference_t<Gen>> AND
(random_access_iterator<O> || forward_range<Rng> || sized_range<Rng>))
sample_result<borrowed_iterator_t<Rng>, O> RANGES_FUNC(sample)(
Rng && rng,
O out,
iter_difference_t<O> const n,
Gen && gen = detail::get_random_engine()) //
{
if(RANGES_CONSTEXPR_IF(forward_range<Rng> || sized_range<Rng>)) //
{
return detail::sample_sized_impl(begin(rng),
end(rng),
distance(rng),
std::move(out),
n,
static_cast<Gen &&>(gen));
}
else
{
return (*this)(
begin(rng), end(rng), std::move(out), n, static_cast<Gen &&>(gen));
}
}
/// \overload
template(typename IRng,
typename ORng,
typename Gen = detail::default_random_engine &)(
requires input_range<IRng> AND range<ORng> AND
indirectly_copyable<iterator_t<IRng>, iterator_t<ORng>> AND
uniform_random_bit_generator<std::remove_reference_t<Gen>> AND
(random_access_iterator<iterator_t<ORng>> || forward_range<IRng> ||
sized_range<IRng>) AND
(forward_range<ORng> || sized_range<ORng>))
sample_result<borrowed_iterator_t<IRng>, borrowed_iterator_t<ORng>> //
RANGES_FUNC(sample)(IRng && rng,
ORng && out,
Gen && gen = detail::get_random_engine())
{
if(RANGES_CONSTEXPR_IF(forward_range<IRng> || sized_range<IRng>)) //
{
return detail::sample_sized_impl(begin(rng),
end(rng),
distance(rng),
begin(out),
distance(out),
static_cast<Gen &&>(gen));
}
else
{
return (*this)(begin(rng),
end(rng),
begin(out),
distance(out),
static_cast<Gen &&>(gen));
}
}
RANGES_FUNC_END(sample)
namespace cpp20
{
using ranges::sample_result;
using ranges::sample;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,241 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_SEARCH_HPP
#define RANGES_V3_ALGORITHM_SEARCH_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/primitives.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I1, typename S1, typename D1, typename I2, typename S2,
typename D2, typename C, typename P1, typename P2>
constexpr subrange<I1> search_sized_impl(I1 const begin1_,
S1 end1,
D1 const d1_,
I2 begin2,
S2 end2,
D2 d2,
C & pred,
P1 & proj1,
P2 & proj2)
{
D1 d1 = d1_;
auto begin1 = uncounted(begin1_);
while(true)
{
// Find first element in sequence 1 that matches *begin2, with a mininum
// of loop checks
while(true)
{
if(d1 < d2) // return the last if we've run out of room
{
auto e =
ranges::next(recounted(begin1_, std::move(begin1), d1_ - d1),
std::move(end1));
return {e, e};
}
if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
break;
++begin1;
--d1;
}
// *begin1 matches *begin2, now match elements after here
auto m1 = begin1;
I2 m2 = begin2;
while(true)
{
if(++m2 == end2) // If pattern exhausted, begin1 is the answer (works
// for 1 element pattern)
{
return {recounted(begin1_, std::move(begin1), d1_ - d1),
recounted(begin1_, std::move(++m1), d1_ - d1)};
}
++m1; // No need to check, we know we have room to match successfully
if(!invoke(
pred,
invoke(proj1, *m1),
invoke(
proj2,
*m2))) // if there is a mismatch, restart with a new begin1
{
++begin1;
--d1;
break;
} // else there is a match, check next elements
}
}
}
template<typename I1, typename S1, typename I2, typename S2, typename C,
typename P1, typename P2>
constexpr subrange<I1> search_impl(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
C & pred,
P1 & proj1,
P2 & proj2)
{
while(true)
{
// Find first element in sequence 1 that matches *begin2, with a mininum
// of loop checks
while(true)
{
if(begin1 == end1) // return end1 if no element matches *begin2
return {begin1, begin1};
if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
break;
++begin1;
}
// *begin1 matches *begin2, now match elements after here
I1 m1 = begin1;
I2 m2 = begin2;
while(true)
{
if(++m2 == end2) // If pattern exhausted, begin1 is the answer (works
// for 1 element pattern)
return {begin1, ++m1};
if(++m1 == end1) // Otherwise if source exhausted, pattern not found
return {m1, m1};
if(!invoke(
pred,
invoke(proj1, *m1),
invoke(
proj2,
*m2))) // if there is a mismatch, restart with a new begin1
{
++begin1;
break;
} // else there is a match, check next elements
}
}
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(search)
/// \brief function template \c search
template(typename I1,
typename S1,
typename I2,
typename S2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires forward_iterator<I1> AND sentinel_for<S1, I1> AND
forward_iterator<I2> AND sentinel_for<S2, I2> AND
indirectly_comparable<I1, I2, C, P1, P2>)
constexpr subrange<I1> RANGES_FUNC(search)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
if(begin2 == end2)
return {begin1, begin1};
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S1, I1> &&
sized_sentinel_for<S2, I2>))
return detail::search_sized_impl(std::move(begin1),
std::move(end1),
distance(begin1, end1),
std::move(begin2),
std::move(end2),
distance(begin2, end2),
pred,
proj1,
proj2);
else
return detail::search_impl(std::move(begin1),
std::move(end1),
std::move(begin2),
std::move(end2),
pred,
proj1,
proj2);
}
/// \overload
template(typename Rng1,
typename Rng2,
typename C = equal_to,
typename P1 = identity,
typename P2 = identity)(
requires forward_range<Rng1> AND forward_range<Rng2> AND
indirectly_comparable<iterator_t<Rng1>, iterator_t<Rng2>, C, P1, P2>)
constexpr borrowed_subrange_t<Rng1> RANGES_FUNC(search)(
Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) //
{
if(empty(rng2))
return subrange<iterator_t<Rng1>>{begin(rng1), begin(rng1)};
if(RANGES_CONSTEXPR_IF(sized_range<Rng1> && sized_range<Rng2>))
return detail::search_sized_impl(begin(rng1),
end(rng1),
distance(rng1),
begin(rng2),
end(rng2),
distance(rng2),
pred,
proj1,
proj2);
else
return detail::search_impl(
begin(rng1), end(rng1), begin(rng2), end(rng2), pred, proj1, proj2);
}
RANGES_FUNC_END(search)
namespace cpp20
{
using ranges::search;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,206 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_SEARCH_N_HPP
#define RANGES_V3_ALGORITHM_SEARCH_N_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/primitives.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I, typename S, typename D, typename V, typename C, typename P>
constexpr subrange<I> search_n_sized_impl(I const begin_,
S last,
D const d_,
D cnt,
V const & val,
C & pred,
P & proj)
{
D d = d_; // always the distance from first to end
auto first = uncounted(begin_);
while(true)
{
// Find first element in sequence 1 that matches val, with a mininum of
// loop checks
while(true)
{
if(d < cnt) // return the last if we've run out of room
{
auto e = ranges::next(recounted(begin_, std::move(first), d_ - d),
std::move(last));
return {e, e};
}
if(invoke(pred, invoke(proj, *first), val))
break;
++first;
--d;
}
// *first matches val, now match elements after here
auto m = first;
D c = 0;
while(true)
{
if(++c == cnt) // If pattern exhausted, first is the answer (works
// for 1 element pattern)
return {recounted(begin_, std::move(first), d_ - d),
recounted(begin_, std::move(++m), d_ - d)};
++m; // No need to check, we know we have room to match successfully
if(!invoke(pred,
invoke(proj, *m),
val)) // if there is a mismatch, restart with a new begin
{
first = next(std::move(m));
d -= (c + 1);
break;
} // else there is a match, check next elements
}
}
}
template<typename I, typename S, typename D, typename V, typename C, typename P>
constexpr subrange<I> search_n_impl(I first,
S last,
D cnt,
V const & val,
C & pred,
P & proj)
{
while(true)
{
// Find first element in sequence 1 that matches val, with a mininum of
// loop checks
while(true)
{
if(first == last) // return last if no element matches val
return {first, first};
if(invoke(pred, invoke(proj, *first), val))
break;
++first;
}
// *first matches val, now match elements after here
I m = first;
D c = 0;
while(true)
{
if(++c == cnt) // If pattern exhausted, first is the answer (works
// for 1 element pattern)
return {first, ++m};
if(++m == last) // Otherwise if source exhausted, pattern not found
return {m, m};
if(!invoke(pred,
invoke(proj, *m),
val)) // if there is a mismatch, restart with a new begin
{
first = next(std::move(m));
break;
} // else there is a match, check next elements
}
}
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(search_n)
/// \brief function template \c search_n
template(typename I,
typename S,
typename V,
typename C = equal_to,
typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirectly_comparable<I, V const *, C, P>)
constexpr subrange<I> RANGES_FUNC(search_n)(I first,
S last,
iter_difference_t<I> cnt,
V const & val,
C pred = C{},
P proj = P{}) //
{
if(cnt <= 0)
return {first, first};
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S, I>))
return detail::search_n_sized_impl(std::move(first),
std::move(last),
distance(first, last),
cnt,
val,
pred,
proj);
else
return detail::search_n_impl(
std::move(first), std::move(last), cnt, val, pred, proj);
}
/// \overload
template(typename Rng, typename V, typename C = equal_to, typename P = identity)(
requires forward_range<Rng> AND
indirectly_comparable<iterator_t<Rng>, V const *, C, P>)
constexpr borrowed_subrange_t<Rng> RANGES_FUNC(search_n)(Rng && rng,
iter_difference_t<iterator_t<Rng>> cnt,
V const & val,
C pred = C{},
P proj = P{}) //
{
if(cnt <= 0)
return subrange<iterator_t<Rng>>{begin(rng), begin(rng)};
if(RANGES_CONSTEXPR_IF(sized_range<Rng>))
return detail::search_n_sized_impl(
begin(rng), end(rng), distance(rng), cnt, val, pred, proj);
else
return detail::search_n_impl(begin(rng), end(rng), cnt, val, pred, proj);
}
RANGES_FUNC_END(search_n)
namespace cpp20
{
using ranges::search_n;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,444 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_SET_ALGORITHM_HPP
#define RANGES_V3_ALGORITHM_SET_ALGORITHM_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/copy.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(includes)
/// \brief function template \c includes
template(typename I1,
typename S1,
typename I2,
typename S2,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND sentinel_for<S2, I2> AND
indirect_strict_weak_order<C, projected<I1, P1>, projected<I2, P2>>)
constexpr bool RANGES_FUNC(includes)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
for(; begin2 != end2; ++begin1)
{
if(begin1 == end1 ||
invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1)))
return false;
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
++begin2;
}
return true;
}
/// \overload
template(typename Rng1,
typename Rng2,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires input_range<Rng1> AND input_range<Rng2> AND
indirect_strict_weak_order<C,
projected<iterator_t<Rng1>, P1>,
projected<iterator_t<Rng2>, P2>>)
constexpr bool RANGES_FUNC(includes)(
Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(includes)
namespace cpp20
{
using ranges::includes;
}
template<typename I1, typename I2, typename O>
using set_union_result = detail::in1_in2_out_result<I1, I2, O>;
RANGES_FUNC_BEGIN(set_union)
/// \brief function template \c set_union
template(typename I1,
typename S1,
typename I2,
typename S2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires sentinel_for<S1, I1> AND sentinel_for<S2, I2> AND
mergeable<I1, I2, O, C, P1, P2>)
constexpr set_union_result<I1, I2, O> RANGES_FUNC(set_union)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
for(; begin1 != end1; ++out)
{
if(begin2 == end2)
{
auto tmp = ranges::copy(begin1, end1, out);
return {tmp.in, begin2, tmp.out};
}
if(invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1)))
{
*out = *begin2;
++begin2;
}
else
{
*out = *begin1;
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
++begin2;
++begin1;
}
}
auto tmp = ranges::copy(begin2, end2, out);
return {begin1, tmp.in, tmp.out};
}
/// \overload
template(typename Rng1,
typename Rng2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires range<Rng1> AND range<Rng2> AND
mergeable<iterator_t<Rng1>, iterator_t<Rng2>, O, C, P1, P2>)
constexpr set_union_result<borrowed_iterator_t<Rng1>, borrowed_iterator_t<Rng2>, O> //
RANGES_FUNC(set_union)(Rng1 && rng1,
Rng2 && rng2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(out),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(set_union)
namespace cpp20
{
using ranges::set_union;
using ranges::set_union_result;
} // namespace cpp20
RANGES_FUNC_BEGIN(set_intersection)
/// \brief function template \c set_intersection
template(typename I1,
typename S1,
typename I2,
typename S2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires sentinel_for<S1, I1> AND sentinel_for<S2, I2> AND
mergeable<I1, I2, O, C, P1, P2>)
constexpr O RANGES_FUNC(set_intersection)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
while(begin1 != end1 && begin2 != end2)
{
if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
++begin1;
else
{
if(!invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1)))
{
*out = *begin1;
++out;
++begin1;
}
++begin2;
}
}
return out;
}
/// \overload
template(typename Rng1,
typename Rng2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires range<Rng1> AND range<Rng2> AND
mergeable<iterator_t<Rng1>, iterator_t<Rng2>, O, C, P1, P2>)
constexpr O RANGES_FUNC(set_intersection)(Rng1 && rng1,
Rng2 && rng2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(out),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(set_intersection)
namespace cpp20
{
using ranges::set_intersection;
}
template<typename I, typename O>
using set_difference_result = detail::in1_out_result<I, O>;
RANGES_FUNC_BEGIN(set_difference)
/// \brief function template \c set_difference
template(typename I1,
typename S1,
typename I2,
typename S2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires sentinel_for<S1, I1> AND sentinel_for<S2, I2> AND
mergeable<I1, I2, O, C, P1, P2>)
constexpr set_difference_result<I1, O> RANGES_FUNC(set_difference)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
while(begin1 != end1)
{
if(begin2 == end2)
{
auto tmp = ranges::copy(begin1, end1, out);
return {tmp.in, tmp.out};
}
if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
{
*out = *begin1;
++out;
++begin1;
}
else
{
if(!invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1)))
++begin1;
++begin2;
}
}
return {begin1, out};
}
/// \overload
template(typename Rng1,
typename Rng2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires range<Rng1> AND range<Rng2> AND
mergeable<iterator_t<Rng1>, iterator_t<Rng2>, O, C, P1, P2>)
constexpr set_difference_result<borrowed_iterator_t<Rng1>, O> //
RANGES_FUNC(set_difference)(Rng1 && rng1,
Rng2 && rng2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(out),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(set_difference)
namespace cpp20
{
using ranges::set_difference;
using ranges::set_difference_result;
} // namespace cpp20
template<typename I1, typename I2, typename O>
using set_symmetric_difference_result = detail::in1_in2_out_result<I1, I2, O>;
RANGES_FUNC_BEGIN(set_symmetric_difference)
/// \brief function template \c set_symmetric_difference
template(typename I1,
typename S1,
typename I2,
typename S2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires sentinel_for<S1, I1> AND sentinel_for<S2, I2> AND
mergeable<I1, I2, O, C, P1, P2>)
constexpr set_symmetric_difference_result<I1, I2, O> //
RANGES_FUNC(set_symmetric_difference)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
while(begin1 != end1)
{
if(begin2 == end2)
{
auto tmp = ranges::copy(begin1, end1, out);
return {tmp.in, begin2, tmp.out};
}
if(invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
{
*out = *begin1;
++out;
++begin1;
}
else
{
if(invoke(pred, invoke(proj2, *begin2), invoke(proj1, *begin1)))
{
*out = *begin2;
++out;
}
else
++begin1;
++begin2;
}
}
auto tmp = ranges::copy(begin2, end2, out);
return {begin1, tmp.in, tmp.out};
}
/// \overload
template(typename Rng1,
typename Rng2,
typename O,
typename C = less,
typename P1 = identity,
typename P2 = identity)(
requires range<Rng1> AND range<Rng2> AND
mergeable<iterator_t<Rng1>, iterator_t<Rng2>, O, C, P1, P2>)
constexpr set_symmetric_difference_result<borrowed_iterator_t<Rng1>,
borrowed_iterator_t<Rng2>,
O>
RANGES_FUNC(set_symmetric_difference)(Rng1 && rng1,
Rng2 && rng2,
O out,
C pred = C{},
P1 proj1 = P1{},
P2 proj2 = P2{}) //
{
return (*this)(begin(rng1),
end(rng1),
begin(rng2),
end(rng2),
std::move(out),
std::move(pred),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(set_symmetric_difference)
namespace cpp20
{
using ranges::set_symmetric_difference;
using ranges::set_symmetric_difference_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,90 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_SHUFFLE_HPP
#define RANGES_V3_ALGORITHM_SHUFFLE_HPP
#include <cstdint>
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/random.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(shuffle)
/// \brief function template \c shuffle
template(typename I, typename S, typename Gen = detail::default_random_engine &)(
requires random_access_iterator<I> AND sentinel_for<S, I> AND
permutable<I> AND
uniform_random_bit_generator<std::remove_reference_t<Gen>> AND
convertible_to<invoke_result_t<Gen &>, iter_difference_t<I>>)
I RANGES_FUNC(shuffle)(I const first,
S const last,
Gen && gen = detail::get_random_engine()) //
{
auto mid = first;
if(mid == last)
return mid;
using D1 = iter_difference_t<I>;
using D2 =
meta::conditional_t<std::is_integral<D1>::value, D1, std::ptrdiff_t>;
std::uniform_int_distribution<D2> uid{};
using param_t = typename decltype(uid)::param_type;
while(++mid != last)
{
RANGES_ENSURE(mid - first <= PTRDIFF_MAX);
if(auto const i = uid(gen, param_t{0, D2(mid - first)}))
ranges::iter_swap(mid - i, mid);
}
return mid;
}
/// \overload
template(typename Rng, typename Gen = detail::default_random_engine &)(
requires random_access_range<Rng> AND permutable<iterator_t<Rng>> AND
uniform_random_bit_generator<std::remove_reference_t<Gen>> AND
convertible_to<invoke_result_t<Gen &>,
iter_difference_t<iterator_t<Rng>>>)
borrowed_iterator_t<Rng> //
RANGES_FUNC(shuffle)(Rng && rng, Gen && rand = detail::get_random_engine()) //
{
return (*this)(begin(rng), end(rng), static_cast<Gen &&>(rand));
}
RANGES_FUNC_END(shuffle)
namespace cpp20
{
using ranges::shuffle;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,234 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
// Copyright (c) 1994
// Hewlett-Packard Company
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Hewlett-Packard Company makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
//
// Copyright (c) 1996
// Silicon Graphics Computer Systems, Inc.
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Silicon Graphics makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
//
#ifndef RANGES_V3_ALGORITHM_SORT_HPP
#define RANGES_V3_ALGORITHM_SORT_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/heap_algorithm.hpp>
#include <range/v3/algorithm/move_backward.hpp>
#include <range/v3/algorithm/partial_sort.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
namespace detail
{
template<typename I, typename C, typename P>
inline constexpr I unguarded_partition(I first, I last, C & pred, P & proj)
{
I mid = first + (last - first) / 2, penultimate = ranges::prev(last);
auto &&x = *first, &&y = *mid, &&z = *penultimate;
auto &&a = invoke(proj, (decltype(x) &&)x),
&&b = invoke(proj, (decltype(y) &&)y),
&&c = invoke(proj, (decltype(z) &&)z);
// Find the median:
I pivot_pnt =
invoke(pred, a, b)
? (invoke(pred, b, c) ? mid
: (invoke(pred, a, c) ? penultimate : first))
: (invoke(pred, a, c) ? first
: (invoke(pred, b, c) ? penultimate : mid));
// Do the partition:
while(true)
{
auto && v = *pivot_pnt;
auto && pivot = invoke(proj, (decltype(v) &&)v);
while(invoke(pred, invoke(proj, *first), pivot))
++first;
--last;
while(invoke(pred, pivot, invoke(proj, *last)))
--last;
if(!(first < last))
return first;
ranges::iter_swap(first, last);
pivot_pnt =
pivot_pnt == first ? last : (pivot_pnt == last ? first : pivot_pnt);
++first;
}
}
template<typename I, typename C, typename P>
inline constexpr void unguarded_linear_insert(I last,
iter_value_t<I> val,
C & pred,
P & proj)
{
I next_ = prev(last);
while(invoke(pred, invoke(proj, val), invoke(proj, *next_)))
{
*last = iter_move(next_);
last = next_;
--next_;
}
*last = std::move(val);
}
template<typename I, typename C, typename P>
inline constexpr void linear_insert(I first, I last, C & pred, P & proj)
{
iter_value_t<I> val = iter_move(last);
if(invoke(pred, invoke(proj, val), invoke(proj, *first)))
{
move_backward(first, last, last + 1);
*first = std::move(val);
}
else
detail::unguarded_linear_insert(last, std::move(val), pred, proj);
}
template<typename I, typename C, typename P>
inline constexpr void insertion_sort(I first, I last, C & pred, P & proj)
{
if(first == last)
return;
for(I i = next(first); i != last; ++i)
detail::linear_insert(first, i, pred, proj);
}
template<typename I, typename C, typename P>
inline constexpr void unguarded_insertion_sort(I first, I last, C & pred, P & proj)
{
for(I i = first; i != last; ++i)
detail::unguarded_linear_insert(i, iter_move(i), pred, proj);
}
constexpr int introsort_threshold()
{
return 16;
}
template<typename I, typename C, typename P>
inline constexpr void final_insertion_sort(I first, I last, C & pred, P & proj)
{
if(last - first > detail::introsort_threshold())
{
detail::insertion_sort(
first, first + detail::introsort_threshold(), pred, proj);
detail::unguarded_insertion_sort(
first + detail::introsort_threshold(), last, pred, proj);
}
else
detail::insertion_sort(first, last, pred, proj);
}
template<typename Size>
inline constexpr Size log2(Size n)
{
Size k = 0;
for(; n != 1; n >>= 1)
++k;
return k;
}
template<typename I, typename Size, typename C, typename P>
inline constexpr void introsort_loop(I first, I last, Size depth_limit, C & pred, P & proj)
{
while(last - first > detail::introsort_threshold())
{
if(depth_limit == 0)
return partial_sort(
first, last, last, std::ref(pred), std::ref(proj)),
void();
I cut = detail::unguarded_partition(first, last, pred, proj);
detail::introsort_loop(cut, last, --depth_limit, pred, proj);
last = cut;
}
}
} // namespace detail
/// \endcond
/// \addtogroup group-algorithms
/// @{
// Introsort: Quicksort to a certain depth, then Heapsort. Insertion
// sort below a certain threshold.
// TODO Forward iterators, like EoP?
RANGES_FUNC_BEGIN(sort)
/// \brief function template \c sort
template(typename I, typename S, typename C = less, typename P = identity)(
requires sortable<I, C, P> AND random_access_iterator<I> AND
sentinel_for<S, I>)
constexpr I RANGES_FUNC(sort)(I first, S end_, C pred = C{}, P proj = P{})
{
I last = ranges::next(first, std::move(end_));
if(first != last)
{
detail::introsort_loop(
first, last, detail::log2(last - first) * 2, pred, proj);
detail::final_insertion_sort(first, last, pred, proj);
}
return last;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires sortable<iterator_t<Rng>, C, P> AND random_access_range<Rng>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(sort)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(sort)
namespace cpp20
{
using ranges::sort;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,331 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
//===-------------------------- algorithm ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef RANGES_V3_ALGORITHM_STABLE_PARTITION_HPP
#define RANGES_V3_ALGORITHM_STABLE_PARTITION_HPP
#include <functional>
#include <memory>
#include <type_traits>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/move.hpp>
#include <range/v3/algorithm/partition_copy.hpp>
#include <range/v3/algorithm/rotate.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/move_iterators.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/memory.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/utility/swap.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I, typename C, typename P, typename D, typename Pair>
I stable_partition_impl(I first, I last, C pred, P proj, D len, Pair const p,
std::forward_iterator_tag fi)
{
// *first is known to be false
// len >= 1
if(len == 1)
return first;
if(len == 2)
{
I tmp = first;
if(invoke(pred, invoke(proj, *++tmp)))
{
ranges::iter_swap(first, tmp);
return tmp;
}
return first;
}
if(len <= p.second)
{ // The buffer is big enough to use
// Move the falses into the temporary buffer, and the trues to the front
// of the line Update first to always point to the last of the trues
auto tmpbuf = make_raw_buffer(p.first);
auto buf = tmpbuf.begin();
*buf = iter_move(first);
++buf;
auto res = partition_copy(make_move_iterator(next(first)),
make_move_sentinel(last),
first,
buf,
std::ref(pred),
std::ref(proj));
// All trues now at start of range, all falses in buffer
// Move falses back into range, but don't mess up first which points to
// first false
ranges::move(p.first, res.out2.base().base(), res.out1);
// h destructs moved-from values out of the temp buffer, but doesn't
// deallocate buffer
return res.out1;
}
// Else not enough buffer, do in place
// len >= 3
D half = len / 2; // half >= 2
I middle = next(first, half);
// recurse on [first, middle), *first know to be false
// F?????????????????
// f m l
I begin_false =
detail::stable_partition_impl(first, middle, pred, proj, half, p, fi);
// TTTFFFFF??????????
// f ff m l
// recurse on [middle, last], except increase middle until *(middle) is false,
// *last know to be true
I m1 = middle;
D len_half = len - half;
while(invoke(pred, invoke(proj, *m1)))
{
if(++m1 == last)
return ranges::rotate(begin_false, middle, last).begin();
--len_half;
}
// TTTFFFFFTTTF??????
// f ff m m1 l
I end_false =
detail::stable_partition_impl(m1, last, pred, proj, len_half, p, fi);
// TTTFFFFFTTTTTFFFFF
// f ff m sf l
return ranges::rotate(begin_false, middle, end_false).begin();
// TTTTTTTTFFFFFFFFFF
// |
}
template<typename I, typename S, typename C, typename P>
I stable_partition_impl(I first, S last, C pred, P proj,
std::forward_iterator_tag fi)
{
using difference_type = iter_difference_t<I>;
difference_type const alloc_limit = 3; // might want to make this a function
// of trivial assignment.
// Either prove all true and return first or point to first false
while(true)
{
if(first == last)
return first;
if(!invoke(pred, invoke(proj, *first)))
break;
++first;
}
// We now have a reduced range [first, last)
// *first is known to be false
using value_type = iter_value_t<I>;
auto len_end = enumerate(first, last);
auto p = len_end.first >= alloc_limit
? detail::get_temporary_buffer<value_type>(len_end.first)
: detail::value_init{};
std::unique_ptr<value_type, detail::return_temporary_buffer> const h{p.first};
return detail::stable_partition_impl(
first, len_end.second, pred, proj, len_end.first, p, fi);
}
template<typename I, typename C, typename P, typename D, typename Pair>
I stable_partition_impl(I first, I last, C pred, P proj, D len, Pair p,
std::bidirectional_iterator_tag bi)
{
// *first is known to be false
// *last is known to be true
// len >= 2
if(len == 2)
{
ranges::iter_swap(first, last);
return last;
}
if(len == 3)
{
I tmp = first;
if(invoke(pred, invoke(proj, *++tmp)))
{
ranges::iter_swap(first, tmp);
ranges::iter_swap(tmp, last);
return last;
}
ranges::iter_swap(tmp, last);
ranges::iter_swap(first, tmp);
return tmp;
}
if(len <= p.second)
{ // The buffer is big enough to use
// Move the falses into the temporary buffer, and the trues to the front
// of the line Update first to always point to the last of the trues
auto tmpbuf = ranges::make_raw_buffer(p.first);
auto buf = tmpbuf.begin();
*buf = iter_move(first);
++buf;
auto res = partition_copy(make_move_iterator(next(first)),
make_move_sentinel(last),
first,
buf,
std::ref(pred),
std::ref(proj));
first = res.out1;
// move *last, known to be true
*first = iter_move(res.in);
++first;
// All trues now at start of range, all falses in buffer
// Move falses back into range, but don't mess up first which points to
// first false
ranges::move(p.first, res.out2.base().base(), first);
// h destructs moved-from values out of the temp buffer, but doesn't
// deallocate buffer
return first;
}
// Else not enough buffer, do in place
// len >= 4
I middle = first;
D half = len / 2; // half >= 2
advance(middle, half);
// recurse on [first, middle-1], except reduce middle-1 until *(middle-1) is
// true, *first know to be false F????????????????T f m l
I m1 = middle;
I begin_false = first;
D len_half = half;
while(!invoke(pred, invoke(proj, *--m1)))
{
if(m1 == first)
goto first_half_done;
--len_half;
}
// F???TFFF?????????T
// f m1 m l
begin_false =
detail::stable_partition_impl(first, m1, pred, proj, len_half, p, bi);
first_half_done:
// TTTFFFFF?????????T
// f ff m l
// recurse on [middle, last], except increase middle until *(middle) is false,
// *last know to be true
m1 = middle;
len_half = len - half;
while(invoke(pred, invoke(proj, *m1)))
{
if(++m1 == last)
return ranges::rotate(begin_false, middle, ++last).begin();
--len_half;
}
// TTTFFFFFTTTF?????T
// f ff m m1 l
I end_false =
detail::stable_partition_impl(m1, last, pred, proj, len_half, p, bi);
// TTTFFFFFTTTTTFFFFF
// f ff m sf l
return ranges::rotate(begin_false, middle, end_false).begin();
// TTTTTTTTFFFFFFFFFF
// |
}
template<typename I, typename S, typename C, typename P>
I stable_partition_impl(I first, S end_, C pred, P proj,
std::bidirectional_iterator_tag bi)
{
using difference_type = iter_difference_t<I>;
using value_type = iter_value_t<I>;
difference_type const alloc_limit =
4; // might want to make this a function of trivial assignment
// Either prove all true and return first or point to first false
while(true)
{
if(first == end_)
return first;
if(!invoke(pred, invoke(proj, *first)))
break;
++first;
}
// first points to first false, everything prior to first is already set.
// Either prove [first, last) is all false and return first, or point last to
// last true
I last = ranges::next(first, end_);
do
{
if(first == --last)
return first;
} while(!invoke(pred, invoke(proj, *last)));
// We now have a reduced range [first, last]
// *first is known to be false
// *last is known to be true
// len >= 2
auto len = distance(first, last) + 1;
auto p = len >= alloc_limit ? detail::get_temporary_buffer<value_type>(len)
: detail::value_init{};
std::unique_ptr<value_type, detail::return_temporary_buffer> const h{p.first};
return detail::stable_partition_impl(first, last, pred, proj, len, p, bi);
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(stable_partition)
/// \brief function template \c stable_partition
template(typename I, typename S, typename C, typename P = identity)(
requires bidirectional_iterator<I> AND sentinel_for<S, I> AND
indirect_unary_predicate<C, projected<I, P>> AND permutable<I>)
I RANGES_FUNC(stable_partition)(I first, S last, C pred, P proj = P{})
{
return detail::stable_partition_impl(std::move(first),
std::move(last),
std::ref(pred),
std::ref(proj),
iterator_tag_of<I>());
}
// BUGBUG Can this be optimized if Rng has O1 size?
/// \overload
template(typename Rng, typename C, typename P = identity)(
requires bidirectional_range<Rng> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> AND
permutable<iterator_t<Rng>>)
borrowed_iterator_t<Rng> //
RANGES_FUNC(stable_partition)(Rng && rng, C pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(stable_partition)
namespace cpp20
{
using ranges::stable_partition;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,236 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
// Copyright (c) 1994
// Hewlett-Packard Company
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Hewlett-Packard Company makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
//
// Copyright (c) 1996
// Silicon Graphics Computer Systems, Inc.
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Silicon Graphics makes no
// representations about the suitability of this software for any
// purpose. It is provided "as is" without express or implied warranty.
//
#ifndef RANGES_V3_ALGORITHM_STABLE_SORT_HPP
#define RANGES_V3_ALGORITHM_STABLE_SORT_HPP
#include <functional>
#include <iterator>
#include <memory>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/inplace_merge.hpp>
#include <range/v3/algorithm/merge.hpp>
#include <range/v3/algorithm/min.hpp>
#include <range/v3/algorithm/sort.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/move_iterators.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/memory.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// \cond
namespace detail
{
template<typename I, typename C, typename P>
void inplace_stable_sort(I first, I last, C & pred, P & proj)
{
if(last - first < 15)
return detail::insertion_sort(first, last, pred, proj), void();
I middle = first + (last - first) / 2;
detail::inplace_stable_sort(first, middle, pred, proj);
detail::inplace_stable_sort(middle, last, pred, proj);
detail::inplace_merge_no_buffer(first,
middle,
last,
middle - first,
last - middle,
std::ref(pred),
std::ref(proj));
}
template<typename I1, typename I2, typename D, typename C, typename P>
void merge_sort_loop(I1 first, I1 last, I2 result, D step_size, C & pred,
P & proj)
{
D two_step = 2 * step_size;
while(last - first >= two_step)
{
result = merge(make_move_iterator(first),
make_move_iterator(first + step_size),
make_move_iterator(first + step_size),
make_move_iterator(first + two_step),
result,
std::ref(pred),
std::ref(proj),
std::ref(proj))
.out;
first += two_step;
}
step_size = ranges::min(D(last - first), step_size);
merge(make_move_iterator(first),
make_move_iterator(first + step_size),
make_move_iterator(first + step_size),
make_move_iterator(last),
result,
std::ref(pred),
std::ref(proj),
std::ref(proj));
}
constexpr int merge_sort_chunk_size()
{
return 7;
}
template<typename I, typename D, typename C, typename P>
void chunk_insertion_sort(I first, I last, D chunk_size, C & pred, P & proj)
{
while(last - first >= chunk_size)
{
detail::insertion_sort(first, first + chunk_size, pred, proj);
first += chunk_size;
}
detail::insertion_sort(first, last, pred, proj);
}
// buffer points to raw memory, we create objects, and then restore the buffer to
// raw memory by destroying the objects on return.
template<typename I, typename V, typename C, typename P>
void merge_sort_with_buffer(I first, I last, V * buffer, C & pred, P & proj)
{
iter_difference_t<I> len = last - first,
step_size = detail::merge_sort_chunk_size();
detail::chunk_insertion_sort(first, last, step_size, pred, proj);
if(step_size >= len)
return;
// The first call to merge_sort_loop moves into raw storage. Construct
// on-demand and keep track of how many objects we need to destroy.
V * buffer_end = buffer + static_cast<std::ptrdiff_t>(len);
auto tmpbuf = make_raw_buffer(buffer);
detail::merge_sort_loop(first, last, tmpbuf.begin(), step_size, pred, proj);
step_size *= 2;
loop:
detail::merge_sort_loop(
buffer, buffer_end, first, (std::ptrdiff_t)step_size, pred, proj);
step_size *= 2;
if(step_size >= len)
return;
detail::merge_sort_loop(first, last, buffer, step_size, pred, proj);
step_size *= 2;
goto loop;
}
// buffer points to raw memory
template<typename I, typename V, typename C, typename P>
void stable_sort_adaptive(I first, I last, V * buffer, std::ptrdiff_t buffer_size,
C & pred, P & proj)
{
iter_difference_t<I> len = (last - first + 1) / 2;
I middle = first + len;
if(len > buffer_size)
{
detail::stable_sort_adaptive(
first, middle, buffer, buffer_size, pred, proj);
detail::stable_sort_adaptive(
middle, last, buffer, buffer_size, pred, proj);
}
else
{
detail::merge_sort_with_buffer(first, middle, buffer, pred, proj);
detail::merge_sort_with_buffer(middle, last, buffer, pred, proj);
}
detail::merge_adaptive(first,
middle,
last,
middle - first,
last - middle,
buffer,
buffer_size,
std::ref(pred),
std::ref(proj));
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(stable_sort)
/// \brief function template \c stable_sort
template(typename I, typename S, typename C = less, typename P = identity)(
requires sortable<I, C, P> AND random_access_iterator<I> AND
sentinel_for<S, I>)
I RANGES_FUNC(stable_sort)(I first, S end_, C pred = C{}, P proj = P{})
{
I last = ranges::next(first, end_);
using D = iter_difference_t<I>;
using V = iter_value_t<I>;
D len = last - first;
auto buf =
len > 256 ? detail::get_temporary_buffer<V>(len) : detail::value_init{};
std::unique_ptr<V, detail::return_temporary_buffer> h{buf.first};
if(buf.first == nullptr)
detail::inplace_stable_sort(first, last, pred, proj);
else
detail::stable_sort_adaptive(
first, last, buf.first, buf.second, pred, proj);
return last;
}
/// \overload
template(typename Rng, typename C = less, typename P = identity)(
requires sortable<iterator_t<Rng>, C, P> AND random_access_range<Rng>)
borrowed_iterator_t<Rng> //
RANGES_FUNC(stable_sort)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(stable_sort)
namespace cpp20
{
using ranges::stable_sort;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,100 @@
// Range v3 library
//
// Copyright 2019 Christopher Di Bella
//
// 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
#ifndef RANGES_V3_ALGORITHM_STARTS_WITH_HPP
#define RANGES_V3_ALGORITHM_STARTS_WITH_HPP
#include <utility>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/equal.hpp>
#include <range/v3/algorithm/mismatch.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
// template<typename I1, typename I2>
// struct starts_with_result : detail::in1_in2_result<I1, I2>
// {
// bool result;
// };
RANGES_FUNC_BEGIN(starts_with)
/// \brief function template \c starts_with
template(typename I1,
typename S1,
typename I2,
typename S2,
typename Comp = equal_to,
typename Proj1 = identity,
typename Proj2 = identity)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND sentinel_for<S2, I2> AND
indirectly_comparable<I1, I2, Comp, Proj1, Proj2>)
constexpr bool RANGES_FUNC(starts_with)(I1 first1,
S1 last1,
I2 first2,
S2 last2,
Comp comp = {},
Proj1 proj1 = {},
Proj2 proj2 = {}) //
{
return mismatch(std::move(first1),
std::move(last1),
std::move(first2),
last2,
std::move(comp),
std::move(proj1),
std::move(proj2))
.in2 == last2;
}
/// \overload
template(typename R1,
typename R2,
typename Comp = equal_to,
typename Proj1 = identity,
typename Proj2 = identity)(
requires input_range<R1> AND input_range<R2> AND
indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Comp, Proj1, Proj2>)
constexpr bool RANGES_FUNC(starts_with)(
R1 && r1, R2 && r2, Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) //
{
return (*this)( //
begin(r1),
end(r1),
begin(r2),
end(r2),
std::move(comp),
std::move(proj1),
std::move(proj2));
}
RANGES_FUNC_END(starts_with)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ALGORITHM_STARTS_WITH_HPP

View File

@@ -0,0 +1,95 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_SWAP_RANGES_HPP
#define RANGES_V3_ALGORITHM_SWAP_RANGES_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I1, typename I2>
using swap_ranges_result = detail::in1_in2_result<I1, I2>;
RANGES_FUNC_BEGIN(swap_ranges)
/// \brief function template \c swap_ranges
template(typename I1, typename S1, typename I2)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND indirectly_swappable<I1, I2>)
constexpr swap_ranges_result<I1, I2> //
RANGES_FUNC(swap_ranges)(I1 begin1, S1 end1, I2 begin2) //
{
for(; begin1 != end1; ++begin1, ++begin2)
ranges::iter_swap(begin1, begin2);
return {begin1, begin2};
}
/// \overload
template(typename I1, typename S1, typename I2, typename S2)(
requires input_iterator<I1> AND sentinel_for<S1, I1> AND
input_iterator<I2> AND sentinel_for<S2, I2> AND
indirectly_swappable<I1, I2>)
constexpr swap_ranges_result<I1, I2> RANGES_FUNC(swap_ranges)(I1 begin1,
S1 end1,
I2 begin2,
S2 end2) //
{
for(; begin1 != end1 && begin2 != end2; ++begin1, ++begin2)
ranges::iter_swap(begin1, begin2);
return {begin1, begin2};
}
template(typename Rng1, typename I2_)(
requires input_range<Rng1> AND input_iterator<uncvref_t<I2_>> AND
indirectly_swappable<iterator_t<Rng1>, uncvref_t<I2_>>)
constexpr swap_ranges_result<iterator_t<Rng1>, uncvref_t<I2_>> //
RANGES_FUNC(swap_ranges)(Rng1 && rng1, I2_ && begin2) //
{
return (*this)(begin(rng1), end(rng1), (I2_ &&) begin2);
}
template(typename Rng1, typename Rng2)(
requires input_range<Rng1> AND input_range<Rng2> AND
indirectly_swappable<iterator_t<Rng1>, iterator_t<Rng2>>)
constexpr swap_ranges_result<borrowed_iterator_t<Rng1>, borrowed_iterator_t<Rng2>> //
RANGES_FUNC(swap_ranges)(Rng1 && rng1, Rng2 && rng2) //
{
return (*this)(begin(rng1), end(rng1), begin(rng2), end(rng2));
}
RANGES_FUNC_END(swap_ranges)
namespace cpp20
{
using ranges::swap_ranges;
using ranges::swap_ranges_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,52 @@
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
#ifndef RANGES_V3_ALGORITHM_TAGSPEC_HPP
#define RANGES_V3_ALGORITHM_TAGSPEC_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/utility/tagged_pair.hpp>
RANGES_DEPRECATED_HEADER(
"This file is deprecated. Please discontinue using the tag types defined here and "
"define your own.")
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \cond
RANGES_DEFINE_TAG_SPECIFIER(in)
RANGES_DEFINE_TAG_SPECIFIER(in1)
RANGES_DEFINE_TAG_SPECIFIER(in2)
RANGES_DEFINE_TAG_SPECIFIER(out)
RANGES_DEFINE_TAG_SPECIFIER(out1)
RANGES_DEFINE_TAG_SPECIFIER(out2)
RANGES_DEFINE_TAG_SPECIFIER(fun)
RANGES_DEFINE_TAG_SPECIFIER(min)
RANGES_DEFINE_TAG_SPECIFIER(max)
RANGES_DEFINE_TAG_SPECIFIER(begin)
RANGES_DEFINE_TAG_SPECIFIER(end)
RANGES_DEFINE_TAG_SPECIFIER(current)
RANGES_DEFINE_TAG_SPECIFIER(engine)
RANGES_DEFINE_TAG_SPECIFIER(range)
RANGES_DEFINE_TAG_SPECIFIER(size)
RANGES_DEFINE_TAG_SPECIFIER(first)
RANGES_DEFINE_TAG_SPECIFIER(second)
/// \endcond
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,220 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_TRANSFORM_HPP
#define RANGES_V3_ALGORITHM_TRANSFORM_HPP
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/iterator/unreachable_sentinel.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using unary_transform_result = detail::in_out_result<I, O>;
template<typename I1, typename I2, typename O>
using binary_transform_result = detail::in1_in2_out_result<I1, I2, O>;
RANGES_FUNC_BEGIN(transform)
// Single-range variant
/// \brief function template \c transform
template(typename I, typename S, typename O, typename F, typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
weakly_incrementable<O> AND copy_constructible<F> AND
indirectly_writable<O, indirect_result_t<F &, projected<I, P>>>)
constexpr unary_transform_result<I, O> //
RANGES_FUNC(transform)(I first, S last, O out, F fun, P proj = P{}) //
{
for(; first != last; ++first, ++out)
*out = invoke(fun, invoke(proj, *first));
return {first, out};
}
/// \overload
template(typename Rng, typename O, typename F, typename P = identity)(
requires input_range<Rng> AND weakly_incrementable<O> AND
copy_constructible<F> AND
indirectly_writable<O, indirect_result_t<F &, projected<iterator_t<Rng>, P>>>)
constexpr unary_transform_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(transform)(Rng && rng, O out, F fun, P proj = P{}) //
{
return (*this)(
begin(rng), end(rng), std::move(out), std::move(fun), std::move(proj));
}
// Double-range variant, 4-iterator version
/// \overload
template(typename I0,
typename S0,
typename I1,
typename S1,
typename O,
typename F,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND sentinel_for<S1, I1> AND
weakly_incrementable<O> AND copy_constructible<F> AND
indirectly_writable<
O,
indirect_result_t<F &, projected<I0, P0>, projected<I1, P1>>>)
constexpr binary_transform_result<I0, I1, O> //
RANGES_FUNC(transform)(I0 begin0,
S0 end0,
I1 begin1,
S1 end1,
O out,
F fun,
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
for(; begin0 != end0 && begin1 != end1; ++begin0, ++begin1, ++out)
*out = invoke(fun, invoke(proj0, *begin0), invoke(proj1, *begin1));
return {begin0, begin1, out};
}
/// \overload
template(typename Rng0,
typename Rng1,
typename O,
typename F,
typename P0 = identity,
typename P1 = identity)(
requires input_range<Rng0> AND input_range<Rng1> AND
weakly_incrementable<O> AND copy_constructible<F> AND
indirectly_writable<
O,
indirect_result_t<F &,
projected<iterator_t<Rng0>, P0>,
projected<iterator_t<Rng1>, P1>>>)
constexpr binary_transform_result<borrowed_iterator_t<Rng0>,
borrowed_iterator_t<Rng1>,
O> //
RANGES_FUNC(transform)(
Rng0 && rng0, Rng1 && rng1, O out, F fun, P0 proj0 = P0{}, P1 proj1 = P1{}) //
{
return (*this)(begin(rng0),
end(rng0),
begin(rng1),
end(rng1),
std::move(out),
std::move(fun),
std::move(proj0),
std::move(proj1));
}
// Double-range variant, 3-iterator version
/// \overload
template(typename I0,
typename S0,
typename I1,
typename O,
typename F,
typename P0 = identity,
typename P1 = identity)(
requires input_iterator<I0> AND sentinel_for<S0, I0> AND
input_iterator<I1> AND weakly_incrementable<O> AND
copy_constructible<F> AND
indirectly_writable<
O,
indirect_result_t<F &, projected<I0, P0>, projected<I1, P1>>>)
RANGES_DEPRECATED(
"Use the variant of ranges::transform that takes an upper bound "
"for both input ranges")
binary_transform_result<I0, I1, O> //
RANGES_FUNC(transform)(I0 begin0,
S0 end0,
I1 begin1,
O out,
F fun,
P0 proj0 = P0{},
P1 proj1 = P1{})
{
return (*this)(std::move(begin0),
std::move(end0),
std::move(begin1),
unreachable,
std::move(out),
std::move(fun),
std::move(proj0),
std::move(proj1));
}
/// \overload
template(typename Rng0,
typename I1Ref,
typename O,
typename F,
typename P0 = identity,
typename P1 = identity)(
requires input_range<Rng0> AND input_iterator<uncvref_t<I1Ref>> AND
weakly_incrementable<O> AND copy_constructible<F> AND
indirectly_writable<
O,
indirect_result_t<F &,
projected<iterator_t<Rng0>, P0>,
projected<uncvref_t<I1Ref>, P1>>>)
RANGES_DEPRECATED(
"Use the variant of ranges::transform that takes an upper bound "
"for both input ranges")
binary_transform_result<borrowed_iterator_t<Rng0>, uncvref_t<I1Ref>, O> //
RANGES_FUNC(transform)(Rng0 && rng0,
I1Ref && begin1,
O out,
F fun,
P0 proj0 = P0{},
P1 proj1 = P1{}) //
{
return (*this)(begin(rng0),
end(rng0),
static_cast<I1Ref &&>(begin1),
unreachable,
std::move(out),
std::move(fun),
std::move(proj0),
std::move(proj1));
}
RANGES_FUNC_END(transform)
namespace cpp20
{
using ranges::binary_transform_result;
using ranges::transform;
using ranges::unary_transform_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,86 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
// 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_ALGORITHM_UNIQUE_HPP
#define RANGES_V3_ALGORITHM_UNIQUE_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/adjacent_find.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(unique)
/// \brief template function \c unique
///
/// range-based version of the \c unique std algorithm
///
/// \pre `Rng` is a model of the `forward_range` concept
/// \pre `I` is a model of the `forward_iterator` concept
/// \pre `S` is a model of the `sentinel_for` concept
/// \pre `C` is a model of the `relation` concept
///
template(typename I, typename S, typename C = equal_to, typename P = identity)(
requires sortable<I, C, P> AND sentinel_for<S, I>)
constexpr I RANGES_FUNC(unique)(I first, S last, C pred = C{}, P proj = P{})
{
first = adjacent_find(std::move(first), last, ranges::ref(pred), ranges::ref(proj));
if(first != last)
{
for(I i = next(first); ++i != last;)
if(!invoke(pred, invoke(proj, *first), invoke(proj, *i)))
*++first = iter_move(i);
++first;
}
return first;
}
/// \overload
template(typename Rng, typename C = equal_to, typename P = identity)(
requires sortable<iterator_t<Rng>, C, P> AND range<Rng>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(unique)(Rng && rng, C pred = C{}, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(unique)
namespace cpp20
{
using ranges::unique;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,190 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-present
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_UNIQUE_COPY_HPP
#define RANGES_V3_ALGORITHM_UNIQUE_COPY_HPP
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/result_types.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
template<typename I, typename O>
using unique_copy_result = detail::in_out_result<I, O>;
/// \cond
namespace detail
{
template<typename I, typename S, typename O, typename C, typename P>
constexpr unique_copy_result<I, O> unique_copy_impl(I first,
S last,
O out,
C pred,
P proj,
std::input_iterator_tag,
std::false_type)
{
if(first != last)
{
// Must save a copy into a local because we will need this value
// even after we advance the input iterator.
iter_value_t<I> value =
*first; // This is guaranteed by indirectly_copyable
*out = value;
++out;
while(++first != last)
{
auto && x = *first;
if(!invoke(pred, invoke(proj, value), invoke(proj, x)))
{
value = (decltype(x) &&)x;
*out = value;
++out;
}
}
}
return {first, out};
}
template<typename I, typename S, typename O, typename C, typename P>
constexpr unique_copy_result<I, O> unique_copy_impl(I first,
S last,
O out,
C pred,
P proj,
std::forward_iterator_tag,
std::false_type)
{
if(first != last)
{
I tmp = first;
*out = *tmp;
++out;
while(++first != last)
{
auto && x = *first;
if(!invoke(pred, invoke(proj, *tmp), invoke(proj, x)))
{
*out = (decltype(x) &&)x;
++out;
tmp = first;
}
}
}
return {first, out};
}
template<typename I, typename S, typename O, typename C, typename P>
constexpr unique_copy_result<I, O> unique_copy_impl(I first,
S last,
O out,
C pred,
P proj,
std::input_iterator_tag, std::true_type)
{
if(first != last)
{
*out = *first;
while(++first != last)
{
auto && x = *first;
if(!invoke(pred, invoke(proj, *out), invoke(proj, x)))
*++out = (decltype(x) &&)x;
}
++out;
}
return {first, out};
}
} // namespace detail
/// \endcond
RANGES_FUNC_BEGIN(unique_copy)
/// \brief template function unique_copy
///
/// range-based version of the `unique_copy` std algorithm
///
/// \pre `Rng` is a model of the `input_range` concept
/// \pre `O` is a model of the `weakly_incrementable` concept
/// \pre `C` is a model of the `relation` concept
template(typename I,
typename S,
typename O,
typename C = equal_to,
typename P = identity)(
requires input_iterator<I> AND sentinel_for<S, I> AND
indirect_relation<C, projected<I, P>> AND weakly_incrementable<O> AND
indirectly_copyable<I, O> AND
(forward_iterator<I> || forward_iterator<O> ||
indirectly_copyable_storable<I, O>)) //
constexpr unique_copy_result<I, O> RANGES_FUNC(unique_copy)(
I first, S last, O out, C pred = C{}, P proj = P{}) //
{
return detail::unique_copy_impl(std::move(first),
std::move(last),
std::move(out),
std::move(pred),
std::move(proj),
iterator_tag_of<I>(),
meta::bool_<forward_iterator<O>>{});
}
/// \overload
template(typename Rng, typename O, typename C = equal_to, typename P = identity)(
requires input_range<Rng> AND
indirect_relation<C, projected<iterator_t<Rng>, P>> AND
weakly_incrementable<O> AND indirectly_copyable<iterator_t<Rng>, O> AND
(forward_iterator<iterator_t<Rng>> || forward_iterator<O> ||
indirectly_copyable_storable<iterator_t<Rng>, O>)) //
constexpr unique_copy_result<borrowed_iterator_t<Rng>, O> //
RANGES_FUNC(unique_copy)(Rng && rng, O out, C pred = C{}, P proj = P{}) //
{
return detail::unique_copy_impl(begin(rng),
end(rng),
std::move(out),
std::move(pred),
std::move(proj),
iterator_tag_of<iterator_t<Rng>>(),
meta::bool_<forward_iterator<O>>{});
}
RANGES_FUNC_END(unique_copy)
namespace cpp20
{
using ranges::unique_copy;
using ranges::unique_copy_result;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,91 @@
/// \file
// Range v3 library
//
// Copyright Andrey Diduh 2019
// Copyright Casey Carter 2019
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_UNSTABLE_REMOVE_IF_HPP
#define RANGES_V3_ALGORITHM_UNSTABLE_REMOVE_IF_HPP
#include <functional>
#include <utility>
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/find_if.hpp>
#include <range/v3/algorithm/find_if_not.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/concepts.hpp>
#include <range/v3/iterator/operations.hpp>
#include <range/v3/iterator/reverse_iterator.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/utility/move.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
/// unstable_remove have O(1) complexity for each element remove, unlike remove O(n)
/// [for worst case]. Each erased element overwritten (moved in) with last one.
/// unstable_remove_if does not preserve relative element order.
RANGES_FUNC_BEGIN(unstable_remove_if)
/// \brief function template \c unstable_remove_if
template(typename I, typename C, typename P = identity)(
requires bidirectional_iterator<I> AND permutable<I> AND
indirect_unary_predicate<C, projected<I, P>>)
constexpr I RANGES_FUNC(unstable_remove_if)(I first, I last, C pred, P proj = {})
{
while(true)
{
first = find_if(std::move(first), last, ranges::ref(pred), ranges::ref(proj));
if(first == last)
return first;
last = next(find_if_not(make_reverse_iterator(std::move(last)),
make_reverse_iterator(next(first)),
ranges::ref(pred),
ranges::ref(proj)))
.base();
if(first == last)
return first;
*first = iter_move(last);
// discussion here: https://github.com/ericniebler/range-v3/issues/988
++first;
}
}
/// \overload
template(typename Rng, typename C, typename P = identity)(
requires bidirectional_range<Rng> AND common_range<Rng> AND
permutable<iterator_t<Rng>> AND
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> //
RANGES_FUNC(unstable_remove_if)(Rng && rng, C pred, P proj = P{}) //
{
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj));
}
RANGES_FUNC_END(unstable_remove_if)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_ALGORITHM_UNSTABLE_REMOVE_IF_HPP

View File

@@ -0,0 +1,76 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014-present
// Copyright Casey Carter 2016
//
// 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
//
#ifndef RANGES_V3_ALGORITHM_UPPER_BOUND_HPP
#define RANGES_V3_ALGORITHM_UPPER_BOUND_HPP
#include <range/v3/range_fwd.hpp>
#include <range/v3/algorithm/aux_/upper_bound_n.hpp>
#include <range/v3/algorithm/partition_point.hpp>
#include <range/v3/functional/comparisons.hpp>
#include <range/v3/functional/identity.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/range/concepts.hpp>
#include <range/v3/range/dangling.hpp>
#include <range/v3/range/traits.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-algorithms
/// @{
RANGES_FUNC_BEGIN(upper_bound)
/// \brief function template \c upper_bound
template(typename I,
typename S,
typename V,
typename C = less,
typename P = identity)(
requires forward_iterator<I> AND sentinel_for<S, I> AND
indirect_strict_weak_order<C, V const *, projected<I, P>>)
constexpr I RANGES_FUNC(upper_bound)(
I first, S last, V const & val, C pred = C{}, P proj = P{}) //
{
return partition_point(std::move(first),
std::move(last),
detail::make_upper_bound_predicate(pred, val),
std::move(proj));
}
/// \overload
template(typename Rng, typename V, typename C = less, typename P = identity)(
requires forward_range<Rng> AND
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>)
constexpr borrowed_iterator_t<Rng> RANGES_FUNC(upper_bound)(
Rng && rng, V const & val, C pred = C{}, P proj = P{}) //
{
return partition_point(
rng, detail::make_upper_bound_predicate(pred, val), std::move(proj));
}
RANGES_FUNC_END(upper_bound)
namespace cpp20
{
using ranges::upper_bound;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif