E.V.E
v2022.03.00

◆ transform_reduce

eve::algo::transform_reduce = function_with_traits<transform_reduce_>[default_simple_algo_traits]
inlineconstexpr

#include <eve/algo/transform_reduce.hpp>

SIMD version of std::transform_reduce for a single range.

Configurable Callable Object performing a SIMD optimized version of the transform_reduce By default, the operation will be unrolled by a factor of 4, align memory accesses and perform conversions if needed.

Due to the nature of how SIMD algorithms work, the reduce operation has to be paired with its, neutral element. For example, for add you pass {add, zero} as zero is the identity for add. Instead of zero it can be beneficial to pass eve's constants like eve::zero, eve::one because sometimes the implementation can be improved

Note
  • The interface differs from the standard because we felt this better matches our use case: do unary transformation and then accumulate that.
  • Multiple range interface is omitted for simplicity. Use eve::zip to get that effect.
  • eve::transform_reduce requires less requirement on the operations than eve::views::map. In transform_reduce we don't need the map_op to be a template, for example.
  • Compilers can auto-vectorize reductions, especially with special options. Maybe you don't need a library implementation.

Alternative Header

#include <eve/algo.hpp>

Callable Signatures

namespace eve::algo
{
template <eve::algo::relaxed_range Rng, typename MapOp, typename U>
U transform_reduce(Rng&& rng, MapOp map_op, U init); // 1
template< eve::algo::relaxed_range Rng, typename MapOp
, typename AddOp, typename Zero, typename U
>
U transform_reduce(Rng&& rng, MapOp map_op, std::pair<AddOp, Zero> add_zero, U init); // 2
}
constexpr auto transform_reduce
SIMD version of std::transform_reduce for a single range.
Definition: transform_reduce.hpp:167
  1. Applies map_op to each element in the range rng and reduces the results along with the initial value init using regular addition as the reduce operation.
  2. Applies map_op to each element in the range rng and reduces the results along with the initial value init using the add_zero reduce operation and neutral element.

Parameters

  • rng: Relaxed input range to process
  • init: Initial value. Also type of init matches the result type
  • map_op: Transformation operation
  • add_zero: Pair of reduction operation (commutative/associative) and an identity (zero) for it. Default add_zero is {eve::plus, eve::zero}.

Return value

  1. Sum of init and map_op applied on each element of rng.
  2. Generalized sum of init and map_op applied on each element of rng using add_zero.

Example

#include <eve/module/core.hpp>
#include <eve/algo.hpp>
#include <tts/tts.hpp>
#include <iostream>
#include <numeric>
#include <vector>
int main()
{
std::vector<float> v = {1.0f, 2.0f, 3.0f, 4.0f};
std::cout << " -> v = "
<< tts::as_string(v)
<< "\n";
std::cout << " -> eve::algo::transform_reduce(v, [](auto x) { return x + x }, 0.) = "
<< eve::algo::transform_reduce(v, [](auto x) { return x + x; }, 0.) << "\n";
std::cout << " -> std::transform_reduce(v.begin(), v.end(), std::plus<>{}, 0., [](auto x) { return x + x }) = "
<< std::transform_reduce(v.begin(), v.end(), 0., std::plus<>{}, [](auto x) { return x + x; }) << "\n";
std::cout << " -> eve::algo::reduce(eve::views::map(v, [](auto x) { return x + x }), 0.) = "
<< eve::algo::reduce(eve::views::map(v, [](auto x) { return x + x; }), 0.) << "\n";
std::cout << " -> eve::algo::transform_reduce(v, [](auto x) { return x + x }, std::pair{eve::mul, eve::one}, 0.) = "
<< eve::algo::transform_reduce(v, [](auto x) { return x + x; }, std::pair{eve::mul, eve::one}, 1.) << "\n";
}
constexpr auto reduce
SIMD optimized version of std::reduce.
Definition: reduce.hpp:152
constexpr callable_mul_ mul
Computes the sum of its arguments.
Definition: mul.hpp:83
constexpr callable_one_ one
Computes the constant .
Definition: one.hpp:51
struct eve::algo::views::@6 map
Given a relaxed iterator/range and an operation return relaxed iterator/range that has no store and a...