ztsdb
vector_base.hpp
1 // (C) 2016 Leonardo Silvestri
2 //
3 // This file is part of ztsdb.
4 //
5 // ztsdb is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // ztsdb is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with ztsdb. If not, see <http://www.gnu.org/licenses/>.
17 
18 
19 #ifndef VECTOR_BASE_HPP
20 #define VECTOR_BASE_HPP
21 
22 
23 #include <memory>
24 #include <string>
25 #include <iterator>
26 #include <new> // std::bad_alloc
27 #include <vector>
28 #include <iostream>
29 #include <ratio>
30 #include <type_traits>
31 #include "globals.hpp"
32 #include "string.hpp"
33 #include "timezone/interval.hpp"
34 #include "period.hpp"
35 #include "type_utils.hpp"
36 #include "allocator.hpp"
37 
38 
48 
49 
50 namespace arr {
51 
52  const size_t VECTOR_INITIAL_ALLOC = 1024;
53  using VECTOR_ALLOC_GROWTH = std::ratio<4,3>;
54 
55  template<typename T, typename O> struct vector_iterator;
56  template<typename T, typename O> struct vector_const_iterator;
57 
58  // to disambiguate constructors:
59  struct rsv_t { };
60  constexpr rsv_t rsv{};
61  struct noinit_t { };
62  constexpr noinit_t noinit_tag{};
63 
64  // this is the information that must be mmapped.
65  template<typename T>
66  struct RawVector {
67  size_t typenumber;
68  size_t n;
69  size_t ordered;
70  T v[0];
71  };
72 
73  template<typename T>
74  inline T getInitValue() {
75  return 0;
76  }
77 
78  inline size_t growCapacity(size_t n) {
79  static_assert(VECTOR_ALLOC_GROWTH::num > VECTOR_ALLOC_GROWTH::den,
80  "vector alloc growth multiplier must be > 1.0");
81  if (n > 0 && n > std::numeric_limits<size_t>::max() / VECTOR_ALLOC_GROWTH::num) {
82  // check for overflow and return the max (which of course will later fail allocation)
83  return std::numeric_limits<size_t>::max();
84  }
85  else {
86  return n < VECTOR_INITIAL_ALLOC/2 ? VECTOR_INITIAL_ALLOC :
87  n * VECTOR_ALLOC_GROWTH::num / VECTOR_ALLOC_GROWTH::den;
88  }
89  }
90 
91 
92  template<typename T>
93  inline size_t getTotalSize(size_t n) {
94  if (n > 0 && n > std::numeric_limits<size_t>::max() / sizeof(T) - sizeof(RawVector<T>)) {
95  // check for overflow
96  return std::numeric_limits<size_t>::max();
97  }
98  return n*sizeof(T) + sizeof(RawVector<T>);
99  }
100 
101 
102  template<typename T, typename O=std::less<T>>
103  struct Vector {
104  typedef T value_type;
105  typedef O comparator;
108 
109  friend struct vector_iterator<T,O>;
110  friend struct vector_const_iterator<T,O>;
111  template<typename U, typename UO>
112  friend bool operator==(const Vector<U,UO>& v1, const Vector<U,UO>& v2);
113 
114  template <typename U, typename UO>
115  friend void setv(Vector<U,UO>& v, size_t i, const U& t);
116  template <typename U, typename UO>
117  friend void setv_checkbefore(Vector<U,UO>& v, size_t i, const U& t);
118  template <typename U, typename UO>
119  friend void setv_nocheck(Vector<U,UO>& v, size_t i, const U& t);
120 
121  // constructors --------------------------------------------
122 
124  Vector(Vector<T,O>&& v) : alloc(std::move(v.alloc)), c(v.c), capacity(v.capacity) {
125  // std::cout << "Vector move constructor" << std::endl;
126  // LLL use swap and then c can never be null, check that alloc will actually swap LLL
127  v.c = nullptr;
128  }
129 
130  // copy constructor.
131  Vector(const Vector<T,O>& v,
132  std::unique_ptr<baseallocator>&& alloc_p=std::make_unique<memallocator>())
133  : alloc(std::move(alloc_p)), capacity(v.capacity)
134  {
135  // std::cout << "Vector copy constructor" << std::endl;
136  if (!alloc) {
137  throw std::invalid_argument("Vector<T>: null allocator");
138  }
139  c = new (alloc->allocate(getTotalSize<T>(capacity))) RawVector<T>;
140  memcpy((void*)c, v.c, sizeof(RawVector<T>));
141  for (size_t j=0; j<v.c->n; ++j) {
142  c->v[j] = v.c->v[j];
143  }
144  }
145 
147  Vector(size_t n=0,
148  const T& value=getInitValue<T>(),
149  std::unique_ptr<baseallocator>&& alloc_p=std::make_unique<memallocator>())
150  : alloc(std::move(alloc_p))
151  {
152  if (!alloc) {
153  throw std::invalid_argument("Vector<T>: null allocator");
154  }
155  capacity = growCapacity(n);
156  c = new (alloc->allocate(getTotalSize<T>(capacity))) RawVector<T>;
157  c->typenumber = TypeNumber<T>::n;
158  c->n = n;
159  for (size_t i=0; i<n; ++i) {
160  new (&c->v[i]) T(value);
161  }
162  c->ordered = n > 1 ? O()(value, value) : true;
163  }
164 
166  Vector(rsv_t, size_t n,
167  std::unique_ptr<baseallocator>&& alloc_p=std::make_unique<memallocator>())
168  : alloc(std::move(alloc_p))
169  {
170  if (!alloc) {
171  throw std::invalid_argument("Vector<T,O>: null allocator");
172  }
173  capacity = growCapacity(n);
174  c = new (alloc->allocate(getTotalSize<T>(capacity))) RawVector<T>;
175  c->typenumber = TypeNumber<T>::n;
176  c->n = 0;
177  c->ordered = true;
178  }
179 
182  Vector(noinit_t, size_t n,
183  std::unique_ptr<baseallocator>&& alloc_p=std::make_unique<memallocator>())
184  : alloc(std::move(alloc_p))
185  {
186  if (!alloc) {
187  throw std::invalid_argument("Vector<T,O>: null allocator");
188  }
189  capacity = growCapacity(n);
190  c = new (alloc->allocate(getTotalSize<T>(capacity))) RawVector<T>;
191  c->typenumber = TypeNumber<T>::n;
192  c->n = n;
193  c->ordered = true;
194  }
195 
197  template <class InputIterator>
198  Vector(const InputIterator& b,
199  const InputIterator& e,
200  std::unique_ptr<baseallocator>&& alloc_p=std::make_unique<memallocator>())
201  : alloc(std::move(alloc_p))
202  {
203  if (!alloc) {
204  throw std::invalid_argument("Vector<T,O>: null allocator");
205  }
206  size_t n = e - b;
207  capacity = growCapacity(n);
208  c = new (alloc->allocate(getTotalSize<T>(capacity))) RawVector<T>;
209  c->typenumber = TypeNumber<T>::n;
210  c->n = n;
211  size_t i = 0;
212  c->ordered = true;
213  if (n > 0) {
214  c->v[i++] = *b;
215  for (auto iter=b+1; iter!=e; ++iter) {
216  c->v[i] = *iter;
217  if (!O()(c->v[i-1], c->v[i])) {
218  c->ordered = false;
219  }
220  ++i;
221  }
222  }
223  }
224 
225  Vector(std::initializer_list<T> l,
226  std::unique_ptr<baseallocator>&& alloc_p=std::make_unique<memallocator>())
227  : alloc(std::move(alloc_p))
228  {
229  if (!alloc) {
230  throw std::invalid_argument("Vector<T,O>: null allocator");
231  }
232  size_t n = l.size();
233  capacity = growCapacity(n);
234  c = new (alloc->allocate(getTotalSize<T>(capacity))) RawVector<T>;
235  c->typenumber = TypeNumber<T>::n;
236  c->n = n;
237  size_t i = 0;
238  c->ordered = true;
239  if (n > 0) {
240  c->v[i++] = *l.begin();
241  for (auto iter=l.begin()+1; iter!=l.end(); ++iter) {
242  c->v[i] = *iter;
243  if (!O()(c->v[i-1], c->v[i])) c->ordered = false;
244  ++i;
245  }
246  }
247  }
248 
250  Vector(std::unique_ptr<baseallocator>&& alloc_p) : alloc(std::move(alloc_p)) {
251  if (!alloc) {
252  throw std::invalid_argument("Vector<T,O>: null allocator");
253  }
254  c = static_cast<RawVector<T>*>(alloc->initialize()); // will throw!
255  capacity = alloc->size();
256  }
257 
258  void swap(Vector<T,O>& o) {
259  std::swap(alloc, o.alloc);
260  std::swap(c, o.c);
261  std::swap(capacity, o.capacity);
262  }
263 
264  Vector& operator=(Vector<T,O> other) {
265  swap(other);
266  return *this;
267  }
268 
269  size_t getBufferSize() const {
270  return sizeof(RawVector<T>) + size()*sizeof(T);
271  }
272 
273  size_t to_buffer(char* buf) const {
274  // header:
275  memcpy(buf, c, sizeof(RawVector<T>));
276  size_t offset = sizeof(RawVector<T>);
277  // data:
278  size_t copysz = size()*sizeof(T);
279  memcpy(buf + offset, c->v, copysz);
280  return offset + copysz;
281  }
282 
283  T& operator[](size_t i) {
284  if (!c || i > size() - 1) {
285  throw std::out_of_range("subscript out of bounds");
286  }
287  return c->v[i];
288  }
289 
290  const T& operator[](size_t i) const {
291  if (!c || i > size() - 1) {
292  throw std::out_of_range("subscript out of bounds");
293  }
294  return c->v[i];
295  }
296 
297  void push_back(const T& value) {
298  if (c->n + 1 > capacity) {
299  if (!alloc) {
300  throw std::range_error("vector::push_back: cannot reallocate with null allocator");
301  }
302  capacity = growCapacity(c->n);
303  auto mem = alloc->reallocate(c, getTotalSize<T>(capacity));
304  c = static_cast<RawVector<T>*>(mem);
305  }
306  new (&c->v[c->n]) T(value);
307  c->ordered = c->n > 0 ? c->ordered & O()(c->v[c->n-1], c->v[c->n]) : true;
308  ++c->n;
309  }
310 
311 
312  template <class InputIterator>
313  vector_iterator<T,O> insert(vector_iterator<T,O> position,
314  const InputIterator first,
315  const InputIterator last) {
316  auto ordered = c->ordered; // remember this because the iterator
317  // access lower will set c->ordered
318  // to false no matter what
319  auto diff = last - first;
320  if (diff <= 0) {
321  return position;
322  }
323  auto oldbegin = begin();
324  auto oldend = end();
325  resize(size() + static_cast<size_t>(diff));
326  // move down everything that is at and beyond position:
327  if (oldbegin != oldend && oldend - 1 - position > 0) {
328  for (auto iter = end(); iter != position; --iter) {
329  *(iter) = *(iter - diff);
330  }
331  }
332  // insert the elements
333  *position = *first;
334  if (position != begin()) {
335  // if the insertion is not at the beginning we need to check the
336  // next element for order:
337  ordered &= O()(*(position-1), *position);
338  }
339  ++position;
340  for (auto iter = first+1; iter != last; ++iter) {
341  *position = *iter;
342  if (c->ordered && !O()(*(position-1), *position)) {
343  ordered = false;
344  }
345  ++position;
346  }
347  if (position != end()) {
348  // if the insertion was not at the end we need to check the
349  // next element for order:
350  ordered &= O()(*(position-1), *position);
351  }
352  c->ordered = ordered;
353  return position;
354  }
355 
356  vector_iterator<T,O> erase(const vector_iterator<T,O>& position) {
357  for (auto iter = position; iter != end()-1; ++iter) {
358  *iter = *(iter + 1);
359  }
360  resize(c->n - 1);
361  return position;
362  }
363 
364  vector_iterator<T,O> erase(const vector_iterator<T,O>& first, const vector_iterator<T,O>& last) {
365  auto diff = last - first;
366  for (auto iter = first; iter + diff != end(); ++iter) {
367  *iter = *(iter + diff);
368  }
369  resize(c->n - diff);
370  return first;
371  }
372 
373  explicit operator std::vector<T>() const {
374  return std::vector<T>(&c->v[0], &c->v[c->n]);
375  }
376 
377  const T& front() const {
378  if (!c || !c->n) {
379  throw std::range_error("front on empty Vector");
380  }
381  return c->v[0];
382  }
383 
384  const T& back() const {
385  if (!c || !c->n) {
386  throw std::range_error("front on empty Vector");
387  }
388  return c->v[c->n-1];
389  }
390 
391  size_t size() const { if (c) return c->n; else return 0; }
392  bool isOrdered() const { if (c) return c->ordered; else return false; }
393  void forceOrdered() { if (c) c->ordered = true; }
394  void forceUnOrdered() { if (c) c->ordered = false; }
395  void setOrdered(bool val) { if (c) c->ordered = val; }
396 
397  bool checkAndSetOrdered() {
398  for (size_t j=1; j<size(); ++j) {
399  if (!O()(c->v[j-1], c->v[j])) {
400  c->ordered = false;
401  return false;
402  }
403  }
404  c->ordered = true;
405  return true;
406  }
407 
408  Vector<T,O>& init(size_t count, const T& value) {
409  resize(count);
410  for (size_t j=0; j<count; ++j) {
411  c->v[j] = value;
412  }
413  c->ordered = count > 1 ? O()(value, value) : true; // a single element is always ordered
414  return *this;
415  }
416 
417  // the elements after current end will be uninitialized
418  Vector<T,O>& resize(size_t n, size_t from=0) {
419  if (from > c->n) {
420  throw std::out_of_range("resize from out of bounds");
421  }
422  if (from || n != c->n) { // only resize if needed
423  if (!alloc) {
424  throw std::range_error("vector::resize: cannot reallocate with null allocator");
425  }
426  capacity = growCapacity(n);
427  RawVector<T> rv = *c;
428  c = new (alloc->reallocate((char*)c + from*sizeof(T), memsize(capacity))) RawVector<T>;
429  memcpy((void*)c, &rv, sizeof(RawVector<T>));
430  c->n = n;
431  }
432  return *this;
433  }
434 
435  Vector<T,O>& resize(size_t n, size_t from, const T& v) {
436  if (from >= c->n) {
437  throw std::out_of_range("resize from out of bounds");
438  }
439  size_t start_fill = c->n - from;
440  resize(n, from);
441  for (size_t i = start_fill; i < n; ++i) {
442  c->v[i] = v;
443  }
444  return *this;
445  }
446 
447 
448  // The problem is this will not work for 'T' that are not "flat"
449  // and we don't know how to check for that. It's a pretty
450  // dangerous trap set up for unaware users. LLL
451  size_t append(const char* buf, const size_t len) {
452  // first check we have enough bytes to construct a 'RawVector':
453  if (len < sizeof(RawVector<T>)) {
454  throw std::out_of_range("invalid append buffer: too short");
455  }
456  auto appendvec = reinterpret_cast<const RawVector<T>*>(buf);
457  // now we know the true size of the vector, check buf len again:
458  const size_t totalsz = sizeof(RawVector<T>) + appendvec->n * sizeof(T);
459  if (len < totalsz) {
460  throw std::out_of_range("missing data");
461  }
462 
463  // check the typenumber:
464  if (TypeNumber<T>::n != appendvec->typenumber) {
465  throw std::out_of_range("incorrect type");
466  }
467 
468  auto old_n = c->n;
469  resize(c->n + appendvec->n); // will also redimension
470  memcpy(&c->v[old_n], appendvec->v, appendvec->n*sizeof(T));
471 
472  if (appendvec->n) {
473  c->ordered &= appendvec->ordered;
474  if (old_n) {
475  c->ordered &= O()(c->v[old_n-1], c->v[old_n]);
476  }
477  }
478  return totalsz;
479  }
480 
481  template <typename AO=O>
482  Vector& sort() {
483  if (std::is_same<AO, O>::value && c->ordered) return *this;
484 
485  std::sort(begin(), end(), AO());
486 
487  // if the sort function is the same as the one defined for
488  // 'Vector', then sorting will result in a vector that is
489  // ordered by 'O', so we set the ordered flag.
490  if (std::is_same<AO, O>::value) {
491  c->ordered = true;
492  }
493 
494  return *this;
495  }
496 
497  template<typename U, typename AO=O>
498  Vector<U> sort_idx(size_t base=0) const {
499  Vector<U> idx(rsv, this->size());
500  for (size_t j=0; j<size(); ++j) idx.push_back(j+base);
501  std::sort(idx.begin(), idx.end(),
502  [this, base](size_t a, size_t b) {
503  return AO()((*this)[a-base], (*this)[b-base]); });
504  return idx;
505  }
506 
507  template<typename F, typename ...U>
508  Vector& apply(const U&... u) {
509  c->ordered = true; // we're doing the whole vector, so
510  // forget about the current status and
511  // calculate it with
512  // 'setv_checkbefore'
513  for (size_t i=0; i<size(); ++i) {
514  setv_checkbefore(*this, i, F()((*this)[i], u[i]...));
515  }
516  return *this;
517  }
518 
519  template<typename F, typename U>
520  Vector& apply_scalar_post(const U& u) {
521  c->ordered = true;
522  for (size_t i=0; i<size(); ++i) {
523  setv_checkbefore(*this, i, F()((*this)[i], u));
524  }
525  return *this;
526  }
527 
528  void deallocate() {
529  alloc->deallocate(c, c->n);
530  c = nullptr;
531  capacity = 0;
532  }
533 
534  vector_iterator<T,O> begin() { return vector_iterator<T,O>(*this, 0); }
535  vector_iterator<T,O> end() { return vector_iterator<T,O>(*this, c->n); }
536  vector_const_iterator<T,O> begin() const { return vector_const_iterator<T,O>(*this, 0); }
537  vector_const_iterator<T,O> end() const { return vector_const_iterator<T,O>(*this, c->n); }
538  vector_const_iterator<T,O> cbegin() const { return vector_const_iterator<T,O>(*this, 0); }
539  vector_const_iterator<T,O> cend() const { return vector_const_iterator<T,O>(*this, c->n); }
540 
541  ~Vector() {
542  // alloc will get destroyed automatically, which means freeing c
543  }
544 
545  const RawVector<T>* getRawVectorPtr() const { return c; }
546 
548  Vector<T,O>(char* buf, size_t len) : alloc(nullptr)
549  {
550  capacity = len;
551  // checks LLL
552  c = new (buf) RawVector<T>;
553  }
554 
555  T* c_ptr() { return c ? c->v : nullptr; }
556  const T* c_ptr() const { return c ? c->v : nullptr; }
557  const baseallocator* getAllocator() const { return alloc.get(); }
558 
559  private:
560  std::unique_ptr<baseallocator> alloc;
561  RawVector<T>* c;
562  size_t capacity;
563 
564  T& at(size_t i) { return c->v[i]; }
565 
566  static inline size_t memsize(size_t n) { return n*sizeof(T) + sizeof(RawVector<T>); }
567  };
568 
569 
570  inline size_t getTypeNumber(const std::string& filename) {
571  mmapallocator alloc(filename);
572  size_t* tp = static_cast<size_t*>(alloc.initialize());
573  return *tp;
574  }
575 
576 
578  template<typename T, typename O>
579  bool operator==(const Vector<T,O>& v1, const Vector<T,O>& v2) {
580  if (v1.c->n != v2.c->n) return false;
581  for (size_t i=0; i<v1.c->n; ++i) {
582  if (!(v1.c->v[i] == v2.c->v[i])) {
583  return false;
584  }
585  }
586  return true;
587  }
588 
589 
592  template<>
593  inline bool operator==(const Vector<double>& v1, const Vector<double>& v2) {
594  if (v1.c->n != v2.c->n) return false;
595  return memcmp(v1.c->v, v2.c->v, v1.c->n * sizeof(double)) == 0;
596  }
597 
598  template<typename T, typename O>
599  bool operator!=(const Vector<T,O>& v1, const Vector<T,O>& v2) {
600  return !(v1 == v2);
601  }
602 
603  template<typename T, typename O>
604  struct vector_iterator {
605  typedef std::random_access_iterator_tag iterator_category;
606  typedef vector_iterator<T,O> iterator;
607  typedef std::ptrdiff_t difference_type;
608  typedef size_t size_type;
609  typedef T value_type;
610  typedef T* pointer;
611  typedef T& reference;
612 
613  vector_iterator(Vector<T,O>& v_p, size_t pos_p = 0) : v(v_p), pos(pos_p) { }
614  vector_iterator(const vector_iterator& i) : v(i.v), pos(i.pos) { }
615  ~vector_iterator() { }
616 
617  vector_iterator& operator=(const vector_iterator& i) { pos = i.pos; return *this; }
618  bool operator==(const vector_iterator& i) const { return &v==&i.v && pos==i.pos; }
619  bool operator!=(const vector_iterator& i) const { return &v!=&i.v || pos!=i.pos; }
620  bool operator< (const vector_iterator& i) const { return pos < i.pos; }
621  bool operator<=(const vector_iterator& i) const { return pos <= i.pos; }
622  bool operator> (const vector_iterator& i) const { return pos > i.pos; }
623  bool operator>=(const vector_iterator& i) const { return pos >= i.pos; }
624 
625  vector_iterator operator+(size_t n) const {
626  return vector_iterator<T,O>(v, pos + n);
627  }
628  vector_iterator& operator+=(size_t n) {
629  pos += n;
630  return *this;
631  }
632  vector_iterator operator-(size_t n) const {
633  return vector_iterator<T,O>(v, pos - n);
634  }
635 
636  difference_type operator-(const vector_iterator& i) const {
637  return pos - i.pos;
638  }
639 
640  vector_iterator& operator++() { ++pos; return *this; }
641  vector_iterator operator++(int)
642  {
643  return vector_iterator<T,O>(v, pos++);
644  }
645  vector_iterator& operator--() { --pos; return *this; }
646  vector_iterator operator--(int)
647  {
648  return vector_iterator<T,O>(v, pos--);
649  }
650 
651  reference operator*() const {
652  v.forceUnOrdered();
653  return v.at(pos);
654  }
655  pointer operator->() const {
656  v.forceUnOrdered();
657  return &v.at(pos);
658  }
659 
660  explicit operator size_t() const {
661  return pos;
662  }
663 
664  private:
665  Vector<T,O>& v;
666  size_t pos;
667  };
668 
669  template<typename T, typename O>
670  struct vector_const_iterator {
671  typedef std::random_access_iterator_tag iterator_category;
672  typedef vector_const_iterator<T,O> iterator;
673  typedef std::ptrdiff_t difference_type;
674  typedef size_t size_type;
675  typedef T value_type;
676  typedef const T* pointer;
677  typedef const T& reference;
678 
679  vector_const_iterator(const Vector<T,O>& v_p, size_t pos_p = 0) : v(v_p), pos(pos_p) { }
680  vector_const_iterator(const vector_const_iterator& i) : v(i.v), pos(i.pos) { }
681  ~vector_const_iterator() { }
682 
683  vector_const_iterator& operator=(const vector_const_iterator& i) { pos = i.pos; return *this; }
684  bool operator==(const vector_const_iterator& i) const { return &v==&i.v && pos==i.pos; }
685  bool operator!=(const vector_const_iterator& i) const { return &v!=&i.v || pos!=i.pos; }
686  vector_const_iterator operator+(size_t n) const {
687  return vector_const_iterator<T,O>(v, pos + n);
688  }
689  vector_const_iterator& operator+=(size_t n) {
690  pos += n;
691  return *this;
692  }
693  vector_const_iterator operator-(size_t n) const {
694  return vector_const_iterator<T,O>(v, pos - n);
695  }
696  difference_type operator-(const vector_const_iterator& i) const {
697  return pos - i.pos;
698  }
699 
700  vector_const_iterator& operator++() { ++pos; return *this; }
701  vector_const_iterator operator++(int)
702  {
703  return vector_const_iterator<T,O>(v, pos++);
704  }
705  vector_const_iterator& operator--() { --pos; return *this; }
706  vector_const_iterator operator--(int)
707  {
708  return vector_const_iterator<T,O>(v, pos--);
709  }
710 
711  reference operator*() const { return v[pos]; }
712  pointer operator->() const { return &v[pos]; }
713 
714  size_t getpos() const { return pos; } // mostly for debug purposes
715 
716  private:
717  const Vector<T,O>& v;
718  size_t pos;
719  };
720 
721 
722  template <typename T, typename O>
723  void setv(Vector<T,O>& v, size_t i, const T& t) {
724  if (i >= v.size()) throw std::range_error("subscript out of bounds");
725  if (v.isOrdered()) {
726  if (i > 0) v.c->ordered = O()(v[i-1], t);
727  if (i < v.size()-1) v.c->ordered = v.c->ordered && O()(t, v[i+1]);
728  }
729  v.c->v[i] = t;
730  }
731  template <typename T, typename O>
732  void setv_checkbefore(Vector<T,O>& v, size_t i, const T& t) {
733  if (i >= v.size()) throw std::range_error("subscript out of bounds");
734  v.c->v[i] = t;
735  if (v.isOrdered()) {
736  if (i > 0) v.c->ordered = O()(v.c->v[i-1], t);
737  }
738  }
739 
740  template <typename T, typename O>
741  void setv_nocheck(Vector<T,O>& v, size_t i, const T& t) {
742  v.c->v[i] = t;
743  }
744 
745 } // end namespace arr
746 
747 
748 #endif
arr::Vector::Vector
Vector(Vector< T, O > &&v)
move constructor.
Definition: vector_base.hpp:124
arr::Vector
Definition: vector_base.hpp:103
val
Contains the types that constitute the output of an evaluation by the interpreter.
Definition: display.hpp:31
arr::vector_const_iterator
Definition: vector_base.hpp:56
arr::Vector::Vector
Vector(const InputIterator &b, const InputIterator &e, std::unique_ptr< baseallocator > &&alloc_p=std::make_unique< memallocator >())
std::vector iterator constructor.
Definition: vector_base.hpp:198
arr::TypeNumber
Definition: type_utils.hpp:10
arr::vector_iterator
Definition: vector_base.hpp:55
arr::Vector::Vector
Vector(rsv_t, size_t n, std::unique_ptr< baseallocator > &&alloc_p=std::make_unique< memallocator >())
basic constructor leaving the vector allocated but uninitialized.
Definition: vector_base.hpp:166
arr::rsv_t
Definition: vector_base.hpp:59
arr::Vector::Vector
Vector(std::unique_ptr< baseallocator > &&alloc_p)
constructor from a mmapallocator.
Definition: vector_base.hpp:250
arr::Vector::Vector
Vector(noinit_t, size_t n, std::unique_ptr< baseallocator > &&alloc_p=std::make_unique< memallocator >())
Definition: vector_base.hpp:182
arr
Contains the classes and functions that implement a multidimentional array type.
Definition: allocator.hpp:29
arr::RawVector
Definition: vector_base.hpp:66
arr::Vector::Vector
Vector(size_t n=0, const T &value=getInitValue< T >(), std::unique_ptr< baseallocator > &&alloc_p=std::make_unique< memallocator >())
basic constructor with initial value.
Definition: vector_base.hpp:147
arr::noinit_t
Definition: vector_base.hpp:61