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

FreeBSD Manual Pages

  
 
  

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

NAME
       std::transform_reduce - std::transform_reduce

Synopsis
	  Defined in header <numeric>
	  template< class InputIt1, class InputIt2, class T >
								       (since
       C++17)
	  T transform_reduce( InputIt1 first1, InputIt1	last1,	   (1) (const-
       expr since C++20)

			      InputIt2 first2, T init );
	  template< class ExecutionPolicy,

		    class ForwardIt1, class ForwardIt2,	class T	>
	  T  transform_reduce( ExecutionPolicy&& policy,	    (2)	(since
       C++17)
			      ForwardIt1 first1, ForwardIt1 last1,

			      ForwardIt2 first2, T init	);
	  template< class InputIt1, class InputIt2, class T,

		    class BinaryOp1, class BinaryOp2 >
	  T transform_reduce( InputIt1 first1, InputIt1	last1,	   (3)	(since
       C++17)
			      InputIt2 first2, T init,		       (const-
       expr since C++20)

			      BinaryOp1	reduce,	BinaryOp2
	  transform );
	  template< class ExecutionPolicy,

		    class ForwardIt1, class ForwardIt2,	class T,
		    class BinaryOp1, class BinaryOp2 >
	  T  transform_reduce( ExecutionPolicy&& policy,	    (4)	(since
       C++17)
			      ForwardIt1 first1, ForwardIt1 last1,
			      ForwardIt2 first2, T init,

			      BinaryOp1	reduce,	BinaryOp2
	  transform );
	  template< class InputIt, class T,

		    class BinaryOp, class UnaryOp >			(since
       C++17)
	  T transform_reduce( InputIt first, InputIt last, T init, (5) (const-
       expr since C++20)

			      BinaryOp reduce, UnaryOp transform
	  );
	  template< class ExecutionPolicy,

		    class ForwardIt, class T,
		    class BinaryOp, class UnaryOp >
	  T  transform_reduce( ExecutionPolicy&& policy,	    (6)	(since
       C++17)
			      ForwardIt	first, ForwardIt last, T
	  init,

			      BinaryOp reduce, UnaryOp transform
	  );

	  1) Equivalent	to transform_reduce(first1, last1, first2, init,
			   std::plus<>(),  std::multiplies<>()),   effectively
       parallelized
	  version of the default std::inner_product.
	  3)  Applies  transform  to  each  pair  of  elements from the	ranges
       [first1,	last1) and
	  the range of std::distance(first1,  last1)  elements	starting  from
       first2 and reduces
	  the results (possibly	permuted and aggregated	in unspecified manner)
       along with the
	  initial value	init over reduce.
	  The  result is non-deterministic if the reduce is not	associative or
       not commutative
	  (such	as floating-point addition).
	  If any of the	following values is not	convertible to T, the  program
       is ill-formed:
	    * reduce(init, init)
	    * reduce(init, transform(*first1, *first2))
	    * reduce(transform(*first1,	*first2), init)
	    * reduce(transform(*first1,	*first2), transform(*first1, *first2))
	  Given	last2 as the std::distance(first1, last1)
	  th  next  iterator  of first2, if any	of the following conditions is
       satisfied, the
	  behavior is undefined:
	    * T	is not MoveConstructible.
	    * transform	or reduce modifies any element of [first1,  last1)  or
       [first2,	last2).
	    *  transform  or  reduce  invalidates  any iterator	or subrange of
       [first1,	last1] or
	      [first2, last2].
	  5) Applies transform to each element in the range [first, last)  and
       reduces the
	  results  (possibly  permuted	and  aggregated	in unspecified manner)
       along with the
	  initial value	init over reduce.
	  The result is	non-deterministic if the reduce	is not associative  or
       not commutative
	  (such	as floating-point addition).
	  If  any of the following values is not convertible to	T, the program
       is ill-formed:
	    * reduce(init, init)
	    * reduce(init, transform(*first))
	    * reduce(transform(*first),	init)
	    * reduce(transform(*first),	transform(*first))
	  If any of the	following conditions is	satisfied, the behavior	is un-
       defined:
	    * T	is not MoveConstructible.
	    * transform	or reduce modifies any element of [first, last).
	    * transform	or reduce invalidates  any  iterator  or  subrange  of
       [first, last].
	  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)

