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

FreeBSD Manual Pages

  
 
  

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

NAME
       std::reduce - std::reduce

Synopsis
	  Defined in header <numeric>
	  template< class InputIt >
									      (since
       C++17)
	  typename  std::iterator_traits<InputIt>::value_type		   (1)
       (constexpr since
									      C++20)
	      reduce( InputIt first, InputIt last );
	  template< class ExecutionPolicy, class ForwardIt >

	  typename std::iterator_traits<ForwardIt>::value_type		   (2)
       (since C++17)
	      reduce( ExecutionPolicy&&	policy,

		      ForwardIt	first, ForwardIt last );
	  template<	   class	InputIt,	class	     T	     >
       (since C++17)
	  T reduce( InputIt first, InputIt last, T init	);		   (3)
       (constexpr since
									      C++20)
	  template< class ExecutionPolicy, class ForwardIt, class T >

	  T  reduce( ExecutionPolicy&& policy,				   (4)
       (since C++17)

		    ForwardIt first, ForwardIt last, T init );
	  template<   class   InputIt,	 class	  T,	class	 BinaryOp    >
       (since C++17)
	  T  reduce( InputIt first, InputIt last, T init, BinaryOp op );   (5)
       (constexpr since
									      C++20)
	  template< class ExecutionPolicy,

		    class ForwardIt, class T, class BinaryOp >
	  T reduce( ExecutionPolicy&& policy,				   (6)
       (since C++17)

		    ForwardIt first, ForwardIt last, T init, BinaryOp op
	  );

	  1) Equivalent	to reduce(first, last, typename
	  std::iterator_traits<InputIt>::value_type{}).
	  3) Equivalent	to reduce(first, last, init, std::plus<>()).
	  5) Reduces the range [first, last), possibly permuted	and aggregated
       in unspecified
	  manner, along	with the initial value init over op.
	  2,4,6) Same as (1,3,5), but executed according to policy.
	  These	overloads participate in overload resolution only if

	  std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>  is	 true.
       (until
										    C++20)
	  std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>  is
       true. (since
										    C++20)

	  Given	binary_op as the actual	binary operation:

	    * The result is non-deterministic if the binary_op is not associa-
       tive or not
	      commutative (such	as floating-point addition).
	    * If any of	the following values is	not convertible	to T, the pro-
       gram is
	      ill-formed:

	    * binary_op(init, *first)
	    * binary_op(*first,	init)
	    * binary_op(init, init)
	    * binary_op(*first,	*first)
	    * If any of	the following conditions is satisfied, the behavior is
       undefined:

	    * T	is not MoveConstructible.
	    * binary_op	modifies any element of	[first,	last).
	    * binary_op	invalidates any	iterator or subrange of	[first,	last].

Parameters
	  first, last -	the range of elements to apply the algorithm to
	  init	      -	the initial value of the generalized sum
	  policy       - the execution policy to use. See execution policy for
       details.
			binary FunctionObject that will	be applied in unspeci-
       fied order to the
	  op	      -	result of dereferencing	the input iterators,  the  re-
       sults of	other op
			and init.

Type requirements
	  -
	  InputIt must meet the	requirements of	LegacyInputIterator.
	  -
	  ForwardIt must meet the requirements of LegacyForwardIterator.

Return value
	  1-4)	The  generalized sum of	init and the elements of [first, last)
       over
	  std::plus<>().
	  5,6) The generalized sum of init and the elements of	[first,	 last)
       over op.

	  The  generalized sum of a group of elements over an binary operation
       binary_op is
	  defined as follows:

	    * If the group only	has one	element, the sum is the	value  of  the
       element.
	    * Otherwise, performs the following	operations in order:
	   1. Takes any	two elements elem1 and elem2 from the group.
	   2.  Calculates  binary_op(elem1, elem2) and puts the	result back to
       the group.
	   3. Repeats steps 1 and 2 until there	is only	 one  element  in  the
       group.

Complexity
	  Given	\(\scriptsize N\)N as std::distance(first, last):

	  1-4) \(\scriptsize O(N)\)O(N)	applications of	std::plus<>().
	  5,6) \(\scriptsize O(N)\)O(N)	applications of	op.

