Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4b5e5a3
add ZeroTo RangeSegment
artv3 Mar 25, 2026
124338d
add python like behavior for RAJA::Range
artv3 Mar 31, 2026
801bd00
pr comments
artv3 Mar 31, 2026
6dbb367
Update include/RAJA/index/RangeSegment.hpp
artv3 Mar 31, 2026
17b5e57
include stride in common type find
artv3 Mar 31, 2026
ce732f4
Merge branch 'artv3/zeroTo' of https://github.com/LLNL/RAJA into artv…
artv3 Mar 31, 2026
3d0195a
PR comments
artv3 Mar 31, 2026
ddae21a
use _v instead of ::value
artv3 Mar 31, 2026
e243737
build fix
artv3 Mar 31, 2026
23a04d6
clean up pass
artv3 Mar 31, 2026
6a8995a
just use decay_t
artv3 Mar 31, 2026
66be94f
simplify
artv3 Mar 31, 2026
0c4666e
remove redundant decay
artv3 Mar 31, 2026
d2886c0
add strongly typed begin and end test
artv3 Mar 31, 2026
ab3c185
add mixed index support
artv3 Apr 1, 2026
ad5f132
add sphinx docs
artv3 Apr 2, 2026
1fc8ac3
Merge branch 'develop' into artv3/zeroTo
artv3 Apr 28, 2026
c7589b4
fix merge conflict
artv3 Jun 19, 2026
744cbc5
clean up pass, throw error for mixed types
artv3 Jun 19, 2026
c30299d
clean up pass
artv3 Jun 19, 2026
557dc27
Merge branch 'develop' into artv3/zeroTo
artv3 Jun 30, 2026
b7b14db
PR comments, add testing and checks
artv3 Jun 30, 2026
2f9edca
Merge branch 'artv3/zeroTo' of github.com:llnl/RAJA into artv3/zeroTo
artv3 Jun 30, 2026
0b1e0d2
Merge branch 'develop' into artv3/zeroTo
artv3 Jul 5, 2026
03b4af1
Merge branch 'develop' into artv3/zeroTo
artv3 Jul 6, 2026
5fd1ee6
Merge branch 'develop' into artv3/zeroTo
artv3 Jul 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions docs/sphinx/user_guide/feature/iteration_spaces.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,68 @@ and two types:

Thus, any iterable type that defines these methods and types appropriately
can be used as a segment with RAJA kernel execution templates.

Python-like Range Helpers
^^^^^^^^^^^^^^^^^^^^^^^^^

RAJA also provides ``RAJA::range(...)`` helpers that construct the segment
type for common half-open iteration patterns. These helpers are intended to
mirror the shape of Python's ``range`` while returning RAJA segment objects
that can be passed directly to ``RAJA::forall`` and other execution
interfaces.

The supported forms are::

RAJA::range(end) // [0, end)
RAJA::range<IndexT>(end) // [0, end) with explicit storage type
RAJA::range(begin, end) // [begin, end)
RAJA::range(begin, end, stride) // [begin, end) with stride

The return type depends on the arguments:

* ``RAJA::range(end)`` and ``RAJA::range(begin, end)`` return a
``RAJA::TypedRangeSegment``.
* ``RAJA::range(begin, end, stride)`` returns a
``RAJA::TypedRangeStrideSegment``.
* When one of the bounds is a RAJA strong index type, such as a type created
with ``RAJA_INDEX_VALUE``, that strong type is preserved for the loop
variable when possible.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When possible? Doesn't it always use the strong type if one is provided?
The only case I'm worried about is something like a strong index type with underlying type int combined with a long choosing long instead of being an error.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is a good point, I think we should error if so

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the code accordingly

* Providing an explicit template argument, such as
``RAJA::range<MyIndex>(end)``, overrides the deduced storage type.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should still be an error to, for example, explicitly ask for int but provide a strong index type as an argument, or explicitly ask for a strong index type and provide a different strong index type as an argument.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can use c++20's require to test that these cases fail?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You definitely can, you could even make concepts to make it easier most likely.


For example::

RAJA_INDEX_VALUE(CellIndex, "CellIndex");

RAJA::forall<RAJA::seq_exec>(RAJA::range(N), [=](RAJA::Index_type i) {
values[i] = i * i;
});

RAJA::forall<RAJA::seq_exec>(RAJA::range<CellIndex>(N), [=](CellIndex i) {
typed_values[*i] = *i + 10;
});

RAJA::forall<RAJA::seq_exec>(RAJA::range(2, 6), [=](int i) {
subrange_values[i] = i;
});

RAJA::forall<RAJA::seq_exec>(RAJA::range(CellIndex {1}, N, 2),
[=](CellIndex i) {
strided_values[*i] = *i;
});

