Skip to content

Commit 51748d9

Browse files
authored
Add Core::CollapsedVector (#78)
1 parent 11e8ad6 commit 51748d9

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

src/Core/CollapsedVector.hh

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/** Copyright 2024 RWTH Aachen University. All rights reserved.
2+
*
3+
* Licensed under the RWTH ASR License (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.hltpr.rwth-aachen.de/rwth-asr/rwth-asr-license.html
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#ifndef COLLAPSED_VECTOR_HH
17+
#define COLLAPSED_VECTOR_HH
18+
19+
#include <stdexcept>
20+
#include <vector>
21+
22+
namespace Core {
23+
24+
/*
25+
* Vector that is automatically collapsed down to one element if all entries have the same value.
26+
* From the outside it behaves like a normal vector. Whether it is collapsed or not only matters internally.
27+
*
28+
* Example:
29+
*
30+
* CollapsedVector<int> v; // Internal data of v is [] with logical size 0
31+
* v.push_back(5); // Normal push. Internal data of v is [5] with logical size 1
32+
* v.push_back(5); // v stays collapsed. Internal data of v is [5] with logical size 2
33+
* std::cout << v.size() << std::endl; // Prints "2"
34+
* std::cout << v[1] << std::endl; // Prints "5"
35+
* v.push_back(6); // v is expanded because the new value is different. Internal data of v is [5, 5, 6] with logical size 3
36+
* std::cout << v[2] << std::endl; // Prints "6"
37+
* v.clear(); // Internal data of v is [] with logical size 0.
38+
*/
39+
template<typename T>
40+
class CollapsedVector {
41+
public:
42+
inline CollapsedVector();
43+
inline CollapsedVector(size_t size, const T& value);
44+
45+
inline void push_back(const T& value);
46+
inline const T& operator[](size_t idx) const;
47+
inline const T& at(size_t idx) const;
48+
inline size_t size() const noexcept;
49+
inline void clear() noexcept;
50+
inline void reserve(size_t size);
51+
inline const T& front() const;
52+
53+
private:
54+
std::vector<T> data_;
55+
size_t logicalSize_;
56+
};
57+
58+
/*
59+
* Implementations
60+
*/
61+
62+
template<typename T>
63+
inline CollapsedVector<T>::CollapsedVector()
64+
: data_(), logicalSize_(0ul) {}
65+
66+
template<typename T>
67+
inline CollapsedVector<T>::CollapsedVector(size_t size, const T& value)
68+
: data_(1ul, value), logicalSize_(size) {}
69+
70+
template<typename T>
71+
inline void CollapsedVector<T>::push_back(const T& value) {
72+
if (data_.size() != 1ul) {
73+
// Vector is not collapsed so the value can be pushed as usual
74+
data_.push_back(value);
75+
}
76+
else if (value != data_.front()) {
77+
// `data_` contains only one element and thus might currently be collapsed.
78+
// If the new value is different to the present one, uncollapse it
79+
// and push the new value
80+
data_.reserve(logicalSize_ + 1);
81+
data_.resize(logicalSize_, data_.front()); // Note: this is a no-op if the logical size is also 1
82+
data_.push_back(value);
83+
}
84+
// Otherwise the value is the same as the present one so the vector stays collapsed
85+
// and the new value does not have to be pushed
86+
87+
++logicalSize_; // Logical size always increases
88+
}
89+
90+
template<typename T>
91+
inline const T& CollapsedVector<T>::operator[](size_t idx) const {
92+
if (data_.size() == 1ul) { // Vector may be collapsed
93+
return front();
94+
}
95+
return data_[idx];
96+
}
97+
98+
template<typename T>
99+
inline const T& CollapsedVector<T>::at(size_t idx) const {
100+
if (idx >= logicalSize_) {
101+
throw std::out_of_range("Trying to access illegal index of CollapsedVector");
102+
}
103+
return (*this)[idx];
104+
}
105+
106+
template<typename T>
107+
inline size_t CollapsedVector<T>::size() const noexcept {
108+
return logicalSize_;
109+
}
110+
111+
template<typename T>
112+
inline void CollapsedVector<T>::clear() noexcept {
113+
data_.clear();
114+
logicalSize_ = 0ul;
115+
}
116+
117+
template<typename T>
118+
inline void CollapsedVector<T>::reserve(size_t size) {
119+
data_.reserve(size);
120+
}
121+
122+
template<typename T>
123+
inline const T& CollapsedVector<T>::front() const {
124+
return data_.front();
125+
}
126+
127+
} // namespace Core
128+
129+
#endif // COLLAPSED_VECTOR_HH

0 commit comments

Comments
 (0)