Skip to content

Commit afeaecd

Browse files
committed
Properly calculate the difference of offset_iterator with different bases
1 parent 5c8f780 commit afeaecd

File tree

2 files changed

+73
-13
lines changed

2 files changed

+73
-13
lines changed

libcudacxx/include/cuda/__iterator/offset_iterator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ class offset_iterator
317317
[[nodiscard]] _LIBCUDACXX_HIDE_FROM_ABI friend constexpr difference_type
318318
operator-(const offset_iterator& __lhs, const offset_iterator& __rhs)
319319
{
320-
return static_cast<difference_type>(__rhs.offset() - __lhs.offset());
320+
return (__rhs.__iter_ + __rhs.offset()) - (__lhs.__iter_ + __lhs.offset());
321321
}
322322

323323
//! @brief Returns the offset between an \c offset_iterators and default sentinel, equivalent to -offset()

libcudacxx/test/libcudacxx/cuda/iterators/offset_iterator/minus.iter.pass.cpp

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ __host__ __device__ constexpr bool test()
1919
{
2020
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
2121

22-
{
22+
{ // Iterators with same base
2323
using offset_iterator = cuda::offset_iterator<int*>;
2424
const int offset1 = 4;
2525
const int offset2 = 2;
@@ -33,7 +33,7 @@ __host__ __device__ constexpr bool test()
3333
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
3434
}
3535

36-
{
36+
{ // const iterators with same base
3737
using offset_iterator = cuda::offset_iterator<int*>;
3838
const int offset1 = 4;
3939
const int offset2 = 2;
@@ -47,30 +47,90 @@ __host__ __device__ constexpr bool test()
4747
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
4848
}
4949

50-
{
50+
{ // Iterators with different base
51+
using offset_iterator = cuda::offset_iterator<int*>;
52+
const int offset1 = 4;
53+
const int offset2 = 2;
54+
const int base_offset = 3;
55+
offset_iterator iter1(buffer + base_offset, offset1);
56+
offset_iterator iter2(buffer, offset2);
57+
assert(iter1 - iter2 == offset2 - (offset1 + base_offset));
58+
assert(iter2 - iter1 == (offset1 + base_offset) - offset2);
59+
assert(iter1.offset() == offset1);
60+
assert(iter2.offset() == offset2);
61+
62+
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
63+
}
64+
65+
{ // const iterators with different base
66+
using offset_iterator = cuda::offset_iterator<int*>;
67+
const int offset1 = 4;
68+
const int offset2 = 2;
69+
const int base_offset = 3;
70+
const offset_iterator iter1(buffer + base_offset, offset1);
71+
const offset_iterator iter2(buffer, offset2);
72+
assert(iter1 - iter2 == offset2 - (offset1 + base_offset));
73+
assert(iter2 - iter1 == (offset1 + base_offset) - offset2);
74+
assert(iter1.offset() == offset1);
75+
assert(iter2.offset() == offset2);
76+
77+
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
78+
}
79+
80+
{ // Iterators with same base and offset array
5181
using offset_iterator = cuda::offset_iterator<int*, random_access_iterator<const int*>>;
5282
const int offset1[] = {4};
5383
const int offset2[] = {2};
5484
offset_iterator iter1(buffer, random_access_iterator<const int*>{offset1});
5585
offset_iterator iter2(buffer, random_access_iterator<const int*>{offset2});
56-
assert(iter1 - iter2 == -2);
57-
assert(iter2 - iter1 == 2);
58-
assert(iter1.offset() == 4);
59-
assert(iter2.offset() == 2);
86+
assert(iter1 - iter2 == (*offset2 - *offset1));
87+
assert(iter2 - iter1 == (*offset1 - *offset2));
88+
assert(iter1.offset() == *offset1);
89+
assert(iter2.offset() == *offset2);
6090

6191
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
6292
}
6393

64-
{
94+
{ // const iterators with same base and offset array
6595
using offset_iterator = cuda::offset_iterator<int*, random_access_iterator<const int*>>;
6696
const int offset1[] = {4};
6797
const int offset2[] = {2};
6898
const offset_iterator iter1(buffer, random_access_iterator<const int*>{offset1});
6999
const offset_iterator iter2(buffer, random_access_iterator<const int*>{offset2});
70-
assert(iter1 - iter2 == -2);
71-
assert(iter2 - iter1 == 2);
72-
assert(iter1.offset() == 4);
73-
assert(iter2.offset() == 2);
100+
assert(iter1 - iter2 == (*offset2 - *offset1));
101+
assert(iter2 - iter1 == (*offset1 - *offset2));
102+
assert(iter1.offset() == *offset1);
103+
assert(iter2.offset() == *offset2);
104+
105+
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
106+
}
107+
108+
{ // Iterators with different base and offset array
109+
using offset_iterator = cuda::offset_iterator<int*, random_access_iterator<const int*>>;
110+
const int offset1[] = {4};
111+
const int offset2[] = {2};
112+
const int base_offset = 3;
113+
offset_iterator iter1(buffer + base_offset, random_access_iterator<const int*>{offset1});
114+
offset_iterator iter2(buffer, random_access_iterator<const int*>{offset2});
115+
assert(iter1 - iter2 == (*offset2 - (*offset1 + base_offset)));
116+
assert(iter2 - iter1 == (*offset1 + base_offset) - *offset2);
117+
assert(iter1.offset() == *offset1);
118+
assert(iter2.offset() == *offset2);
119+
120+
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
121+
}
122+
123+
{ // const iterators with different base and offset array
124+
using offset_iterator = cuda::offset_iterator<int*, random_access_iterator<const int*>>;
125+
const int offset1[] = {4};
126+
const int offset2[] = {2};
127+
const int base_offset = 3;
128+
const offset_iterator iter1(buffer + base_offset, random_access_iterator<const int*>{offset1});
129+
const offset_iterator iter2(buffer, random_access_iterator<const int*>{offset2});
130+
assert(iter1 - iter2 == (*offset2 - (*offset1 + base_offset)));
131+
assert(iter2 - iter1 == (*offset1 + base_offset) - *offset2);
132+
assert(iter1.offset() == *offset1);
133+
assert(iter2.offset() == *offset2);
74134

75135
static_assert(cuda::std::is_same_v<decltype(iter1 - iter2), cuda::std::iter_difference_t<int*>>);
76136
}

0 commit comments

Comments
 (0)