Strided ranges follow the same half-open interval convention as
``RAJA::TypedRangeStrideSegment``. Positive strides move forward, and negative
strides move backward. For example, ``RAJA::range(N - 1, -1, -2)`` visits
``N - 1, N - 3, ...`` down to the first value that remains greater than
``-1``. A zero stride is invalid and causes RAJA to abort or throw, depending
on the build configuration.

The older ``RAJA::make_range`` and ``RAJA::make_strided_range`` helpers remain
available. Use ``RAJA::range(...)`` when the Python-like spelling improves
readability or when you want the one-argument ``[0, end)`` shorthand.

The complete example added in this branch is shown below:

.. literalinclude:: ../../../../examples/raja-ranges.cpp
:language: c++
4 changes: 4 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ raja_add_executable(
NAME resource-forall
SOURCES resource-forall.cpp)

raja_add_executable(
NAME raja-ranges
SOURCES raja-ranges.cpp)

raja_add_executable(
NAME dynamic-forall
SOURCES dynamic-forall.cpp)
Expand Down
113 changes: 113 additions & 0 deletions examples/raja-ranges.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Copyright (c) Lawrence Livermore National Security, LLC and other
// RAJA Project Developers. See top-level LICENSE and COPYRIGHT
// files for dates and other details. No copyright assignment is required
// to contribute to RAJA.
//
// SPDX-License-Identifier: (BSD-3-Clause)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

#include <iostream>

#include "RAJA/RAJA.hpp"

/*
* RAJA ranges example
*
* Demonstrates Python-like range helpers backed by RAJA segments:
* 1. RAJA::range(N) for [0, N)
* 2. RAJA::range<T>(N) for a TypedRangeSegment<T> over [0, N)
* 3. RAJA::range(begin, end) for [begin, end)
* 4. RAJA::range(begin, end, step) for a strided half-open interval
* 5. Mixed strong/numeric begin/end and strided ranges
*/

RAJA_INDEX_VALUE(CellIndex, "CellIndex");

int main(int RAJA_UNUSED_ARG(argc), char** RAJA_UNUSED_ARG(argv))
{
constexpr RAJA::Index_type N = 8;

int values[N] = {};
int typed_values[N] = {};
int subrange_values[N] = {};
int odd_values[N] = {};
int mixed_end_values[N] = {};
int mixed_stride_values[N] = {};

// Equivalent to Python range(N): [0, N)
RAJA::forall<RAJA::seq_exec>(RAJA::range(N), [&](RAJA::Index_type i) {
values[i] = static_cast<int>(i * i);
});

// Equivalent to Python range(N), but preserving a strong index type.
RAJA::forall<RAJA::seq_exec>(RAJA::range<CellIndex>(N), [&](CellIndex i) {
typed_values[*i] = static_cast<int>(*i + 10);
});

// Equivalent to Python range(2, 6): [2, 6)
RAJA::forall<RAJA::seq_exec>(RAJA::range(2, 6), [&](int i) {
subrange_values[i] = i;
});

// Equivalent to Python range(1, N, 2): odd indices in [1, N)
RAJA::forall<RAJA::seq_exec>(RAJA::range(1, N, 2), [&](int i) {
odd_values[i] = i;
});

// Mixed numeric/strong range: preserves CellIndex for the loop index.
RAJA::forall<RAJA::seq_exec>(RAJA::range(1, CellIndex {6}), [&](CellIndex i) {
mixed_end_values[*i] = static_cast<int>(*i * 10);
});

// Mixed strong begin with numeric end/stride for a strided range.
RAJA::forall<RAJA::seq_exec>(RAJA::range(CellIndex {1}, N, 2),
[&](CellIndex i) {
mixed_stride_values[*i] =
static_cast<int>(*i * 100);
});

std::cout << "range(N):";
for (auto i : RAJA::range(N)) {
std::cout << ' ' << values[i];
}
std::cout << '\n';

std::cout << "range<CellIndex>(N):";
for (auto i : RAJA::range<CellIndex>(N)) {
std::cout << ' ' << typed_values[*i];
}
std::cout << '\n';

std::cout << "range(2, 6):";
for (auto i : RAJA::range(2, 6)) {
std::cout << ' ' << subrange_values[i];
}
std::cout << '\n';

std::cout << "range(1, N, 2):";
for (auto i : RAJA::range(1, N, 2)) {
std::cout << ' ' << odd_values[i];
}
std::cout << '\n';

std::cout << "range(1, CellIndex{6}):";
for (auto i : RAJA::range(1, CellIndex {6})) {
std::cout << ' ' << mixed_end_values[*i];
}
std::cout << '\n';

std::cout << "range(CellIndex{1}, N, 2):";
for (auto i : RAJA::range(CellIndex {1}, N, 2)) {
std::cout << ' ' << mixed_stride_values[*i];
}
std::cout << '\n';

std::cout << "range(N - 1, -1, -2):";
for (auto i : RAJA::range(N - 1, -1, -2)) {
std::cout << ' ' << i;
}
std::cout << '\n';

return 0;
}
Loading
Loading