stl-algorithms#
- group Algorithms
Functions
-
template<typename Range>
void fill( - Range &&output,
- value_type_of_t<Range> val
Fills the given range with the specified value.
This function fills the elements in the range [begin, end) with the specified value. The range must be a logical store-like object, meaning it supports the necessary operations for storing values. The value to be filled is specified by the
val
parameter.- Example:
// Declare a 3-dimensional logical store and fill it with the value 42. stl::logical_store<int, 3> store{{100, 200, 300}}; stl::fill(store, 42); // store's elements are now all 42
- Parameters:
output – The range to be filled.
val – The value to fill the range with.
-
template<typename Function, typename ...Inputs>
void for_each_zip(
)# Applies the given function
fn
with elements of each of the input sequencesins
as function arguments.This function launches a Legate task that applies the provided function
fn
element-wise to the pack of rangesins
.- Examples:
// Element-wise addition of two logical stores. stl::logical_store<int, 2> store1 = {{1, 2, 3, 4}, // {2, 3, 4, 5}, {3, 4, 5, 6}}; stl::logical_store<int, 2> store2 = {{3, 4, 5, 6}, // {2, 3, 4, 5}, {1, 2, 3, 4}}; // `a` and `b` refer to the elements of `store1` and `store2`. auto fn = [] LEGATE_HOST_DEVICE(int& a, int& b) { a += b; }; stl::for_each_zip(fn, store1, store2); // store1 now contains: // { // {4, 6, 8, 10}, // {4, 6, 8, 10}, // {4, 6, 8, 10} // }
// Row-wise operation on two logical stores. stl::logical_store<int, 2> store1 = {{1, 2, 3, 4}, // {2, 3, 4, 5}, {3, 4, 5, 6}}; stl::logical_store<int, 2> store2 = {{3, 4, 5, 6}, // {2, 3, 4, 5}, {1, 2, 3, 4}}; // `a` and `b` are `mdspan` objects referring to the rows of `store1` // and `store2`. auto fn = [] LEGATE_HOST_DEVICE(auto&& a, auto&& b) { for (std::ptrdiff_t i = 0; i < a.extent(0); ++i) { a(i) += b(i); } }; stl::for_each_zip(fn, stl::rows_of(store1), stl::rows_of(store2)); // store1 now contains: // { // {4, 6, 8, 10}, // {4, 6, 8, 10}, // {4, 6, 8, 10} // }
- Parameters:
fn – The function object to apply with each set of elements.
ins – The input sequences to iterate over.
- Pre:
The number of input sequences must be greater than 0.
The input sequences must satisfy the
logical_store_like
concept.The input sequences must have the same shape.
The function object
fn
must be callable with the same number of arguments as the number of input sequences.The function object
fn
must be trivially copyable.
-
template<typename Input, typename Function>
void for_each(
)# Applies the given function to each element in the input range.
This function launches a Legate task that applies the provided function
fn
to each element in the input rangeinput
.- Examples:
// Element-wise addition of two logical stores. stl::logical_store<int, 2> store = {{1, 2, 3, 4}, // {2, 3, 4, 5}, {3, 4, 5, 6}}; // `a` refers to the elements of `store`. auto fn = [] LEGATE_HOST_DEVICE(int& a) { ++a; }; stl::for_each(store, fn); // store1 now contains: // { // {2, 3, 4, 5}, // {3, 4, 5, 6} // {4, 5, 6, 7} // }
// Row-wise operation on two logical stores. stl::logical_store<int, 2> store = {{1, 2, 3, 4}, // {2, 3, 4, 5}, {3, 4, 5, 6}}; // `a` is an `mdspan` object referring to the rows of `store`. auto fn = [] LEGATE_HOST_DEVICE(auto&& a) { a(0) = 42; }; stl::for_each(stl::rows_of(store), fn); // store1 now contains: // { // {42, 2, 3, 4}, // {42, 3, 4, 5}, // {42, 4, 5, 6} // }
- Parameters:
input – The input range to iterate over.
fn – The function to apply to each element.
- Pre:
The input range
input
must satisfy thelogical_store_like
concept.The function object
fn
must be callable with the element type of theinput
range.The function object
fn
must be trivially copyable.
-
template<typename InputRange, typename Init, typename ReductionOperation>
logical_store<element_type_of_t<InputRange>, dim_of_v<Init>> reduce( - InputRange &&input,
- Init &&init,
- ReductionOperation op
Reduces the elements of the input range using the given reduction operation operation.
- Examples:
auto store = stl::create_store({5}, std::int64_t{1}); auto init = stl::create_store({}, std::int64_t{1}); // fill the store with data auto elems = stl::elements_of(store); std::iota(elems.begin(), elems.end(), std::int64_t{1}); auto result = stl::reduce(store, init, std::plus<>()); auto result_span = stl::as_mdspan(result); auto&& value = result_span(); static_assert(std::is_same_v<decltype(value), const std::int64_t&>); EXPECT_EQ(16, value);
stl::logical_store<std::int64_t, 2> store = {{0, 0, 0, 0}, // {1, 1, 1, 1}, {2, 2, 2, 2}}; // Reduce by rows { auto init = stl::create_store({4}, std::int64_t{0}); auto result = stl::reduce(stl::rows_of(store), init, stl::elementwise(std::plus<>())); auto result_span = stl::as_mdspan(result); EXPECT_EQ(result_span.rank(), 1); EXPECT_EQ(result_span.extent(0), 4); EXPECT_EQ(result_span(0), 3); EXPECT_EQ(result_span(1), 3); EXPECT_EQ(result_span(2), 3); EXPECT_EQ(result_span(3), 3); } // Reduce by columns { auto init = stl::create_store({3}, std::int64_t{0}); auto result = stl::reduce(stl::columns_of(store), init, stl::elementwise(std::plus<>())); auto result_span = stl::as_mdspan(result); EXPECT_EQ(result_span.rank(), 1); EXPECT_EQ(result_span.extent(0), 3); EXPECT_EQ(result_span(0), 0); EXPECT_EQ(result_span(1), 4); EXPECT_EQ(result_span(2), 8); }
- Parameters:
input – The input range to reduce.
init – The initial value of the reduction.
op – The reduction operation to apply to the elements of the input range.
op
can be a type that satisfies thelegate_reduction
concept or one of the standard functional objectsstd::plus
,std::minus
,std::multiplies
,std::divides
, etc.; or an elementwise operation created by passing any of the above tostl::elementwise
.
- Pre:
InputRange
must satisfy thelogical_store_like
concept.Init
must satisfy thelogical_store_like
concept.The value type of the input range must be the same as the value type of the initial value.
The dimension of the input range must be one greater than the dimension of the initial value.
- Returns:
An instance of
logical_store
with the same value type and shape asinit
.
-
template<typename InputRange, typename OutputRange, typename UnaryOperation>
void transform( - InputRange &&input,
- OutputRange &&output,
- UnaryOperation op
Applies a unary operation to each element in the input range and stores the result in the output range.
The input range and the output range may be the same.
- Example:
stl::logical_store<std::int64_t, 2> input = {{0, 1, 2, 3}, // {4, 5, 6, 7}, {8, 9, 10, 11}}; // Transform by rows auto result = stl::create_store({3, 4}, std::int64_t{0}); stl::transform(stl::rows_of(input), // stl::rows_of(result), stl::elementwise(Square())); // `result` now contains the squares of the elements: // [[0 1 4 9] // [16 25 36 49] // [64 81 100 121]]
- Parameters:
input – The input range. Must satisfy the
logical_store_like
concept.output – The output range. Must satisfy the
logical_store_like
concept.op – The unary operation to apply.
- Pre:
The input and output ranges must have the same shape.
The unary operation must be trivially relocatable.
-
template<typename InputRange1, typename InputRange2, typename OutputRange, typename BinaryOperation>
void transform( - InputRange1 &&input1,
- InputRange2 &&input2,
- OutputRange &&output,
- BinaryOperation op
Applies a binary operation to each element in two input ranges and stores the result in the output range.
The output range may be the same as one of the input ranges.
- Example:
std::size_t extents[] = {4, 5}; auto store1 = stl::create_store<std::int64_t>(extents); auto store2 = stl::create_store<std::int64_t>(extents); auto store3 = stl::create_store<std::int64_t>(extents); // Stateless extended lambdas work with both clang CUDA and nvcc auto shift = [] LEGATE_HOST_DEVICE(std::int64_t a, std::int64_t b) { // return a << b; }; stl::fill(store1, 2); stl::fill(store2, 4); stl::transform(store1, store2, store3, shift); // `store3` now contains the elements: // [[32 32 32 32 32] // [32 32 32 32 32] // [32 32 32 32 32] // [32 32 32 32 32]]
- Parameters:
input1 – The first input range. Must satisfy the
logical_store_like
concept.input2 – The second input range. Must satisfy the
logical_store_like
concept.output – The output range. Must satisfy the
logical_store_like
concept.op – The binary operation to apply.
- Pre:
The input and output ranges must all have the same shape.
The binary operation must be trivially relocatable.
-
template<typename InputRange, typename Init, typename Reduction, typename UnaryTransform>
logical_store<value_type_of_t<Init>, dim_of_v<Init>> transform_reduce( - InputRange &&input,
- Init &&init,
- Reduction &&reduction_op,
- UnaryTransform &&transform_op
Transform the elements of a store with a unary operation and reduce them using a binary operation with an initial value.
stl::transform_reduce(input, init, reduction_op, transform_op)
is semantically equivalent (with the caveat noted below) to:auto result = stl::create_store<TransformResult>( <extents-of-input> ); stl::transform(input, result, transform_op); return stl::reduce(result, init, reduction_op);
TransformResult
is the result type of the unary transform operation. The input store arguments can belegate_store
instances, or they can be views created with one of the view adaptors . If the input store is a view, theresult
store used to hold the results of the transformation step will be a view of the same shape as the input store.- Example
stl::logical_store<std::int64_t, 1> store{{5}}; // fill the store with data. The store will contain {1, 2, 3, 4, 5} auto elems = stl::elements_of(store); std::iota(elems.begin(), elems.end(), std::int64_t{1}); // a host/device lambda to square the elements auto square = [] LEGATE_HOST_DEVICE(std::int64_t x) { return x * x; }; // sum the squared elements auto result = stl::transform_reduce(store, stl::scalar<std::int64_t>(0), std::plus<>{}, square); auto result_span = stl::as_mdspan(result); auto result_value = result_span(); // index into the 0-D mdspan // result_value is 55
- Parameters:
input – The input range to transform.
init – The initial value of the reduction.
reduction_op – The reduction operation to apply to the transformed elements of the input range.
Reduction
can be a type that satisfies thelegate_reduction
concept or one of the standard functional objectsstd::plus
,std::minus
,std::multiplies
,std::divides
, etc.; or an elementwise operation created by passing any of the above tostl::elementwise
.transform_op – The unary operation to apply to the elements of the input prior to the reduction step.
- Pre:
InputRange
must satisfy thelogical_store_like
concept.Init
must satisfy thelogical_store_like
concept.The result type of the unary transform must be the same as the value type of the reduction’s initial value.
The dimension of the input range must be one greater than the dimension of the initial value.
- Returns:
An instance of
logical_store
with the same value type and shape asinit
.
-
template<typename InputRange1, typename InputRange2, typename Init, typename Reduction, typename BinaryTransform>
logical_store<element_type_of_t<Init>, dim_of_v<Init>> transform_reduce( - InputRange1 &&input1,
- InputRange2 &&input2,
- Init &&init,
- Reduction &&reduction_op,
- BinaryTransform &&transform_op
Transform the elements of two stores with a binary operation and reduce them using a binary operation with an initial value.
stl::transform_reduce(input1, input2, init, reduction_op, transform_op)
is semantically equivalent (with the caveat noted below) to:auto result = stl::create_store<TransformResult>( <extents-of-input1> ); stl::transform(input1, input2, result, transform_op); return stl::reduce(result, init, reduction_op);
TransformResult
is the result type of the binary transform operation. The input store arguments can belegate_store
instances, or they can be views created with one of the view adaptors . If the input stores are views, theresult
store used to hold the results of the transformation step will be a view of the same shape as the first input store.- Parameters:
input1 – The first input range to transform.
input2 – The second input range to transform.
init – The initial value of the reduction.
reduction_op – The reduction operation to apply to the transformed elements of the input ranges.
Reduction
can be a type that satisfies thelegate_reduction
concept or one of the standard functional objectsstd::plus
,std::minus
,std::multiplies
,std::divides
, etc.; or an elementwise operation created by passing any of the above tostl::elementwise
.transform_op – The binary operation to apply to the elements of the two input ranges prior to the reduction step.
- Pre:
InputRange1
andInputRange2 must satisfy the @c logical_store_like concept. @li
Init` must satisfy thelogical_store_like
concept.The shape of the input ranges must be the same.
The result type of the binary transform must be the same as the value type of the initial reduction value.
The dimensionality of the input ranges must be one greater than the dimension of the reduction initial value.
- Returns:
An instance of
logical_store
with the same value type and shape asinit
.
-
template<typename Range>