Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
std::ranges::sample(3)	      C++ Standard Libary	std::ranges::sample(3)

NAME
       std::ranges::sample - std::ranges::sample

Synopsis
	  Defined in header <algorithm>
	  Call signature
	  template< std::input_iterator	I, std::sentinel_for<I>	S,

		    std::weakly_incrementable O, class Gen >
	  requires   (std::forward_iterator<I>	 ||  std::random_access_itera-
       tor<O>) &&
		    std::indirectly_copyable<I,		    O>		    &&
       (1) (since
										       C++20)
	  std::uniform_random_bit_generator<std::remove_reference_t<Gen>>

	  O sample( I first, S last, O out, std::iter_difference_t<I> n, Gen&&
       gen
	  );
	  template<  ranges::input_range R, std::weakly_incrementable O, class
       Gen
	  >

	  requires  (ranges::forward_range<R>	||   std::random_access_itera-
       tor<O>) &&     (since
		    std::indirectly_copyable<ranges::iterator_t<R>,    O>   &&
       (2) C++20)

	  std::uniform_random_bit_generator<std::remove_reference_t<Gen>>

	  O sample( R&&	r, O out, ranges::range_difference_t<R>	n,  Gen&&  gen
       );

	  1)  Selects  M  =  min(n,  last  - first) elements from the sequence
       [first, last)
	  (without replacement)	such that each possible	sample has equal prob-
       ability of
	  appearance, and writes those selected	elements into the range	begin-
       ning at out.
	  The algorithm	is stable (preserves the relative  order  of  the  se-
       lected elements)	only
	  if I models std::forward_iterator.
	  The behavior is undefined if out is in [first, last).
	  2)  Same  as	(1),  but  uses	 r  as	the  source range, as if using
       ranges::begin(r)	as
	  first, and ranges::end(r) as last.

	  The function-like entities described on  this	 page  are  niebloids,
       that is:

	    *  Explicit	template argument lists	cannot be specified when call-
       ing any of them.
	    * None of them are visible to argument-dependent lookup.
	    * When any of them are found by normal unqualified lookup  as  the
       name to the left
	      of  the function-call operator, argument-dependent lookup	is in-
       hibited.

	  In practice, they may	be implemented as function  objects,  or  with
       special compiler
	  extensions.

Parameters
	  first1, last1	- the range from which to make the sampling (the popu-
       lation)
	  r		- the range from which to make the sampling (the popu-
       lation)
	  out		- the output iterator where the	samples	are written
	  n		- number of samples to take
	  gen		 -  the	 random	number generator used as the source of
       randomness

Return value
	  An iterator equal to out + M,	that is	the end	of the resulting  sam-
       ple range.

Complexity
	  Linear: (last	- first).

Notes
	  This	function  may  implement  selection sampling or	reservoir sam-
       pling.

Possible implementation
	  struct sample_fn
	  {
	      template<std::input_iterator I, std::sentinel_for<I> S,
		       std::weakly_incrementable O, class Gen>
	      requires (std::forward_iterator<I> or
			std::random_access_iterator<O>)	&&
			std::indirectly_copyable<I, O> &&
			std::uniform_random_bit_generator<std::remove_refer-
       ence_t<Gen>>
	      O	operator()(I first, S last, O  out,  std::iter_difference_t<I>
       n, Gen&&	gen) const
	      {
		  using	diff_t = std::iter_difference_t<I>;
		  using	distrib_t = std::uniform_int_distribution<diff_t>;
		  using	param_t	= typename distrib_t::param_type;
		  distrib_t D{};

		  if constexpr (std::forward_iterator<I>)
		  {
		      //  this branch preserves	"stability" of the sample ele-
       ments
		      auto rest{ranges::distance(first,	last)};
		      for (n = ranges::min(n, rest); n != 0; ++first)
			  if (D(gen, param_t(0,	--rest)) < n)
			  {
			      *out++ = *first;
			      --n;
			  }
		      return out;
		  }
		  else
		  {
		      // O is a	random_access_iterator
		      diff_t sample_size{};
		      // copy [first, first + M) elements to  "random  access"
       output
		      for (; first != last && sample_size != n;	++first)
			  out[sample_size++] = *first;
		      //  overwrite  some of the copied	elements with randomly
       selected	ones
		      for (auto	pop_size{sample_size}; first !=	last; ++first,
       ++pop_size)
		      {
			  const	auto i{D(gen, param_t{0, pop_size})};
			  if (i	< n)
			      out[i] = *first;
		      }
		      return out + sample_size;
		  }
	      }

	      template<ranges::input_range  R,	std::weakly_incrementable   O,
       class Gen>
	      requires	(ranges::forward_range<R> or std::random_access_itera-
       tor<O>) &&
			std::indirectly_copyable<ranges::iterator_t<R>,	O> &&
			std::uniform_random_bit_generator<std::remove_refer-
       ence_t<Gen>>
	      O	operator()(R&&	r,  O  out,  ranges::range_difference_t<R>  n,
       Gen&& gen) const
	      {
		  return       (*this)(ranges::begin(r),       ranges::end(r),
       std::move(out), n,
				 std::forward<Gen>(gen));
	      }
	  };

	  inline constexpr sample_fn sample {};

Example
       // Run this code

	#include <algorithm>
	#include <iomanip>
	#include <iostream>
	#include <iterator>
	#include <random>
	#include <vector>

	void print(auto	const& rem, auto const&	v)
	{
	    std::cout << rem <<	" = [" << std::size(v) << "] { ";
	    for	(auto const& e : v)
		std::cout << e << ' ';
	    std::cout << "}\n";
	}

	int main()
	{
	    const auto in = {1,	2, 3, 4, 5, 6};
	    print("in",	in);

	    std::vector<int> out;
	    const int max = in.size() +	2;
	    auto gen = std::mt19937{std::random_device{}()};

	    for	(int n{}; n != max; ++n)
	    {
		out.clear();
		std::ranges::sample(in,	std::back_inserter(out), n, gen);
		std::cout << "n	= " << n;
		print(", out", out);
	    }
	}

Possible output:
	in = [6] { 1 2 3 4 5 6 }
	n = 0, out = [0] { }
	n = 1, out = [1] { 5 }
	n = 2, out = [2] { 4 5 }
	n = 3, out = [3] { 2 3 5 }
	n = 4, out = [4] { 2 4 5 6 }
	n = 5, out = [5] { 1 2 3 5 6 }
	n = 6, out = [6] { 1 2 3 4 5 6 }
	n = 7, out = [6] { 1 2 3 4 5 6 }

See also
	  ranges::shuffle randomly re-orders elements in a range
	  (C++20)	  (niebloid)
	  sample	  selects N random elements from a sequence
	  (C++17)	  (function template)

http://cppreference.com		  2024.06.10		std::ranges::sample(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::ranges::sample&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help