Created
June 20, 2020 19:31
-
-
Save bstaletic/16f1118be9668584d9081ec9c25c5deb to your computer and use it in GitHub Desktop.
New nano::ranges algorithms
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// nanorange/algorithm/clamp.hpp | |
// | |
// Copyright (c) 2020 Tristan Brindle (tcbrindle at gmail dot com) | |
// Distributed under 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) | |
#ifndef NANORANGE_ALGORITHM_CLAMP_HPP_INCLUDED | |
#define NANORANGE_ALGORITHM_CLAMP_HPP_INCLUDED | |
#include <nanorange/ranges.hpp> | |
NANO_BEGIN_NAMESPACE | |
namespace detail { | |
struct clamp_fn { | |
private: | |
template <typename T, typename Proj, typename Comp> | |
static constexpr T& | |
impl(const T& value, const T& low, const T& high, Comp comp = {}, Proj proj = {}) | |
{ | |
auto projected_value = nano::invoke(proj, value); | |
if(nano::invoke(comp, projected_value, nano::invoke(proj, low))) { | |
return low; | |
} else if(nano::invoke(comp, nano::invoke(proj, high), projected_value)) { | |
return high; | |
} else { | |
return value; | |
} | |
} | |
public: | |
template <typename T, typename Proj = identity, typename Comp = nano::less> | |
constexpr std::enable_if_t< | |
input_iterator<T> && | |
indirect_strict_weak_order<Comp, projected<const T*, Proj>>, | |
T&> | |
operator()(const T& value, const T& low, const T& high, Comp comp = {}, Proj proj = Proj{}) const | |
{ | |
return clamp_fn::impl(value, low, high, comp, proj); | |
} | |
}; | |
} // namespace detail | |
NANO_INLINE_VAR(detail::clamp_fn, clamp) | |
NANO_END_NAMESPACE | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// nanorange/algorithm/for_each.hpp | |
// | |
// Copyright (c) 2020 Tristan Brindle (tcbrindle at gmail dot com) | |
// Distributed under 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) | |
#ifndef NANORANGE_ALGORITHM_FOR_EACH_N_HPP_INCLUDED | |
#define NANORANGE_ALGORITHM_FOR_EACH_N_HPP_INCLUDED | |
#include <nanorange/ranges.hpp> | |
#include <nanorange/algorithm/for_each.hpp> | |
NANO_BEGIN_NAMESPACE | |
template <typename I, typename F> | |
using for_each_n_result = for_each_result<I, F>; | |
namespace detail { | |
struct for_each_n_fn { | |
private: | |
template <typename I, typename Proj, typename Fun> | |
static constexpr for_each_n_result<I, Fun> | |
impl(I first, iter_difference_t<I> n, Fun& fun, Proj& proj) | |
{ | |
iter_difference_t<I> steps = 0; | |
while (steps < n) { | |
nano::invoke(fun, nano::invoke(proj, *first)); | |
++first; | |
++steps; | |
} | |
return {first, std::move(fun)}; | |
} | |
public: | |
template <typename I, typename S, typename Proj = identity, typename Fun> | |
constexpr std::enable_if_t< | |
input_iterator<I> && | |
indirect_unary_invocable<Fun, projected<I, Proj>>, | |
for_each_n_result<I, Fun>> | |
operator()(I first, S last, Fun fun, Proj proj = Proj{}) const | |
{ | |
return for_each_n_fn::impl(std::move(first), std::move(last), | |
fun, proj); | |
} | |
}; | |
} // namespace detail | |
NANO_INLINE_VAR(detail::for_each_n_fn, for_each_n) | |
NANO_END_NAMESPACE | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// nanorange/algorithm/shuffle.hpp | |
// | |
// Copyright (c) 2020 Tristan Brindle (tcbrindle at gmail dot com) | |
// Distributed under 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) | |
#ifndef NANORANGE_ALGORITHM_SHUFFLE_HPP_INCLUDED | |
#define NANORANGE_ALGORITHM_SHUFFLE_HPP_INCLUDED | |
#include <nanorange/ranges.hpp> | |
#include <nanorange/random.hpp> | |
#include <nanorange/algorithm/min.hpp> | |
#include <random> | |
NANO_BEGIN_NAMESPACE | |
namespace detail { | |
struct sample_fn { | |
private: | |
template <typename I, typename S, typename O, typename Gen> | |
static O impl(I first, S last, O out, iter_difference_t<I> n, Gen&& g) | |
{ | |
using diff_t = iter_difference_t<I>; | |
using distr_t = std::uniform_int_distribution<diff_t>; | |
using param_t = typename distr_t::param_type; | |
distr_t D; | |
auto unsampled_size = nano::distance(first, last); | |
for(n = nano::min(n, unsampled_size); n != 0; ++first) { | |
if(D(g, param_t(0, --unsampled_size)) < n) { | |
*out++ = *first; | |
--n; | |
} | |
} | |
return out; | |
} | |
public: | |
template <typename I, typename S, typename O, typename Gen> | |
std::enable_if_t< | |
input_iterator<I> && | |
sentinel_for<S, I> && | |
weakly_incrementable<O> && | |
(forward_iterator<I> || random_access_iterator<O>) && | |
indirectly_copyable<I, O> && | |
uniform_random_bit_generator<std::remove_reference_t<Gen>>, | |
O> | |
operator()(I first, S last, O out, iter_difference_t<I> n, Gen&& gen) const | |
{ | |
return sample_fn::impl(std::move(first), std::move(last), | |
std::move(out), std::move(n), | |
std::forward<Gen>(gen)); | |
} | |
template <typename Rng, typename O, typename Gen> | |
std::enable_if_t< | |
input_range<Rng> && | |
weakly_incrementable<O> && | |
(forward_range<Rng> || random_access_iterator<O> ) && | |
indirectly_copyable<iterator_t<Rng>, O> && | |
uniform_random_bit_generator<std::remove_reference_t<Gen>>, | |
O> | |
operator()(Rng&& rng, O out, range_difference_t<Rng> n, Gen&& gen) const | |
{ | |
return sample_fn::impl(nano::begin(rng), nano::end(rng), | |
std::move(out), std::move(n), std::forward<Gen>(gen)); | |
} | |
}; | |
} | |
NANO_INLINE_VAR(detail::sample_fn, sample) | |
NANO_END_NAMESPACE | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, bstaletic.
For comparison, you may take a look at my suggesion for
ranges::for_each_n
.As Tristan said, pull/95, paraphrasing, there is no need in that static
impl()
.Have a look at gcc as well. : -)