Skip to content

Commit 6feae2f

Browse files
authored
Fix AppendVector random access iterator (#917)
1 parent 0ac8df6 commit 6feae2f

2 files changed

Lines changed: 78 additions & 53 deletions

File tree

include/append_vector.h

Lines changed: 50 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <vector>
66
#include <queue>
77
#include <cstdint>
8+
#include <iterator>
89

910
// Tilemaker collects OutputObjects in a list that
1011
// - spills to disk
@@ -32,114 +33,111 @@ namespace AppendVectorNS {
3233
using reference = T&;
3334

3435
Iterator(AppendVector<T>& appendVector, uint16_t vec, uint16_t offset):
35-
appendVector(&appendVector), vec(vec), offset(offset) {}
36+
appendVector(&appendVector), index(difference_type(vec) * APPEND_VECTOR_SIZE + offset) {}
3637

3738
Iterator():
38-
appendVector(nullptr), vec(0), offset(0) {}
39+
appendVector(nullptr), index(0) {}
3940

4041

4142
bool operator<(const Iterator& other) const {
42-
if (vec < other.vec)
43-
return true;
43+
return index < other.index;
44+
}
4445

45-
if (vec > other.vec)
46-
return false;
46+
bool operator>(const Iterator& other) const {
47+
return other < *this;
48+
}
4749

48-
return offset < other.offset;
50+
bool operator<=(const Iterator& other) const {
51+
return !(other < *this);
4952
}
5053

5154
bool operator>=(const Iterator& other) const {
5255
return !(*this < other);
5356
}
5457

55-
Iterator operator-(int delta) const {
56-
int64_t absolute = vec * APPEND_VECTOR_SIZE + offset;
57-
absolute -= delta;
58-
return Iterator(*appendVector, absolute / APPEND_VECTOR_SIZE, absolute % APPEND_VECTOR_SIZE);
58+
Iterator operator-(difference_type delta) const {
59+
Iterator result = *this;
60+
result -= delta;
61+
return result;
62+
}
63+
64+
Iterator operator+(difference_type delta) const {
65+
Iterator result = *this;
66+
result += delta;
67+
return result;
5968
}
6069

61-
Iterator operator+(int delta) const {
62-
int64_t absolute = vec * APPEND_VECTOR_SIZE + offset;
63-
absolute += delta;
64-
return Iterator(*appendVector, absolute / APPEND_VECTOR_SIZE, absolute % APPEND_VECTOR_SIZE);
70+
friend Iterator operator+(difference_type delta, const Iterator& iterator) {
71+
return iterator + delta;
6572
}
6673

6774
bool operator==(const Iterator& other) const {
68-
return appendVector == other.appendVector && vec == other.vec && offset == other.offset;
75+
return appendVector == other.appendVector && index == other.index;
6976
}
7077

7178
bool operator!=(const Iterator& other) const {
7279
return !(*this == other);
7380
}
7481

75-
std::ptrdiff_t operator-(const Iterator& other) const {
76-
int64_t absolute = vec * APPEND_VECTOR_SIZE + offset;
77-
int64_t otherAbsolute = other.vec * APPEND_VECTOR_SIZE + other.offset;
78-
79-
return absolute - otherAbsolute;
82+
difference_type operator-(const Iterator& other) const {
83+
return index - other.index;
8084
}
8185

8286
reference operator*() const {
83-
auto& vector = appendVector->vecs[vec];
84-
auto& el = vector[offset];
87+
auto& vector = appendVector->vecs[index / APPEND_VECTOR_SIZE];
88+
auto& el = vector[index % APPEND_VECTOR_SIZE];
8589
return el;
8690
}
8791

92+
reference operator[](difference_type delta) const {
93+
return *(*this + delta);
94+
}
95+
8896
pointer operator->() const {
89-
auto& vector = appendVector->vecs[vec];
90-
auto& el = vector[offset];
97+
auto& vector = appendVector->vecs[index / APPEND_VECTOR_SIZE];
98+
auto& el = vector[index % APPEND_VECTOR_SIZE];
9199
return &el;
92100
}
93101

94-
Iterator& operator+= (int delta) {
95-
int64_t absolute = vec * APPEND_VECTOR_SIZE + offset;
96-
absolute += delta;
97-
98-
vec = absolute / APPEND_VECTOR_SIZE;
99-
offset = absolute % APPEND_VECTOR_SIZE;
102+
Iterator& operator+= (difference_type delta) {
103+
index += delta;
100104
return *this;
101105
}
102106

103-
Iterator& operator-= (int delta) {
104-
int64_t absolute = vec * APPEND_VECTOR_SIZE + offset;
105-
absolute -= delta;
106-
107-
vec = absolute / APPEND_VECTOR_SIZE;
108-
offset = absolute % APPEND_VECTOR_SIZE;
107+
Iterator& operator-= (difference_type delta) {
108+
index -= delta;
109109
return *this;
110110
}
111111

112112
// Prefix increment
113113
Iterator& operator++() {
114-
offset++;
115-
if (offset == APPEND_VECTOR_SIZE) {
116-
offset = 0;
117-
vec++;
118-
}
114+
index++;
119115
return *this;
120116
}
121117

122118
// Postfix increment
123-
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
119+
Iterator operator++(int) {
120+
Iterator result = *this;
121+
++*this;
122+
return result;
123+
}
124124

125125
// Prefix decrement
126126
Iterator& operator--() {
127-
if (offset > 0) {
128-
offset--;
129-
} else {
130-
vec--;
131-
offset = APPEND_VECTOR_SIZE - 1;
132-
}
133-
127+
index--;
134128
return *this;
135129
}
136130

137131
// Postfix decrement
138-
Iterator operator--(int) { Iterator tmp = *this; --(*this); return tmp; }
132+
Iterator operator--(int) {
133+
Iterator result = *this;
134+
--*this;
135+
return result;
136+
}
139137

140138
private:
141139
mutable AppendVector<T>* appendVector;
142-
int32_t vec, offset;
140+
difference_type index;
143141
};
144142

145143
AppendVector():

test/append_vector.test.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#include <iostream>
2+
#include <iterator>
3+
#include <type_traits>
24
#include <boost/sort/sort.hpp>
35
#include "external/minunit.h"
46
#include "append_vector.h"
@@ -30,6 +32,32 @@ MU_TEST(test_append_vector) {
3032
mu_check(*(vec.end() - 2) == 9998);
3133
mu_check(*(vec.end() - 9000) == 1000);
3234
mu_check(*(vec.begin() - -1) == 1);
35+
mu_check(vec.begin()[25] == 25);
36+
mu_check(25 + vec.begin() == vec.begin() + 25);
37+
mu_check((vec.begin() + 25) - vec.begin() == 25);
38+
mu_check(vec.end() - vec.begin() == 10000);
39+
mu_check(vec.begin() < vec.end());
40+
mu_check(vec.begin() <= vec.begin());
41+
mu_check(vec.end() > vec.begin());
42+
mu_check(vec.end() >= vec.end());
43+
44+
auto postfix = vec.begin();
45+
mu_check(*(postfix++) == 0);
46+
mu_check(*postfix == 1);
47+
mu_check(*(postfix--) == 1);
48+
mu_check(*postfix == 0);
49+
50+
const int32_t chunkBoundary = 8192;
51+
auto boundary = vec.begin();
52+
boundary += chunkBoundary;
53+
mu_check(*boundary == chunkBoundary);
54+
boundary -= 1;
55+
mu_check(*boundary == chunkBoundary - 1);
56+
57+
static_assert(std::is_same<
58+
std::iterator_traits<AppendVector<int32_t>::Iterator>::iterator_category,
59+
std::random_access_iterator_tag
60+
>::value, "AppendVector iterator should advertise random access");
3361

3462
boost::sort::block_indirect_sort(
3563
vec.begin(),
@@ -95,4 +123,3 @@ int main() {
95123
MU_REPORT();
96124
return MU_EXIT_CODE;
97125
}
98-

0 commit comments

Comments
 (0)