Parameters
	  first1,  last1  -  the  range	 of  elements  to be taken as the left
       operand of transform
	  first2	- the start of range of	elements to be	taken  as  the
       right operand of
			  transform
	  first,  last	 - the range of	elements to be taken as	the operand of
       transform
	  init		- the initial value of the generalized sum
	  policy	- the execution	policy to use.	See  execution	policy
       for details.
	  reduce	 -  binary  FunctionObject that	will be	applied	in un-
       specified order to
			  the results of transform, the	results	of  other  re-
       duce and	init.
			  unary	 or binary FunctionObject that will be applied
       to each element
	  transform	- of the input range(s). The return type must  be  ac-
       ceptable	as input
			  to reduce.

Type requirements
	  -
	  InputIt1,  InputIt2, InputIt must meet the requirements of LegacyIn-
       putIterator.
	  -
	  ForwardIt1, ForwardIt2, ForwardIt must meet the requirements of
	  LegacyForwardIterator.

Return value
	  1,2) The generalized sum of  init  and  values  over	std::plus<>(),
       where values are	the
	  values transformed by	std::multiplies<>(), each value	is transformed
       from a pair of
	  elements from	the two	input ranges.
	  3,4)	The generalized	sum of init and	values over reduce, where val-
       ues are the values
	  transformed by transform, each value is transformed from a  pair  of
       elements	from the
	  two input ranges.
	  5,6)	The generalized	sum of init and	values over reduce, where val-
       ues are the values
	  transformed by transform, each value is transformed from an  element
       from the	input
	  range.

	  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(first1,  last1)  (or
       std::distance(first,
	  last)	for overloads (5,6)):

	  1,2) \(\scriptsize  O(N)\)O(N)  applications	of  std::plus<>()  and
       std::multiplies<>()
	  respectively.
	  3-6)	\(\scriptsize  O(N)\)O(N) applications of reduce and transform
       respectively.

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
	  transform is never applied to	init.

	  If first == last or first1 ==	last1, init is returned, unmodified.

Example
	  transform_reduce can be used to parallelize std::inner_product. Some
       systems may
	  need	additional  support  to	 get advantages	of parallel execution.
       E.g., on	GNU/Linux,
	  the Intel TBB	be installed and -ltbb option be provided to gcc/clang
       compiler.

       // Run this code

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

	#include <algorithm>
	#include <functional>
	#include <iostream>
	#include <iterator>
	#include <locale>
	#include <numeric>
	#include <vector>

	// to parallelize non-associate	accumulative operation,	 you'd	better
       choose
	// transform_reduce instead of reduce; e.g., a + b * b != b + a	* a
	void print_sum_squared(long const num)
	{
	    std::cout.imbue(std::locale{"en_US.UTF8"});
	    std::cout << "num =	" << num << '\n';

	    //	create	an  immutable  vector  filled  with  pattern: 1,2,3,4,
       1,2,3,4 ...
	    const std::vector<long> v{[n = num * 4] {
		std::vector<long> v;
		v.reserve(n);
		std::generate_n(std::back_inserter(v), n,
		    [i = 0]() mutable {	return 1 + i++ % 4; });
		return v;
	    }()};

	    auto squared_sum = [](auto sum, auto val) {	return	sum  +	val  *
       val; };

	    auto    sum1    =	 std::accumulate(v.cbegin(),   v.cend(),   0L,
       squared_sum);
	    std::cout << "accumulate():	" << sum1 << '\n';

	    auto   sum2	  =   std::reduce(PAR	v.cbegin(),   v.cend(),	   0L,
       squared_sum);
	    std::cout << "reduce(): " << sum2 << '\n';

	    auto  sum3	=  std::transform_reduce(PAR v.cbegin(), v.cend(), 0L,
       std::plus{},
					      [](auto val) { return val	* val;
       });
	    std::cout << "transform_reduce(): "	<< sum3	<< "\n\n";
	}

	int main()
	{
	    print_sum_squared(1);
	    print_sum_squared(1'000);
	    print_sum_squared(1'000'000);
	}

Possible output:
	num = 1
	accumulate(): 30
	reduce(): 30
	transform_reduce(): 30

	num = 1,000
	accumulate(): 30,000
	reduce(): -7,025,681,278,312,630,348
	transform_reduce(): 30,000

	num = 1,000,000
	accumulate(): 30,000,000
	reduce(): -5,314,886,882,370,003,032
	transform_reduce(): 30,000,000

	// Compile-options for parallel	execution on POSIX:
	// g++ -O2 -std=c++17 -Wall -Wextra -pedantic -DPARALLEL ./example.cpp
       -ltbb -o	tr; ./tr

See also
	  accumulate sums up or	folds a	range of elements
		     (function template)
		     applies a function	to a range of  elements,  storing  re-
       sults in	a
	  transform  destination range
		     (function template)
	  reduce     similar to	std::accumulate, except	out of order
	  (C++17)    (function template)

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

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

home | help