55#include < algorithm>
66#include < cassert>
77#include < span>
8+ #include < stdexcept>
89#include < vector>
910
1011namespace edm {
@@ -19,6 +20,8 @@ namespace edm {
1920* It is intended for iteration over heterogeneous but logically connected data ranges without copying
2021* or merging them into a single container.
2122*
23+ * To find a span that corresponds to a global index, a binary search is used, making the access time logarithmic in the number of spans.
24+ *
2225*/
2326 template <typename T>
2427 class MultiSpan {
@@ -32,23 +35,34 @@ namespace edm {
3235 }
3336
3437 const T& operator [](const std::size_t globalIndex) const {
35- assert (globalIndex < totalSize_ && " Global index out of range" );
36-
38+ #ifndef NDEBUG
39+ if (globalIndex >= totalSize_) {
40+ throw std::out_of_range (" Global index out of range" );
41+ }
42+ #endif
3743 const auto [spanIndex, indexWithinSpan] = spanAndLocalIndex (globalIndex);
3844 return spans_[spanIndex][indexWithinSpan];
3945 }
4046
4147 std::size_t globalIndex (const std::size_t spanIndex, const std::size_t indexWithinSpan) const {
42- assert (spanIndex < spans_.size () && " spanIndex index out of range" );
43- assert (indexWithinSpan < spans_[spanIndex].size () && " indexWithinSpan out of range" );
48+ #ifndef NDEBUG
49+ if (spanIndex >= spans_.size ()) {
50+ throw std::out_of_range (" spanIndex index out of range" );
51+ }
52+ if (indexWithinSpan >= spans_[spanIndex].size ()) {
53+ throw std::out_of_range (" indexWithinSpan index out of range" );
54+ }
55+ #endif
4456
4557 return offsets_[spanIndex] + indexWithinSpan;
4658 }
4759
48- inline __attribute__ ((always_inline)) std::pair<std::size_t, std::size_t> spanAndLocalIndex(
49- const std::size_t globalIndex) const {
50- assert (globalIndex < totalSize_ && " Global index out of range" );
51-
60+ std::pair<std::size_t , std::size_t > spanAndLocalIndex (const std::size_t globalIndex) const {
61+ #ifndef NDEBUG
62+ if (globalIndex >= totalSize_) {
63+ throw std::out_of_range (" Global index out of range" );
64+ }
65+ #endif
5266 auto it = std::upper_bound (offsets_.begin (), offsets_.end (), globalIndex);
5367 std::size_t spanIndex = std::distance (offsets_.begin (), it) - 1 ;
5468 std::size_t indexWithinSpan = globalIndex - offsets_[spanIndex];
@@ -115,10 +129,7 @@ namespace edm {
115129
116130 bool operator ==(const ConstRandomAccessIterator& other) const { return currentIndex_ == other.currentIndex_ ; }
117131 bool operator !=(const ConstRandomAccessIterator& other) const { return currentIndex_ != other.currentIndex_ ; }
118- bool operator <(const ConstRandomAccessIterator& other) const { return currentIndex_ < other.currentIndex_ ; }
119- bool operator >(const ConstRandomAccessIterator& other) const { return currentIndex_ > other.currentIndex_ ; }
120- bool operator <=(const ConstRandomAccessIterator& other) const { return currentIndex_ <= other.currentIndex_ ; }
121- bool operator >=(const ConstRandomAccessIterator& other) const { return currentIndex_ >= other.currentIndex_ ; }
132+ auto operator <=>(const ConstRandomAccessIterator& other) const { return currentIndex_ <=> other.currentIndex_ ; }
122133
123134 private:
124135 const MultiSpan* ms_;
0 commit comments