LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
sparse_vector.h
Go to the documentation of this file.
1 
11 #ifndef LARDATAOBJ_UTILITIES_SPARSE_VECTOR_H
12 #define LARDATAOBJ_UTILITIES_SPARSE_VECTOR_H
13 
14 
15 // C/C++ standard library
16 #include <cstddef> // std::ptrdiff_t
17 #include <stdexcept> // std::out_of_range()
18 #include <vector>
19 #include <ostream>
20 #include <iterator> // std::distance()
21 #include <algorithm> // std::upper_bound(), std::max()
22 #include <numeric> // std::accumulate
23 #include <type_traits> // std::is_integral
24 
25 
27 namespace lar {
28 
29 // -----------------------------------------------------------------------------
30 // --- utility classes for sparse_vector
31 // ---
32 
41 template <typename T>
44  public:
45  typedef T value_type;
46 
49 
51  explicit const_value_box(value_type new_value): value(new_value) {}
52 
54  this_t& operator= (value_type) { return *this; }
55 
57  operator value_type() const { return value; }
59  operator const value_type& () const { return value; }
61 
62  protected:
63  value_type value;
64 }; // class const_value_box
65 
66 
69 template <typename T>
71  public std::iterator<std::random_access_iterator_tag, T>
72 {
73  typedef std::iterator<std::random_access_iterator_tag, T> base_t;
75 
76  public:
77 
78  using typename base_t::value_type;
79  using typename base_t::difference_type;
80 
83 
85  value_const_iterator(value_type new_value): value(new_value) {}
86 
88  value_const_iterator(value_type new_value, difference_type offset):
89  index(offset), value(new_value) {}
90 
92  value_type operator* () const { return value; }
93 
95  value_type operator[] (difference_type) const { return value; }
96 
98  this_t& operator++() { ++index; return *this; }
99 
101  this_t operator++(int) { this_t copy(*this); ++index; return copy; }
102 
104  this_t& operator--() { --index; return *this; }
105 
107  this_t operator--(int) { this_t copy(*this); --index; return copy; }
108 
110  this_t& operator+= (difference_type ofs) { index += ofs; return *this; }
111 
113  this_t& operator-= (difference_type ofs) { index -= ofs; return *this; }
114 
116  this_t operator+ (difference_type ofs) const
117  { return this_t(value, index + ofs); }
118 
120  this_t operator- (difference_type ofs) const
121  { return this_t(value, index - ofs); }
122 
125  difference_type operator- (const this_t& iter) const
126  { return index - iter.index; }
127 
129  bool operator== (const this_t& as) const { return index == as.index; }
131  bool operator!= (const this_t& as) const { return index != as.index; }
132 
133  bool operator< (const this_t& as) const { return index < as.index; }
134  bool operator<= (const this_t& as) const { return index <= as.index; }
135  bool operator> (const this_t& as) const { return index > as.index; }
136  bool operator>= (const this_t& as) const { return index >= as.index; }
138 
139  protected:
140  difference_type index{0};
142 }; // class value_const_iterator<>
143 
144 
150 template <typename T>
154 )
155  { return { iter.value, iter.index + ofs }; }
156 
157 /* // not ready yet...
158 template <typename T>
159 class value_iterator: public value_const_iterator<T> {
160  using base_t = value_const_iterator<T>;
161  using this_t = value_iterator<T>;
162  using const_value_box<value_type> = value_box;
163  public:
164 
165  using typename base_t::value_type;
166  using typename base_t::reference;
167 
168  value_box operator* () const { return value_box(value); }
169  value_box operator[] (difference_type) const { return value_box(value); }
170 
171 }; // class value_iterator<>
172 */
173 
174 
175 
176 //------------------------------------------------------------------------------
177 //--- lar::range_t<SIZE>
178 //---
185 template <typename SIZE>
186 class range_t {
187  public:
188  typedef SIZE size_type;
189  typedef std::ptrdiff_t difference_type;
190 
191  static_assert
192  (std::is_integral<size_type>::value, "range_t needs an integral type");
193 
194  size_type offset;
195  size_type last;
196 
198  range_t(): offset(0), last(0) {}
199 
201  range_t(size_type from, size_type to):
202  offset(from), last(std::max(from, to)) {}
203 
204 
206  void set(size_type from, size_type to)
207  { offset = from; last = std::max(from, to); }
208 
210  size_type begin_index() const { return offset; }
211 
213  size_type end_index() const { return last; }
214 
216  size_type relative_index(size_type index) const { return index - offset; }
217 
219  size_type size() const { return last - offset; }
220 
222  void resize(size_type new_size) { last = offset + new_size; }
223 
225  void move_head(difference_type shift) { offset += shift; }
226 
228  void move_tail(difference_type shift) { last += shift; }
229 
231  bool empty() const { return last <= offset; }
232 
234  bool includes(size_type index) const
235  { return (index >= offset) && (index < last); }
236 
238  bool includes(const range_t& r) const
239  { return includes(r.begin_index()) && includes(r.end_index()); }
240 
242  bool overlap(const range_t& r) const
243  { return (begin_index() < r.end_index()) && (end_index() > r.begin_index()); }
244 
246  bool separate(const range_t& r) const
247  { return (begin_index() > r.end_index()) || (end_index() < r.begin_index()); }
248 
253  bool borders(size_type index) const
254  { return (index >= offset) && (index <= last); }
255 
257  bool operator< (const range_t& than) const { return less(*this, than); }
260 
262  bool operator== (const range_t& as) const
263  { return (offset == as.offset) && (last == as.last); }
264 
266  bool is_valid() const { return last >= offset; }
267 
269  static bool less(const range_t& a, const range_t& b)
271  { return a.offset < b.offset; }
272  static bool less(const range_t& a, size_type b)
273  { return a.offset < b; }
274  static bool less(size_type a, const range_t& b)
275  { return a < b.offset; }
277 
279  typedef bool (*less_int_range)(size_type, const range_t& b);
280 }; // class range_t
281 
282 
283 
284 // -----------------------------------------------------------------------------
285 // --- lar::sparse_vector<T>
286 // ---
287 
456 template <typename T>
459  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
460  // - - - public interface
461  public:
462  // - - - types
463  typedef T value_type;
464  typedef std::vector<value_type> vector_t;
466  typedef typename vector_t::size_type size_type;
467  typedef typename vector_t::difference_type difference_type;
469  typedef typename vector_t::pointer pointer;
470  typedef typename vector_t::const_pointer const_pointer;
471 // typedef typename vector_t::reference reference;
472 // typedef typename vector_t::const_reference const_reference;
473 
474  // --- declarations only ---
475  class reference;
476  class const_reference;
477  class iterator;
478  class const_iterator;
479 
480  class datarange_t;
481  // --- ----------------- ---
482 
483  typedef std::vector<datarange_t> range_list_t;
489 
490 
491  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
492  // - - - public methods
494  sparse_vector(): nominal_size(0), ranges() {}
495 
496 
498  sparse_vector(size_type new_size): nominal_size(0), ranges()
499  { resize(new_size); }
500 
506  sparse_vector(const vector_t& from, size_type offset = 0):
507  nominal_size(0), ranges()
508  { add_range(offset, from.begin(), from.end()); }
509 
511  sparse_vector(sparse_vector const&) = default;
512 
515  : nominal_size(from.nominal_size)
516  , ranges(std::move(from.ranges))
517  { from.nominal_size = 0; }
518 
520  sparse_vector& operator=(sparse_vector const&) = default;
521 
524  {
525  ranges = std::move(from.ranges);
526  nominal_size = from.nominal_size;
527  from.nominal_size = 0;
528  return *this;
529  } // operator= (sparse_vector&&)
530 
536  sparse_vector(vector_t&& from, size_type offset = 0):
537  nominal_size(0), ranges()
538  { add_range(offset, std::move(from)); }
539 
540 
542  ~sparse_vector() = default;
543 
544 
545  // - - - STL-like interface
547  void clear() { ranges.clear(); nominal_size = 0; }
548 
549 
551  size_type size() const { return nominal_size; }
552 
554  bool empty() const { return size() == 0; }
555 
557  size_type capacity() const { return nominal_size; }
558 
560  void resize(size_type new_size);
563  void resize(size_type new_size, value_type def_value);
565 
567  iterator begin();
569  iterator end();
570  const_iterator begin() const;
571  const_iterator end() const;
572  const_iterator cbegin() const { return begin(); }
573  const_iterator cend() const { return end(); }
575 
577  value_type operator[] (size_type index) const;
578 
580  reference operator[] (size_type index);
581 
582 
583  // - - - special interface
584 
588 
589  // --- element test
596  bool is_void(size_type index) const;
597 
598 
601  bool back_is_void() const
602  { return ranges.empty() || (ranges.back().end_index() < size()); }
603 
604 
606  size_type count() const;
608 
609 
613 
623  value_type& set_at(size_type index, value_type value);
624 
626  void unset_at(size_type index);
627 
629  void push_back(value_type value) { resize(size() + 1, value); }
632 
640  void push_back(value_type value, value_type thr)
641  {
642  if (is_zero(value, thr)) resize(size() + 1);
643  else push_back(value);
644  } // push_back()
646 
647 
649 
657  template <typename ITER>
658  void assign(ITER first, ITER last) { clear(); append(first, last); }
659 
667  template <typename CONT>
668  void assign(const CONT& new_data) { clear(); append(new_data); }
669 
676  void assign(vector_t&& new_data) { clear(); append(std::move(new_data)); }
678 
680 
681 
686 
687  // --- range location
688 
690  const range_list_t& get_ranges() const { return ranges; }
691 
693  size_type n_ranges() const { return ranges.size(); }
694 
696  const datarange_t& range(size_t i) const { return ranges[i]; }
697 
699  range_const_iterator begin_range() const { return ranges.begin(); }
700 
702  range_const_iterator end_range() const { return ranges.end(); }
703 
704 
706 
713  range_const_iterator find_range_iterator(size_type index) const;
714  range_iterator find_range_iterator(size_type index);
716 
718 
725  const datarange_t& find_range(size_type index) const;
726  datarange_t& find_range(size_type index);
728 
735  void make_void_around(size_type index);
736 
738 
751  template <typename ITER>
752  const datarange_t& add_range(size_type offset, ITER first, ITER last);
753 
766  template <typename CONT>
767  const datarange_t& add_range(size_type offset, const CONT& new_data)
768  { return add_range(offset, new_data.begin(), new_data.end()); }
769 
783  const datarange_t& add_range(size_type offset, vector_t&& new_data);
785 
787 
814  template <typename ITER, typename OP>
815  const datarange_t& combine_range(
816  size_type offset, ITER first, ITER last, OP&& op,
817  value_type void_value = value_zero
818  );
819 
834  template <typename CONT, typename OP>
835  const datarange_t& combine_range(
836  size_type offset, const CONT& other, OP&& op,
837  value_type void_value = value_zero
838  )
839  {
840  return combine_range(offset, other.begin(), other.end(),
841  std::forward<OP>(op), void_value);
842  }
844 
846 
856  template <typename ITER>
857  const datarange_t& append(ITER first, ITER last)
858  { return add_range(size(), first, last); }
859 
869  template <typename CONT>
870  const datarange_t& append(const CONT& range_data)
871  { return add_range(size(), range_data); }
872 
883  const datarange_t& append(vector_t&& range_data)
884  { return add_range(size(), std::move(range_data)); }
886 
887 
889 
894  void void_range(range_iterator iRange) { ranges.erase(iRange); }
895  void void_range(size_t iRange) { ranges.erase(ranges.begin() + iRange); }
897 
899 
912  bool is_valid() const;
913 
914 
916  void make_void(iterator first, iterator last);
917 
918 
920  bool optimize() { return optimize(min_gap()); }
922  bool optimize(size_t) { return false; /* no optimization implemented yet */ }
924 
925 
927 
928  static constexpr value_type value_zero{0};
929 
931  static value_type abs(value_type v) { return (v < value_zero)? -v: v; }
932 
934  static value_type is_zero(value_type v) { return v == value_zero; }
935 
937  static value_type is_zero(value_type v, value_type thr)
938  { return abs(v - value_zero) <= thr; }
939 
941  static value_type is_equal(value_type a, value_type b)
942  { return is_zero(abs(a - b)); }
943 
945  static value_type is_equal(value_type a, value_type b, value_type thr)
946  { return is_zero(abs(a - b), thr); }
948 
950 
952  static size_t expected_vector_size(size_t size);
953 
955  static size_t min_gap();
956 
958  static bool should_merge(
959  const typename datarange_t::base_t& a,
960  const typename datarange_t::base_t& b
961  );
963 
964  // --------------------------------------------------------------------------
965  protected:
966 
967  size_type nominal_size;
968  range_list_t ranges;
969 
971 
977  range_iterator find_next_range_iter(size_type index)
978  { return find_next_range_iter(index, ranges.begin()); }
979  range_const_iterator find_next_range_iter(size_type index) const
980  { return find_next_range_iter(index, ranges.cbegin()); }
982 
983 
991  range_iterator find_next_range_iter(size_type index, range_iterator rbegin);
992  range_const_iterator find_next_range_iter
993  (size_type index, range_const_iterator rbegin) const;
995 
997 
1015  range_iterator find_extending_range_iter(size_type index)
1016  { return find_extending_range_iter(index, ranges.begin()); }
1017  range_const_iterator find_extending_range_iter(size_type index) const
1018  { return find_extending_range_iter(index, ranges.cbegin()); }
1020 
1022 
1029  range_iterator find_extending_range_iter
1030  (size_type index, range_iterator rbegin);
1031  range_const_iterator find_extending_range_iter
1032  (size_type index, range_const_iterator rbegin) const;
1034 
1036  size_type minimum_size() const
1037  { return ranges.empty()? 0: ranges.back().end_index(); }
1038 
1040  range_iterator insert_range(range_iterator iInsert, const datarange_t& data)
1042  { return data.empty()? iInsert: ranges.insert(iInsert, data); }
1043  range_iterator insert_range(range_iterator iInsert, datarange_t&& data)
1044  { return data.empty()? iInsert: ranges.insert(iInsert, std::move(data)); }
1046 
1048  range_iterator eat_range_head(range_iterator iRange, size_t index);
1049 
1051  datarange_t& merge_ranges(range_iterator iRange);
1052 
1054  size_type fix_size();
1055 
1056 }; // class sparse_vector<>
1057 
1058 
1059 } // namespace lar
1060 
1076 template <typename T>
1077 std::ostream& operator<< (std::ostream& out, const lar::sparse_vector<T>& v);
1078 
1079 
1080 
1081 // -----------------------------------------------------------------------------
1082 // --- sparse_vector::datarange_t definition
1083 // ---
1084 
1086 template <typename T>
1087 class lar::sparse_vector<T>::datarange_t: public range_t<size_type> {
1088  public:
1090 
1091  typedef typename vector_t::iterator iterator;
1093 
1095  datarange_t(): base_t(), values() {}
1096 
1098  datarange_t(const base_t& range): base_t(range), values(range.size()) {}
1099 
1101  template <typename ITER>
1102  datarange_t(size_type offset, ITER first, ITER last):
1103  base_t(offset, offset + std::distance(first, last)),
1104  values(first, last)
1105  {}
1106 
1108  datarange_t(size_type offset, vector_t&& data):
1109  base_t(offset, offset + data.size()), values(data)
1110  {}
1111 
1112 
1114  iterator get_iterator(size_type index)
1116  { return values.begin() + index - base_t::begin_index(); }
1117  const_iterator get_iterator(size_type index) const
1118  { return get_const_iterator(index); }
1119  const_iterator get_const_iterator(size_type index) const
1120  { return values.begin() + index - base_t::begin_index(); }
1122 
1124  iterator begin() { return values.begin(); }
1126  iterator end() { return values.end(); }
1127  const_iterator begin() const { return values.begin(); }
1128  const_iterator end() const { return values.end(); }
1129  const_iterator cbegin() const { return values.cbegin(); }
1130  const_iterator cend() const { return values.cend(); }
1132 
1134  void resize(size_t new_size)
1136  { values.resize(new_size); fit_size_from_data(); }
1137  void resize(size_t new_size, value_type def_value)
1138  { values.resize(new_size, def_value); fit_size_from_data(); }
1140 
1142  value_type& operator[] (size_type index)
1144  { return values[base_t::relative_index(index)]; }
1145  const value_type& operator[] (size_type index) const
1146  { return values[base_t::relative_index(index)]; }
1148 
1150  const vector_t& data() const { return values; }
1152 // vector_t& data() { return values; }
1154 
1163  template <typename ITER>
1164  datarange_t& extend(size_type index, ITER first, ITER last);
1165 
1171  void move_head(size_type to_index, value_type def_value = value_zero);
1172 
1178  void move_tail(size_type to_index, value_type def_value = value_zero)
1179  { resize(base_t::relative_index(to_index), def_value); }
1180 
1181 
1182  protected:
1184 
1185  void fit_size_from_data() { base_t::resize(values.size()); }
1186 
1187 }; // class datarange_t
1188 
1189 
1190 
1191 // -----------------------------------------------------------------------------
1192 // --- sparse_vector iterators definition
1193 // ---
1194 
1196 template <typename T>
1198  protected:
1199  const value_type* ptr;
1200  public:
1201  const_reference(const value_type* pValue = 0): ptr(pValue) {}
1203 
1204  explicit operator value_type() const { return ptr? *ptr: value_zero; }
1205  operator const value_type&() const
1206  { return ptr? *ptr: value_zero; }
1207 }; // lar::sparse_vector<T>::const_reference
1208 
1209 
1217 template <typename T>
1219  friend class iterator;
1220 
1221  // This object "disappears" when assigned to: either the assignment is not
1222  // possible, and then a segmentation fault will occur, or the return value
1223  // is an actual C++ reference to the assigned value.
1224  // The same is true when explicitly converting it to a reference.
1225  public:
1226  reference(value_type* pValue = 0): const_reference(pValue) {}
1228 
1229  reference& operator=(const reference&) = default;
1231  { return const_cast<value_type&>(*const_reference::ptr) = v; }
1232 
1233  operator const_reference() const
1234  { return const_reference(const_reference::ptr); }
1235  explicit operator value_type&()
1236  { return const_cast<value_type&>(*const_reference::ptr); }
1237 
1238  protected:
1239  explicit reference(const const_reference& from): const_reference(from) {}
1240 
1241 }; // lar::sparse_vector<T>::reference
1242 
1243 
1244 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1246 template <typename T>
1248  //
1249  // This iterator fulfils the traits of an immutable forward iterator.
1250  //
1251 
1252  protected:
1253  friend class container_t;
1254 
1258 
1259 
1260  public:
1261  // so far, only forward interface is implemented;
1262  // backward is tricky...
1263  typedef std::forward_iterator_tag iterator_category;
1264 
1266  struct special {
1267  class begin {};
1268  class end {};
1269  };
1270 
1271  // types
1274  typedef typename container_t::pointer pointer;
1276  // note that this is not out little box, it's the normal C++ constant
1277  // reference from the underlying vector
1278  typedef typename vector_t::const_reference const_reference;
1279 
1280 
1282  const_iterator(): cont(nullptr), index(0), currentRange() {}
1283 
1285  const_iterator(const container_t& c, size_type offset):
1286  cont(&c), index(std::min(offset, c.size())), currentRange()
1287  { refresh_state(); }
1288 
1290  const_iterator(const container_t& c, const typename special::begin):
1291  cont(&c), index(0), currentRange(c.get_ranges().begin())
1292  {}
1293 
1295  const_iterator(const container_t& c, const typename special::end):
1296  cont(&c), index(c.size()), currentRange(c.get_ranges().end())
1297  {}
1298 
1300  const_reference operator[] (size_type offset) const
1301  { return (*cont)[index + offset]; }
1302 
1304  const_reference operator*() const;
1305 
1307  const_iterator& operator++();
1310  { const_iterator copy(*this); const_iterator::operator++(); return copy; }
1312 
1313 
1315  const_iterator& operator+= (difference_type delta);
1317  const_iterator& operator-= (difference_type delta);
1318  const_iterator operator+ (difference_type delta) const;
1319  const_iterator operator- (difference_type delta) const;
1321 
1323  difference_type operator- (const const_iterator& iter) const;
1324 
1326  bool operator== (const const_iterator& as) const
1328  { return (cont == as.cont) && (index == as.index); }
1329  bool operator!= (const const_iterator& as) const
1330  { return (cont != as.cont) || (index != as.index); }
1331  bool operator< (const const_iterator& than) const
1332  { return (cont == than.cont) && (index < than.index); }
1333  bool operator> (const const_iterator& than) const
1334  { return (cont == than.cont) && (index > than.index); }
1335  bool operator<= (const const_iterator& than) const
1336  { return (cont == than.cont) && (index <= than.index); }
1337  bool operator>= (const const_iterator& than) const
1338  { return (cont == than.cont) && (index >= than.index); }
1340 
1342  range_const_iterator get_current_range() const { return currentRange; }
1343 
1344  protected:
1345  //
1346  // Logic of the internals:
1347  // - cont provides the list of ranges
1348  // - index is the absolute index in the container
1349  // - currentRange is a pointer to the "current" range, cached for speed
1350  //
1351  // An iterator past-the-end has the index equal to the size of the
1352  // container it points to. Operations on it are undefined, except that
1353  // going backward by one decrement goes back to the container
1354  // (if not empty) TODO currently backward iteration is not supported
1355  //
1356  // When the iterator is pointing to an element within a range,
1357  // currentRange points to that range.
1358  // When the iterator is pointing into the void of the vector, currentRange
1359  // points to the range next to that void area, or end() if there is none.
1360  // When the iterator is past-the-end, currentRange is not defined.
1361  //
1362  // Conversely, when the index is equal (or greater) to the size of the
1363  // container, the iterator is not dereferenciable, the iterator points
1364  // past-the-end of the container.
1365  // When currentRange points to a valid range and the index
1366  // is before that range, the iterator is pointing to the void.
1367  // When currentRange points to a valid range and the index
1368  // is inside that range, the iterator is pointing to an item in that
1369  // range.
1370  // When currentRange points to a valid range, the index can't point beyond
1371  // that range.
1372  // When currentRange points to the past-to-last range, the iterator is
1373  // pointing to the void (past the last range).
1374  //
1375  const container_t* cont;
1376  size_type index;
1377  ranges_const_iterator currentRange;
1378 
1380  void refresh_state();
1381 
1382 }; // class lar::sparse_vector<T>::const_iterator
1383 
1384 
1395 template <typename T>
1397  typedef typename const_iterator::container_t container_t;
1398  friend typename const_iterator::container_t;
1399 
1400  public:
1401  typedef typename const_iterator::reference reference;
1402  typedef typename const_iterator::const_reference const_reference;
1403  typedef typename const_iterator::special special;
1404 
1407 
1409  iterator(container_t& c, size_type offset = 0):
1410  const_iterator(c, offset) {}
1411 
1413  iterator(const container_t& c, const typename special::begin _):
1414  const_iterator(c, _) {}
1415 
1417  iterator(const container_t& c, const typename special::end _):
1418  const_iterator(c, _) {}
1419 
1421  reference operator[] (size_type offset) const
1422  { return (*const_iterator::cont)[const_iterator::index + offset]; }
1423 
1425  iterator& operator++() { const_iterator::operator++(); return *this; }
1429 
1433  { const_iterator::operator+=(delta); return *this; }
1434  iterator& operator-= (difference_type delta)
1435  { const_iterator::operator+=(delta); return *this; }
1437  { return const_iterator::operator+(delta); }
1439  { return const_iterator::operator-(delta); }
1441 
1442 
1444  reference operator*() const
1445  { return reference(const_iterator::operator*()); }
1446 
1447 // /// Returns the current range internal value; use it at your own risk!!
1448 // range_iterator get_current_range() const
1449 // { return const_iterator::currentRange; }
1450 
1451  protected:
1452 
1453  // also worth conversion
1455 
1456 }; // class lar::sparse_vector<T>::iterator
1457 
1458 
1459 
1460 // -----------------------------------------------------------------------------
1461 // --- implementation --------------------------------------------------------
1462 // -----------------------------------------------------------------------------
1463 namespace lar::details {
1464 
1466  template <typename BITER, typename EITER>
1468  BITER b;
1469  EITER e;
1470  public:
1471  iteratorRange(BITER const& b, EITER const& e): b(b), e(e) {}
1472  auto const& begin() const { return b; }
1473  auto const& end() const { return e; }
1474  }; // iteratorRange()
1475 
1476 } // namespace lar::details
1477 
1478 
1479 //------------------------------------------------------------------------------
1480 //--- sparse_vector implementation
1481 
1482 template <typename T>
1483 constexpr typename lar::sparse_vector<T>::value_type
1485 
1486 
1487 template <typename T>
1489  if (new_size >= size()) {
1490  nominal_size = new_size;
1491  return;
1492  }
1493 
1494  // truncating...
1495  range_iterator iLastRange = find_next_range_iter(new_size);
1496  ranges.erase(iLastRange, ranges.end());
1497  if (!ranges.empty()) {
1498  range_iterator iLastRange = ranges.end() - 1;
1499  if (new_size == iLastRange->begin_index())
1500  ranges.erase(iLastRange);
1501  else if (new_size < iLastRange->end_index())
1502  iLastRange->resize(new_size - iLastRange->begin_index());
1503  } // if we have ranges
1504 
1505  // formally resize
1506  nominal_size = new_size;
1507 } // lar::sparse_vector<T>::resize()
1508 
1509 
1510 template <typename T>
1512  if (new_size == size()) return;
1513  if (new_size > size()) {
1514 
1515  if (back_is_void()) // add a new range
1516  append(vector_t(new_size - size(), def_value));
1517  else // extend the last range
1518  ranges.back().resize(new_size - ranges.back().begin_index(), def_value);
1519 
1520  nominal_size = new_size;
1521  return;
1522  }
1523  // truncating is the same whether there is a default value or not
1524  resize(new_size);
1525 } // lar::sparse_vector<T>::resize()
1526 
1527 
1528 template <typename T>
1530  { return iterator(*this, typename iterator::special::begin()); }
1531 
1532 template <typename T>
1534  { return iterator(*this, typename iterator::special::end()); }
1535 
1536 template <typename T>
1539  { return const_iterator(*this, typename const_iterator::special::begin()); }
1540 
1541 template <typename T>
1544  { return const_iterator(*this, typename const_iterator::special::end()); }
1545 
1546 template <typename T>
1548  (size_type index) const
1549 {
1550  // first range not including the index
1551  range_const_iterator iNextRange = find_next_range_iter(index);
1552 
1553  // if not even the first range includes the index, we are in the void
1554  // (or in some negative index space, if index signedness allowed);
1555  if (iNextRange == ranges.begin()) return value_zero;
1556 
1557  // otherwise, let's take the previous range;
1558  // if it includes the index, we return its value;
1559  // or it precedes it, and our index is in the void: return zero
1560  const datarange_t& range(*--iNextRange);
1561  return (index < range.end_index())? range[index]: value_zero;
1562 } // lar::sparse_vector<T>::operator[]
1563 
1564 
1565 template <typename T>
1567  (size_type index)
1568 {
1569  // first range not including the index
1570  range_iterator iNextRange = find_next_range_iter(index);
1571 
1572  // if not even the first range includes the index, we are in the void
1573  // (or in some negative index space, if index signedness allowed);
1574  if (iNextRange == ranges.begin()) return reference();
1575 
1576  // otherwise, let's take the previous range;
1577  // if it includes the index, we return its value;
1578  // or it precedes it, and our index is in the void: return zero
1579  datarange_t& range(*--iNextRange);
1580  return (index < range.end_index())? reference(range[index]): reference();
1581 } // lar::sparse_vector<T>::operator[]
1582 
1583 
1584 template <typename T>
1586  if (ranges.empty() || (index >= size()))
1587  throw std::out_of_range("empty sparse vector");
1588  // range after the index:
1589  range_const_iterator iNextRange = find_next_range_iter(index);
1590  return ((iNextRange == ranges.begin())
1591  || ((--iNextRange)->end_index() <= index));
1592 } // lar::sparse_vector<T>::is_void()
1593 
1594 
1595 template <typename T>
1597  const
1598 {
1599  return std::accumulate(begin_range(), end_range(), size_type(0),
1600  [](size_type s, const datarange_t& rng) { return s + rng.size(); }
1601  );
1602 } // count()
1603 
1604 
1605 template <typename T>
1608 {
1609  // first range not including the index
1610  range_iterator iNextRange = find_next_range_iter(index);
1611 
1612  // if not even the first range includes the index, we are in the void
1613  // (or in some negative index space, if index signedness allowed);
1614  if (iNextRange != ranges.begin()) {
1615  // otherwise, let's take the previous range;
1616  // if it includes the index, we set the existing value;
1617  // or it precedes it, and our index is in the void, add the value as a
1618  // range
1619  datarange_t& range(*--iNextRange);
1620  if (index < range.end_index()) return range[index] = value;
1621  }
1622  // so we are in the void; add the value as a new range
1623  return const_cast<datarange_t&>(add_range(index, { value }))[index];
1624 } // lar::sparse_vector<T>::set_at()
1625 
1626 
1627 template <typename T>
1629  // first range not including the index
1630  range_iterator iNextRange = find_next_range_iter(index);
1631 
1632  // if not even the first range includes the index, we are in the void
1633  // (or in some negative index space, if index signedness allowed);
1634  if (iNextRange == ranges.begin()) return;
1635 
1636  // otherwise, let's take the previous range;
1637  // or it precedes the index, and our index is in the void
1638  datarange_t& range(*--iNextRange);
1639  if (index >= range.end_index()) return; // void already
1640 
1641  // it includes the index:
1642  // - if it's a one-element range, remove the range
1643  if (range.size() == 1) ranges.erase(iNextRange);
1644  // - if it's on a border, resize the range
1645  else if (index == range.begin_index())
1646  range.move_head(index + 1);
1647  else if (index == range.end_index() - 1)
1648  range.move_tail(index);
1649  // - if it's inside, break the range in two
1650  else if (index < range.end_index()) {
1651  // we are going to put a hole in a range;
1652  // this effectively creates two ranges;
1653  // first create the rightmost range, and add it to the list
1654  ranges.emplace(++iNextRange, index + 1,
1655  range.begin() + range.relative_index(index + 1),
1656  range.end()
1657  );
1658  // then cut the existing one
1659  range.move_tail(index);
1660  }
1661 } // lar::sparse_vector<T>::unset_at()
1662 
1663 
1664 template <typename T>
1667 {
1668  if (ranges.empty()) throw std::out_of_range("empty sparse vector");
1669  // range after the index:
1670  range_const_iterator iNextRange = find_next_range_iter(index);
1671  return ((iNextRange == ranges.begin())
1672  || (index >= (--iNextRange)->end_index()))?
1673  ranges.end(): iNextRange;
1674 } // lar::sparse_vector<T>::find_range_iterator() const
1675 
1676 
1677 template <typename T>
1680 {
1681  return ranges.begin() + (
1682  (const_cast<const this_t*>(this)->find_range_iterator(index))
1683  - ranges.begin());
1684 } // lar::sparse_vector<T>::find_range_iterator()
1685 
1686 
1687 template <typename T>
1688 const typename lar::sparse_vector<T>::datarange_t&
1690 {
1691  if (ranges.empty()) throw std::out_of_range("empty sparse vector");
1692  // range on the index:
1693  range_const_iterator iNextRange = find_range_iterator(index);
1694  if (iNextRange == ranges.end())
1695  throw std::out_of_range("index in no range of the sparse vector");
1696  return *iNextRange;
1697 } // lar::sparse_vector<T>::find_range() const
1698 
1699 template <typename T>
1700 inline typename lar::sparse_vector<T>::datarange_t&
1702 {
1703  return const_cast<datarange_t&>
1704  (const_cast<const this_t*>(this)->find_range(index));
1705 } // lar::sparse_vector<T>::find_range()
1706 
1707 
1708 template <typename T>
1710  if (ranges.empty() || (index >= size()))
1711  throw std::out_of_range("empty sparse vector");
1712  // range after the index:
1713  range_iterator iNextRange = find_next_range_iter(index);
1714  if ((iNextRange == ranges.begin())
1715  || ((--iNextRange)->end_index() <= index))
1716  {
1717  return;
1718  }
1719  ranges.erase(iNextRange);
1720 } // lar::sparse_vector<T>::make_void_around()
1721 
1722 
1723 template <typename T> template <typename ITER>
1725  (size_type offset, ITER first, ITER last)
1726 {
1727  // insert the new range before the existing range which starts after offset
1728  range_iterator iInsert = find_next_range_iter(offset);
1729 
1730  // is there a range before this, which includes the offset?
1731  if ((iInsert != ranges.begin()) && (iInsert-1)->borders(offset)) {
1732  // then we should extend it
1733  (--iInsert)->extend(offset, first, last);
1734  }
1735  else {
1736  // no range before the insertion one includes the offset of the new range;
1737  // ... we need to add it as a new range
1738  iInsert = insert_range(iInsert, { offset, first, last });
1739  }
1740  return merge_ranges(iInsert);
1741 } // lar::sparse_vector<T>::add_range<ITER>()
1742 
1743 
1744 template <typename T>
1746  (size_type offset, vector_t&& new_data)
1747 {
1748  // insert the new range before the existing range which starts after offset
1749  range_iterator iInsert = std::upper_bound(
1750  ranges.begin(), ranges.end(), offset,
1751  typename datarange_t::less_int_range(datarange_t::less)
1752  );
1753 
1754  // is there a range before this, which includes the offset?
1755  if ((iInsert != ranges.begin()) && (iInsert-1)->borders(offset)) {
1756  // then we should extend it
1757  (--iInsert)->extend(offset, new_data.begin(), new_data.end());
1758  }
1759  else {
1760  // no range before the insertion one includes the offset of the new range;
1761  // ... we need to add it as a new range;
1762  // it is not really clear to me [GP] why I need a std::move here, since
1763  // new_data is a rvalue already; in doubt, I have painted all this kind
1764  // of constructs with move()s, just in case
1765  iInsert = insert_range(iInsert, { offset, std::move(new_data) });
1766  }
1767  return merge_ranges(iInsert);
1768 } // lar::sparse_vector<T>::add_range(vector)
1769 
1770 
1771 template <typename T>
1772 template <typename ITER, typename OP>
1774  size_type offset, ITER first, ITER last, OP&& op,
1775  value_type void_value /* = value_zero */
1776  )
1777  -> const datarange_t&
1778 {
1779  /*
1780  * This is a complicate enough task, that we go brute force:
1781  * 1) combine all the input elements within the datarange where offset falls
1782  * in
1783  * 2) create a new datarange combining void with the remaining input elements
1784  * 3) if the void area is over before the input elements are, repeat steps
1785  * (1) and (2) with the updated offset
1786  * 4) at this point we'll have a train of contiguous ranges, result of
1787  * combination of the input elements alternating with existing elements
1788  * and with void cells: apply the regular merge algorithm
1789  *
1790  */
1791 
1792  auto src = first;
1793  auto const insertionPoint = offset; // saved for later
1794  auto destRange = find_extending_range_iter(offset, ranges.begin());
1795  while (src != last) {
1796 
1797  //
1798  // (1) combine all the input elements within the datarange including offset
1799  //
1800  if ((destRange != end_range()) && (offset < destRange->end_index())) {
1801  // this means `destRange` contains offset:
1802  // combine input data until this range is over (or input data is over)
1803  auto dest = destRange->get_iterator(offset);
1804 
1805  auto const end = destRange->end();
1806  while (src != last) {
1807  *dest = op(*dest, *src);
1808  ++src;
1809  ++offset;
1810  if (++dest == end) break;
1811  } // while
1812  if (src == last) break;
1813  offset = destRange->end_index();
1814  } // if
1815 
1816  //
1817  // (2) create a new datarange combining void with input elements
1818  //
1819  // at this point, offset is in the void, and we do have more input data;
1820  // we fill as much void as we can with data, creating a new range.
1821  // When to stop? at the beginning of the next range, or when data is over
1822  ++destRange;
1823  size_type const newRangeSize = (destRange == end_range())
1824  ? std::distance(src, last): (destRange->begin_index() - offset);
1825 
1826  // prepare the data (we'll plug it in directly)
1827  vector_t combinedData;
1828  combinedData.reserve(newRangeSize);
1829  size_type i = 0;
1830  while (i++ < newRangeSize) {
1831  combinedData.push_back(op(void_value, *src));
1832  if (++src == last) break; // no more data
1833  }
1834  // move the data as a new range inserted before the next range we just found
1835  // return value is the iterator to the inserted range
1836  destRange = insert_range(destRange, { offset, std::move(combinedData) });
1837 
1838  //
1839  // (3) if there is more input, repeat steps (1) and (2) with updated offset
1840  //
1841  offset = destRange->end_index();
1842  ++destRange;
1843  } // while
1844 
1845  //
1846  // (4) apply the regular merge algorithm
1847  //
1848  return merge_ranges(find_extending_range_iter(insertionPoint));
1849 
1850 } // lar::sparse_vector<T>::combine_range<ITER>()
1851 
1852 
1853 template <typename T>
1855  // iterators have in "currentRange" either the range they point into,
1856  // or the range next to the void they point to
1857 
1858  if ((first.cont != this) || (last.cont != this)) {
1859  throw std::runtime_error
1860  ("lar::sparse_vector::make_void(): iterators from alien container");
1861  }
1862  // if first is after next, no range is identified
1863  if (first >= last) return;
1864 
1866  first_range
1867  = ranges.begin() + (first.get_current_range() - ranges.begin()),
1868  last_range = ranges.begin() + (last.get_current_range() - ranges.begin());
1869 
1870  //--- "first": void up to this iterator ---
1871  // if first in the last void region, there is nothing to erase
1872  if (first_range == ranges.end()) return;
1873 
1874  // if first is in the middle of a valid range instead, we have to resize it
1875  if (first.index > first_range->begin_index()) {
1876  if (first_range == last_range) {
1877  // we are going to erase a subset of a range;
1878  // this effectively creates two ranges;
1879  // first create the rightmost (last) range, and add it to the list
1880  last_range = ranges.emplace(++last_range, last.index,
1881  first_range->begin() + first_range->relative_index(last.index),
1882  first_range->end()
1883  );
1884  // then cut the existing one
1885  first_range->move_tail(first.index);
1886  return;
1887  }
1888  first_range->move_tail(first.index);
1889  ++first_range; // from next range on, start voiding
1890  }
1891 
1892  //--- "last"
1893  // if the index is inside a range, remove up to it
1894  if ((last_range != ranges.end()) && (last.index > last_range->begin_index()))
1895  eat_range_head(last_range, last.index);
1896 
1897  // finally, remove entirely the ranges in between
1898  ranges.erase(first_range, last_range);
1899 } // lar::sparse_vector<T>::make_void()
1900 
1901 
1902 template <typename T>
1904  // a sparse vector with no non-null elements can't be detected invalid
1905  if (ranges.empty()) return true;
1906 
1907  range_const_iterator iNext = ranges.begin(), rend = ranges.end();
1908  while (iNext != rend) {
1909  range_const_iterator iRange = iNext++;
1910  if (iRange->empty()) return false;
1911  if (iNext != rend) {
1912  if (!(*iRange < *iNext)) return false;
1913  if (!iRange->separate(*iNext)) return false;
1914  }
1915  } // while
1916  if (nominal_size < ranges.back().end_index()) return false;
1917  return true;
1918 } // lar::sparse_vector<T>::is_valid()
1919 
1920 
1921 
1922 // --- private methods
1923 
1924 template <typename T>
1927  (size_type index, range_iterator rbegin)
1928 {
1929  // this range has the offset (first index) above the index argument:
1930  return std::upper_bound(
1931  rbegin, ranges.end(), index,
1932  typename datarange_t::less_int_range(datarange_t::less)
1933  );
1934 } // lar::sparse_vector<T>::find_next_range_iter()
1935 
1936 template <typename T>
1939  (size_type index, range_const_iterator rbegin) const
1940 {
1941  // this range has the offset (first index) above the index argument:
1942  return std::upper_bound(
1943  rbegin, ranges.end(), index,
1944  typename datarange_t::less_int_range(datarange_t::less)
1945  );
1946 } // lar::sparse_vector<T>::find_next_range_iter() const
1947 
1948 
1949 template <typename T>
1952  (size_type index, range_iterator rbegin)
1953 {
1954  // this range has the offset (first index) above the index argument:
1955  auto it = find_next_range_iter(index, rbegin);
1956  // if index were not void, would it belong to the previous range?
1957  // if so, the previus range is the one we want
1958  return ((it != rbegin) && std::prev(it)->borders(index))? std::prev(it): it;
1959 } // lar::sparse_vector<T>::find_extending_range_iter()
1960 
1961 
1962 template <typename T>
1965  (size_type index, range_const_iterator rbegin) const
1966 {
1967  // this range has the offset (first index) above the index argument:
1968  auto it = find_next_range_iter(index, rbegin);
1969  // if index were not void, would it belong to the previous range?
1970  // if so, the previus range is the one we want
1971  return ((it != rbegin) && std::prev(it)->borders(index))? std::prev(it): it;
1972 } // lar::sparse_vector<T>::find_extending_range_iter() const
1973 
1974 
1975 template <typename T>
1978 {
1979  range_iterator iNext = iRange + 1;
1980  while (iNext != ranges.end()) {
1981  if (!iRange->borders(iNext->begin_index())) break;
1982  // iRange content dominates, but if iNext has data beyond it,
1983  // then we copy it
1984  if (iNext->end_index() > iRange->end_index()) {
1985  iRange->extend
1986  (iRange->end_index(), iNext->get_iterator(iRange->end_index()), iNext->end());
1987  }
1988  iNext = ranges.erase(iNext);
1989  } // while
1990  fix_size();
1991  return *iRange;
1992 } // lar::sparse_vector<T>::merge_ranges()
1993 
1994 
1995 template <typename T>
1997  (range_iterator iRange, size_t index)
1998 {
1999  if (index <= iRange->begin_index()) return iRange;
2000  if (index >= iRange->end_index()) return ranges.erase(iRange);
2001  iRange->move_head(index);
2002  return iRange;
2003 } // lar::sparse_vector<T>::eat_range_head()
2004 
2005 
2006 template <typename T>
2008  if (!ranges.empty())
2009  nominal_size = std::max(nominal_size, ranges.back().end_index());
2010  return nominal_size;
2011 } // lar::sparse_vector<T>::fix_size()
2012 
2013 
2014 // --- static methods
2015 
2016 template <typename T>
2018  // apparently, a chunk of heap memory takes at least 32 bytes;
2019  // that means that a vector of 1 or 5 32-bit integers takes the same
2020  // space; the overhead appears to be 8 bytes, which can be allocated
2021  return sizeof(vector_t)
2022  + std::max(size_t(32), (alignof(datarange_t)*size + 8));
2023 } // lar::sparse_vector<T>::expected_vector_size()
2024 
2025 
2026 template <typename T>
2028  // we assume here that there is no additional overhead by alignment;
2029  // the gap adds the space of another datarange_t, including the vector,
2030  // its data and overhead from heap (apparently, 8 bytes);
2031  //
2032  return (sizeof(datarange_t) + 8) / sizeof(value_type) + 1; // round up
2033 } // lar::sparse_vector<T>::min_gap()
2034 
2035 
2036 template <typename T>
2038  const typename datarange_t::base_t& a,
2039  const typename datarange_t::base_t& b
2040  )
2041 {
2042  size_type gap_size = (a < b)?
2043  b.begin_index() - a.begin_index() - a.size():
2044  a.begin_index() - b.begin_index() - b.size();
2045  return expected_vector_size(a.size() + b.size() + gap_size)
2046  <= expected_vector_size(a.size()) + expected_vector_size(b.size());
2047 } // lar::sparse_vector<T>::should_merge()
2048 
2049 
2050 
2051 // --- non-member functions
2052 template <typename T>
2053 std::ostream& operator<< (std::ostream& out, const lar::sparse_vector<T>& v) {
2054 
2055  out << "Sparse vector of size " << v.size() << " with "
2056  << v.get_ranges().size() << " ranges:";
2058  iRange = v.begin_range(), rend = v.end_range();
2059  while (iRange != rend) {
2060  out << "\n [" << iRange->begin_index() << " - " << iRange->end_index()
2061  << "] (" << iRange->size() << "):";
2063  iValue = iRange->begin(), vend = iRange->end();
2064  while (iValue != vend) out << " " << (*(iValue++));
2065  ++iRange;
2066  } // for
2067  return out << std::endl;
2068 } // operator<< (ostream, sparse_vector<T>)
2069 
2070 
2071 
2072 // -----------------------------------------------------------------------------
2073 // --- lar::sparse_vector<T>::datarange_t implementation
2074 // ---
2075 template <typename T> template <typename ITER>
2077  (size_type index, ITER first, ITER last)
2078 {
2079  size_type new_size = std::max(
2080  base_t::relative_index(index) + std::distance(first, last),
2081  base_t::size());
2082  base_t::resize(new_size);
2083  values.resize(new_size);
2084  std::copy(first, last, get_iterator(index));
2085  return *this;
2086 } // lar::sparse_vector<T>::datarange_t::extend()
2087 
2088 
2089 template <typename T>
2091  (size_type to_index, value_type def_value /* = value_zero */)
2092 {
2093  difference_type delta = to_index - base_t::begin_index();
2094  if (delta == 0) return;
2095  base_t::move_head(delta);
2096  if (delta > 0) // shrink
2097  values.erase(values.begin(), values.begin() + delta);
2098  else { // extend
2099  values.insert(values.begin(),
2101  value_const_iterator<value_type>(def_value) - delta
2102  );
2103  }
2104 } // lar::sparse_vector<T>::datarange_t::move_head()
2105 
2106 
2107 // -----------------------------------------------------------------------------
2108 // --- lar::sparse_vector<T>::const_iterator implementation
2109 // ---
2110 template <typename T>
2113  // no container, not doing anything;
2114  // index beyond the end: stays there
2115  if (!cont || (index >= cont->size())) return *this;
2116 
2117  // increment the internal index
2118  ++index;
2119 
2120  // were we in a valid range?
2121  if (currentRange != cont->ranges.end()) {
2122  // if the new index is beyond the current range, pick the next
2123  if (currentRange->end_index() <= index) ++currentRange;
2124  }
2125  // if we have no valid range, we are forever in the void
2126  return *this;
2127 } // lar::sparse_vector<T>::iterator::operator++()
2128 
2129 
2130 template <typename T>
2133  // no container, no idea what to do
2134  if (!cont) throw std::out_of_range("iterator to no sparse vector");
2135 
2136  // index beyond the end: can't return any reference
2137  if (index >= cont->size()) return value_zero;
2138 
2139  // are we in a valid range? if not, we are past the last range
2140  if (currentRange == cont->ranges.end()) return value_zero;
2141 
2142  // if the index is beyond the current range, we are in the void
2143  if (index < currentRange->begin_index()) return value_zero;
2144 
2145  return (*currentRange)[index];
2146 } // lar::sparse_vector<T>::const_iterator::operator*()
2147 
2148 
2149 template <typename T>
2152 {
2153  if (delta == 1) return this->operator++();
2154  index += delta;
2155  if ((currentRange == cont->ranges.end())
2156  || !currentRange->includes(index)
2157  )
2158  refresh_state();
2159  return *this;
2160 } // lar::sparse_vector<T>::const_iterator::operator+=()
2161 
2162 template <typename T>
2165  { return this->operator+= (-delta); }
2166 
2167 
2168 template <typename T>
2171 {
2172  if ((currentRange == cont->ranges.end())
2173  || !currentRange->includes(index + delta)
2174  )
2175  return const_iterator(*cont, index + delta);
2176  const_iterator iter(*this);
2177  iter.index += delta;
2178  return iter;
2179 } // lar::sparse_vector<T>::const_iterator::operator+()
2180 
2181 template <typename T>
2184  { return this->operator+ (-delta); }
2185 
2186 
2188 template <typename T>
2191  (const const_iterator& iter) const
2192 {
2193  if (cont != iter.cont) {
2194  throw std::runtime_error("lar::sparse_vector::const_iterator:"
2195  " difference with alien iterator");
2196  }
2197  return index -iter.index;
2198 } // lar::sparse_vector<T>::const_iterator::operator-(const_iterator)
2199 
2200 
2201 template <typename T>
2203  // update the currentRange
2204  // currentRange is the range including the current item, or next to it
2205  if (cont) {
2206  // the following is actually the range after the index:
2207  currentRange = cont->find_next_range_iter(index);
2208  // if the index is inside the previous index, then we want to move there:
2209  if (currentRange != cont->ranges.begin()) {
2210  if ((currentRange - 1)->end_index() > index) --currentRange;
2211  }
2212  }
2213  else {
2214  currentRange = {};
2215  }
2216 } // lar::sparse_vector<T>::const_iterator::refresh_state()
2217 
2218 
2219 // -----------------------------------------------------------------------------
2220 // --- lar::sparse_vector<T>::iterator implementation
2221 // ---
2222 //
2223 // nothing new so far
2224 //
2225 
2226 
2227 #endif // LARDATAOBJ_UTILITIES_SPARSE_VECTOR_H
void clear()
Removes all the data, making the vector empty.
iterator(const container_t &c, const typename special::begin _)
Special constructor: initializes at the beginning of the container.
bool includes(const range_t &r) const
Returns whether the specified range is completely included in this one.
std::vector< value_type > vector_t
type of STL vector holding this data
sparse_vector(const vector_t &from, size_type offset=0)
Constructor: a solid vector from an existing STL vector.
sparse_vector()
Default constructor: an empty vector.
Float_t s
Definition: plot.C:23
void refresh_state()
Reassigns the internal state according to the index.
const datarange_t & range(size_t i) const
Returns the i-th non-void range (zero-based)
const datarange_t & add_range(size_type offset, const CONT &new_data)
Copies the elements in container to a range with specified offset.
Iterator to the sparse vector values.
vector_t::const_pointer const_pointer
size_type n_ranges() const
Returns the internal list of non-void ranges.
reference(value_type &value)
static size_t expected_vector_size(size_t size)
Returns the expected size taken by a vector of specified size.
const_reference(const value_type *pValue=0)
size_type fix_size()
Extends the vector size according to the last range.
void resize(size_type new_size)
Resizes the vector to the specified size, adding void.
const datarange_t & append(const CONT &range_data)
Adds a sequence of elements as a range at the end of the vector.
const_reference operator*() const
Constant dereferenciation operator.
static value_type abs(value_type v)
Returns the module of the specified value.
vector_t values
data in the range
const_value_box< T > this_t
Definition: sparse_vector.h:43
bool operator<(CryostatID const &a, CryostatID const &b)
Order cryostats with increasing ID.
Definition: geo_types.h:413
reference(const const_reference &from)
intermediate_table::iterator iterator
size_type size() const
Returns the size of the vector.
this_t operator++(int)
Increments the position of the iterator, returns the old position.
A class representing a cell in a sparse vector.
vector_t::pointer pointer
iterator(container_t &c, size_type offset=0)
Constructor from a container and an offset.
constexpr bool operator>(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:158
size_type offset
offset (absolute index) of the first element
range_iterator eat_range_head(range_iterator iRange, size_t index)
Voids the starting elements up to index (excluded) of a given range.
constexpr bool operator<=(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:165
std::iterator< std::random_access_iterator_tag, T > base_t
base type
Definition: sparse_vector.h:73
const_iterator & operator+=(difference_type delta)
Increment and decrement operators.
value_type value
value to be returned when dereferencing
size_type minimum_size() const
Returns the size determined by the ranges already present.
range_t< size_type > base_t
base class
const_iterator::const_reference const_reference
const container_t * cont
pointer to the container
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
STL namespace.
const range_list_t & get_ranges() const
Returns the internal list of non-void ranges.
void void_range(range_iterator iRange)
Turns the specified range into void.
reference(value_type *pValue=0)
range_const_iterator find_extending_range_iter(size_type index) const
Returns an iterator to the range no earlier than index, or end() if none.
value_type & operator=(value_type v)
const_iterator cend() const
Standard iterators interface.
range_const_iterator find_next_range_iter(size_type index) const
Returns an iterator to the range after index, or end() if none.
constexpr bool is_valid(IDNumber_t< L > const id)
Definition: IDNumber.h:112
value_const_iterator< T > operator+(typename value_const_iterator< T >::difference_type ofs, value_const_iterator< T > &iter)
Returns an iterator pointing ahead of this one by the specified steps.
size_type begin_index() const
Returns the first absolute index included in the range.
this_t operator--(int)
Decrements the position of the iterator, returns the old position.
const_reference(const value_type &value)
container_t::difference_type difference_type
const_iterator(const container_t &c, const typename special::end)
Special constructor: initializes at the end of the container.
value_type & set_at(size_type index, value_type value)
Writes into an element (creating or expanding a range if needed)
T value_type
type of the stored values
bool is_void(size_type index) const
Returns whether the specified position is void.
bool separate(const range_t &r) const
Returns if there are elements in between this and the specified range.
const_iterator get_iterator(size_type index) const
Returns an iterator to the specified absolute value (no check!)
constexpr bool operator>=(Index_t left, Flag_t< Storage > right)
Definition: BitMask.h:172
Iterator to the sparse vector values.
bool overlap(const range_t &r) const
Returns if this and the specified range overlap.
datarange_t(size_type offset, ITER first, ITER last)
Constructor: offset and data.
void move_tail(size_type to_index, value_type def_value=value_zero)
Moves the end of this range.
const datarange_t & combine_range(size_type offset, const CONT &other, OP &&op, value_type void_value=value_zero)
Combines the elements in container with the data at offset.
ranges_const_iterator currentRange
pointer to the current (or next) range
bool is_valid() const
Returns if the vector is in a valid state.
size_type end_index() const
Returns the first absolute index not included in the range.
QuadExpr operator-(double v, const QuadExpr &e)
Definition: QuadExpr.h:38
void move_head(difference_type shift)
Moves the begin of the range by the specified amount.
sparse_vector(sparse_vector &&from)
Move constructor.
range_iterator find_extending_range_iter(size_type index)
Returns an iterator to the range no earlier than index, or end() if none.
container_t::size_type size_type
range_t(size_type from, size_type to)
Constructor from first and last index.
static bool should_merge(const typename datarange_t::base_t &a, const typename datarange_t::base_t &b)
Returns if merging the two specified ranges would save memory.
void move_tail(difference_type shift)
Moves the end of the range by the specified amount.
const_iterator cbegin() const
begin and end iterators
bool empty() const
Returns whether the range is empty.
const_iterator(const container_t &c, const typename special::begin)
Special constructor: initializes at the beginning of the container.
datarange_t(const base_t &range)
Constructor: range initialized with 0.
const_value_box(value_type new_value)
Constructor: stores the specified value.
Definition: sparse_vector.h:51
const_iterator cend() const
begin and end iterators
range_list_t ranges
list of ranges
Int_t max
Definition: plot.C:27
bool back_is_void() const
Returns whether the sparse vector ends with void.
vector_t::difference_type difference_type
index difference type
iterator(const_iterator from)
sparse_vector(size_type new_size)
Constructor: a vector with new_size elements in the void.
A range (interval) of integers.
this_t & operator--()
Decrements the position of the iterator, returns the new position.
static size_t min_gap()
Minimum optimal gap between ranges (a guess)
iterator get_iterator(size_type index)
Returns an iterator to the specified absolute value (no check!)
range_iterator find_next_range_iter(size_type index)
Returns an iterator to the range after index, or end() if none.
intermediate_table::const_iterator const_iterator
sparse_vector & operator=(sparse_vector &&from)
Move assignment.
Namespace for special initialization.
datarange_t()
Default constructor: an empty range.
const_iterator get_const_iterator(size_type index) const
Returns an iterator to the specified absolute value (no check!)
iterator end()
Standard iterators interface.
datarange_t & extend(size_type index, ITER first, ITER last)
Appends the specified elements to this range.
value_const_iterator(value_type new_value, difference_type offset)
Constructor: value to be returned and current iterator "position".
Definition: sparse_vector.h:88
vector_t::size_type size_type
size type
void assign(const CONT &new_data)
Copies data from a container.
const_iterator operator-(difference_type delta) const
Increment and decrement operators.
this_t & operator++()
Increments the position of the iterator, returns the new position.
Definition: sparse_vector.h:98
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
value_const_iterator()
Default constructor: use the default value.
Definition: sparse_vector.h:82
std::vector< datarange_t > range_list_t
type of sparse vector data
Little class storing a value.
Definition: sparse_vector.h:42
void make_void(iterator first, iterator last)
Makes all the elements from first and before last void.
vector_t::const_reference const_reference
const_iterator & operator++()
Increment and decrement operators.
container_t::range_list_t::const_iterator ranges_const_iterator
datarange_t & merge_ranges(range_iterator iRange)
Merges all the following ranges.
void move_head(size_type to_index, value_type def_value=value_zero)
Moves the begin of this range.
String & operator+=(String &s, VectorDumper< Vector > const &manip)
Appends a string rendering of a vector to the specified string.
Definition: DumpUtils.h:424
container_t::reference reference
range_const_iterator begin_range() const
Returns a constant iterator to the first data range.
range_t()
Default constructor: empty range.
const datarange_t & append(ITER first, ITER last)
Adds a sequence of elements as a range at the end of the vector.
void push_back(value_type value, value_type thr)
Adds one element to the end of the vector (if zero, just adds void)
sparse_vector(vector_t &&from, size_type offset=0)
Constructor: a solid vector from an existing STL vector.
bool is_valid() const
Returns whether the range is valid (that is, non-negative size)
size_type index
pointer to the current value, as absolute index
sparse_vector< T > this_t
bool optimize(size_t)
Performs internal optimization, returns whether the object was changed.
range_list_t::const_iterator range_const_iterator
type of constant iterator over ranges
const_iterator operator++(int)
Increment and decrement operators.
const_iterator & operator-=(difference_type delta)
Increment and decrement operators.
static value_type is_zero(value_type v)
Returns whether the value is exactly zero.
const datarange_t & combine_range(size_type offset, ITER first, ITER last, OP &&op, value_type void_value=value_zero)
Combines a sequence of elements as a range with data at offset.
iterator operator++(int _)
Increment and decrement operators.
difference_type index
(arbitrary) position pointed by the iterator
const_iterator()
Default constructor, does not iterate anywhere.
void resize(size_t new_size, value_type def_value)
Resizes the range (optionally filling the new elements with def_value)
const datarange_t & append(vector_t &&range_data)
Adds a sequence of elements as a range at the end of the vector.
value_const_iterator< T > this_t
alias for this type
Definition: sparse_vector.h:74
iterator()
Default constructor, does not iterate anywhere.
bool operator!=(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to different IDs.
size_type size() const
Returns the size of the range.
void make_void_around(size_type index)
Casts the whole range with the specified item into the void.
A sparse vector.
std::string value(boost::any const &)
static bool less(const range_t &a, size_type b)
Returns if a is "less" than b.
static bool less(size_type a, const range_t &b)
Returns if a is "less" than b.
range_const_iterator find_range_iterator(size_type index) const
Returns an iterator to the range containing the specified index.
void void_range(size_t iRange)
Turns the specified range into void.
SIZE size_type
type for the indices in the range
LArSoft-specific namespace.
size_type nominal_size
current size
const datarange_t & find_range(size_type index) const
Returns the range containing the specified index.
Int_t min
Definition: plot.C:26
QuadExpr operator+(double v, const QuadExpr &e)
Definition: QuadExpr.h:37
iteratorRange(BITER const &b, EITER const &e)
this_t & operator=(value_type)
Assignment: the assigned value is ignored.
Definition: sparse_vector.h:54
vector_t::const_iterator const_iterator
Namespace hiding implementation details.
Definition: ServiceUtil.h:38
bool empty() const
Returns whether the vector is empty.
const_iterator(const container_t &c, size_type offset)
Constructor from a container and a offset.
Special little box to allow void elements to be treated as references.
void unset_at(size_type index)
Casts the element with the specified index into the void.
Enclosure to use two iterators representing a range in a range-for loop.
void assign(vector_t &&new_data)
Moves data from a vector.
range_const_iterator get_current_range() const
Returns the current range internal value; use it at your own risk!!
const_value_box()
Default constructor: stores default value.
Definition: sparse_vector.h:48
auto const & begin() const
reference operator*() const
Dereferenciation operator (can&#39;t write non-empty elements!)
const_iterator::special special
iterator begin()
Standard iterators interface.
auto const & end() const
Range class, with range and data.
value_type value
the value stored for delivery
Definition: sparse_vector.h:63
void resize(size_type new_size)
Moves the end of the range to fit the specified size.
datarange_t(size_type offset, vector_t &&data)
Constructor: offset and data as a vector (which will be used directly)
const_iterator end() const
begin and end iterators
static value_type is_zero(value_type v, value_type thr)
Returns whether the value is zero below a given threshold.
range_iterator insert_range(range_iterator iInsert, datarange_t &&data)
Plug a new data range in the specified position; no check performed.
std::forward_iterator_tag iterator_category
range_const_iterator end_range() const
Returns a constant iterator to after the last data range.
bool includes(size_type index) const
Returns whether the specified absolute index is included in this range.
static value_type is_equal(value_type a, value_type b)
Returns whether two values are the same.
range_list_t::iterator range_iterator
type of iterator over ranges
const_iterator begin() const
begin and end iterators
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
value_const_iterator(value_type new_value)
Constructor: value that will be returned.
Definition: sparse_vector.h:85
iterator(const container_t &c, const typename special::end _)
Special constructor: initializes at the end of the container.
container_t::value_type value_type
const_iterator cbegin() const
Standard iterators interface.
iterator begin()
begin and end iterators
iterator end()
begin and end iterators
const_iterator::reference reference
Float_t e
Definition: plot.C:34
size_type last
offset (absolute index) after the last element
const_iterator::container_t container_t
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
const_iterator operator+(difference_type delta) const
Increment and decrement operators.
void assign(ITER first, ITER last)
Copies data from a sequence between two iterators.
A constant iterator returning always the same value.
Definition: sparse_vector.h:70
bool operator==(geometry_element_iterator< GEOIDITER > const &iter, GEOIDITER const &id_iter)
Comparison operator: geometry ID and element point to the same ID.
T value_type
type of the value stored
Definition: sparse_vector.h:45
vec_iX clear()
std::ptrdiff_t difference_type
type for index difference
size_type capacity() const
Returns the capacity of the vector (compatibility only)
static value_type is_equal(value_type a, value_type b, value_type thr)
Returns whether two values are the same below a given threshold.
size_type relative_index(size_type index) const
Returns the position within the range of the absolute index specified.
bool borders(size_type index) const
Returns whether an index is within or immediately after this range.
size_type count() const
Returns the number of non-void cells.