Exceptions
	  The overloads	with a template	parameter named	ExecutionPolicy	report
       errors as
	  follows:

	    *  If  execution  of  a  function invoked as part of the algorithm
       throws an exception
	      and ExecutionPolicy is one of the	standard policies, std::termi-
       nate is called.
	      For any other ExecutionPolicy, the behavior  is  implementation-
       defined.
	    *  If  the	algorithm  fails to allocate memory, std::bad_alloc is
       thrown.

Notes
	  std::reduce behaves like std::accumulate except the elements of  the
       range may be
	  grouped and rearranged in arbitrary order.

Example
	  side-by-side comparison between std::reduce and std::accumulate:

       // Run this code

	#if PARALLEL
	#include <execution>
	#define	SEQ std::execution::seq,
	#define	PAR std::execution::par,
	#else
	#define	SEQ
	#define	PAR
	#endif

	#include <chrono>
	#include <iomanip>
	#include <iostream>
	#include <numeric>
	#include <utility>
	#include <vector>

	int main()
	{
	    std::cout.imbue(std::locale("en_US.UTF-8"));
	    std::cout << std::fixed << std::setprecision(1);

	    auto eval =	[](auto	fun)
	    {
		const auto t1 =	std::chrono::high_resolution_clock::now();
		const auto [name, result] = fun();
		const auto t2 =	std::chrono::high_resolution_clock::now();
		const std::chrono::duration<double, std::milli>	ms = t2	- t1;
		std::cout << std::setw(28) << std::left	<< name	<< "sum: "
			  <<  result  <<  '\t'	<< "time: " << ms.count() << "
       ms\n";
	    };

	    {
		const std::vector<double> v(100'000'007, 0.1);

		eval([&v]{ return std::pair{"std::accumulate (double)",
		    std::accumulate(v.cbegin(),	v.cend(), 0.0)}; });
		eval([&v]{ return std::pair{"std::reduce (seq, double)",
		    std::reduce(SEQ v.cbegin(),	v.cend())}; });
		eval([&v]{ return std::pair{"std::reduce (par, double)",
		    std::reduce(PAR v.cbegin(),	v.cend())}; });
	    }

	    {
		const std::vector<long>	v(100'000'007, 1);

		eval([&v]{ return std::pair{"std::accumulate (long)",
		    std::accumulate(v.cbegin(),	v.cend(), 0l)};	});
		eval([&v]{ return std::pair{"std::reduce (seq, long)",
		    std::reduce(SEQ v.cbegin(),	v.cend())}; });
		eval([&v]{ return std::pair{"std::reduce (par, long)",
		    std::reduce(PAR v.cbegin(),	v.cend())}; });
	    }
	}

Possible output:
	// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3; ./a.out
	std::accumulate	(double)    sum: 10,000,000.7	time: 356.9 ms
	std::reduce (seq, double)   sum: 10,000,000.7	time: 140.1 ms
	std::reduce (par, double)   sum: 10,000,000.7	time: 140.1 ms
	std::accumulate	(long)	    sum: 100,000,007	time: 46.0 ms
	std::reduce (seq, long)	    sum: 100,000,007	time: 67.3 ms
	std::reduce (par, long)	    sum: 100,000,007	time: 63.3 ms

	// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3 -DPARALLEL; ./a.out
	std::accumulate	(double)    sum: 10,000,000.7	time: 353.4 ms
	std::reduce (seq, double)   sum: 10,000,000.7	time: 140.7 ms
	std::reduce (par, double)   sum: 10,000,000.7	time: 24.7 ms
	std::accumulate	(long)	    sum: 100,000,007	time: 42.4 ms
	std::reduce (seq, long)	    sum: 100,000,007	time: 52.0 ms
	std::reduce (par, long)	    sum: 100,000,007	time: 23.1 ms

See also
	  accumulate	    sums up or folds a range of	elements
			    (function template)
			    applies a function to a range of elements, storing
       results in a
	  transform	    destination	range
			    (function template)
	  transform_reduce  applies an invocable, then reduces out of order
	  (C++17)	    (function template)
	  ranges::fold_left left-folds a range of elements
	  (C++23)	    (niebloid)

http://cppreference.com		  2024.06.10			std::reduce(3)

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

home | help