clingo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
pod_vector.h
Go to the documentation of this file.
1 //
2 // Copyright (c) 2006-2010, Benjamin Kaufmann
3 //
4 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
5 //
6 // Clasp is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // Clasp is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with Clasp; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 #ifndef BK_LIB_POD_VECTOR_H_INCLUDED
21 #define BK_LIB_POD_VECTOR_H_INCLUDED
22 #include "type_manip.h"
23 #include <iterator>
24 #include <memory>
25 #include <cstring>
26 #include <algorithm>
27 #include <cassert>
28 #include <stdexcept>
29 namespace bk_lib { namespace detail {
30  template <class T>
31  void fill(T* first, T* last, const T& x) {
32  assert(first <= last);
33  switch ((last - first) & 7u)
34  {
35  case 0:
36  while (first != last)
37  {
38  new(first++) T(x);
39  case 7: new(first++) T(x);
40  case 6: new(first++) T(x);
41  case 5: new(first++) T(x);
42  case 4: new(first++) T(x);
43  case 3: new(first++) T(x);
44  case 2: new(first++) T(x);
45  case 1: new(first++) T(x);
46  assert(first <= last);
47  }
48  }
49  }
50  template <class Iter, class T>
51  void copy(Iter first, Iter last, std::size_t s, T* out) {
52  switch (s & 7u)
53  {
54  case 0:
55  while (first != last)
56  {
57  new(out++) T(*first++);
58  case 7: new(out++) T(*first++);
59  case 6: new(out++) T(*first++);
60  case 5: new(out++) T(*first++);
61  case 4: new(out++) T(*first++);
62  case 3: new(out++) T(*first++);
63  case 2: new(out++) T(*first++);
64  case 1: new(out++) T(*first++);
65  }
66  }
67  }
68  template <class T>
69  struct Fill {
70  Fill(const T& val) : val_(val) {}
71  void operator()(T* first, std::size_t n) const { detail::fill(first, first + n, val_); }
72  const T& val_;
73  private: Fill& operator=(const Fill&);
74  };
75  template <class Iter>
76  struct Copy {
77  Copy(Iter first, Iter last) : first_(first), last_(last) {}
78  template <class T>
79  void operator()(T* out, std::size_t n) const { detail::copy(first_, last_, n, out); }
80  Iter first_;
81  Iter last_;
82  };
83  template <class T>
84  struct Memcpy {
85  Memcpy(const T* first) : first_(first) {}
86  void operator()(T* out, std::size_t n) const {
87  std::memcpy(out, first_, n*sizeof(T));
88  }
89  const T* first_;
90  };
91  typedef char yes_type;
92  typedef char (&no_type)[2];
93  template <class T>
94  struct IterType {
95  static yes_type isPtr(const volatile void*);
96  static no_type isPtr(...);
97  static yes_type isLong(int64);
98  static no_type isLong(...);
99  static T& makeT();
100  enum { ptr = sizeof(isPtr(makeT())) == sizeof(yes_type) };
101  enum { num = sizeof(isLong(makeT())) == sizeof(yes_type) };
102  enum { value = ptr ? 1 : num ? 2 : 0 };
103  };
104 
105 } // end namespace bk_lib::detail
106 
108 
114 template <class T, class Allocator = std::allocator<T> >
115 class pod_vector {
116 public:
117  // types:
118  typedef pod_vector<T,Allocator> this_type;//not standard
119  typedef Allocator allocator_type;
120  typedef typename Allocator::reference reference;
121  typedef typename Allocator::const_reference const_reference;
122  typedef typename Allocator::pointer iterator;
123  typedef typename Allocator::const_pointer const_iterator;
124  typedef typename Allocator::pointer pointer;
125  typedef typename Allocator::const_pointer const_pointer;
126  typedef std::reverse_iterator<iterator> reverse_iterator;
127  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
128  typedef T value_type;
129  typedef typename detail::if_then_else<
130  sizeof(typename Allocator::size_type)<=sizeof(unsigned int),
131  typename Allocator::size_type,
132  unsigned int>::type size_type;
133  typedef typename detail::if_then_else<
134  sizeof(typename Allocator::difference_type)<=sizeof(int),
135  typename Allocator::difference_type,
136  int>::type difference_type;
137  // ctors
139 
142  pod_vector() : ebo_(0, allocator_type()) { }
143 
145 
148  explicit pod_vector(const allocator_type& a) : ebo_(0, a) { }
149 
151 
154  explicit pod_vector(size_type n, const T& value = T(), const allocator_type& a = allocator_type())
155  : ebo_(n, a) {
156  detail::fill(ebo_.buf, ebo_.buf + n, value);
157  ebo_.size = n;
158  }
159 
161 
164  template <class Iter>
165  pod_vector(Iter first, Iter last, const allocator_type& a = allocator_type(), typename detail::disable_if<detail::IterType<Iter>::num>::type* = 0)
166  : ebo_(0, a) {
167  insert_range(end(), first, last, typename std::iterator_traits<Iter>::iterator_category());
168  }
169 
171 
174  pod_vector(const pod_vector& other) : ebo_(other.size(), other.get_allocator()) {
175  std::memcpy(ebo_.buf, other.begin(), other.size()*sizeof(T));
176  ebo_.size = other.size();
177  }
178 
179  pod_vector& operator=(const pod_vector& other) {
180  if (this != &other) {
181  assign(other.begin(), other.end());
182  }
183  return *this;
184  }
185 
187 
190  ~pod_vector() { }
191 
196 
198  size_type size() const { return ebo_.size; }
200  size_type max_size() const {
201  typename allocator_type::size_type x = get_allocator().max_size();
202  std::size_t y = size_type(-1)/sizeof(T);
203  return static_cast<size_type>(std::min(std::size_t(x), y));
204  }
206  size_type capacity() const { return ebo_.cap; }
208  bool empty() const { return ebo_.size == 0; }
209 
210  const_iterator begin() const { return ebo_.buf; }
211  const_iterator end() const { return ebo_.buf+ebo_.size;}
212  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
213  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
214 
215  iterator begin() { return ebo_.buf; }
216  iterator end() { return ebo_.buf+ebo_.size; }
217  reverse_iterator rbegin() { return reverse_iterator(end()); }
218  reverse_iterator rend() { return reverse_iterator(begin()); }
219 
221  allocator_type get_allocator() const { return ebo_; }
222 
224 
228 
230 
233  reference operator[](size_type n) {
234  assert(n < size());
235  return ebo_.buf[n];
236  }
237 
239 
242  const_reference operator[](size_type n) const {
243  assert(n < size());
244  return ebo_.buf[n];
245  }
246 
248  const_reference at(size_type n) const {
249  if (n < size()) return ebo_.buf[n];
250  throw std::range_error("pod_vector::at");
251  }
253  reference at(size_type n) {
254  if (n < size()) return ebo_.buf[n];
255  throw std::range_error("pod_vector::at");
256  }
257 
259  reference front() { assert(!empty()); return *ebo_.buf; }
261  const_reference front() const { assert(!empty()); return *ebo_.buf; }
262 
264  reference back() { assert(!empty()); return ebo_.buf[ebo_.size-1]; }
265 
267  const_reference back() const { assert(!empty()); return ebo_.buf[ebo_.size-1]; }
268 
270 
274 
276 
279  void clear() { ebo_.size = 0; }
280 
281  void assign(size_type n, const T& val) {
282  clear();
283  insert(end(), n, val);
284  }
285 
286  template <class Iter>
287  void assign(Iter first, Iter last) {
288  clear();
289  insert(end(), first, last);
290  }
291 
293 
300  iterator erase(iterator pos) {
301  assert(!empty() && pos != end());
302  erase(pos, pos + 1);
303  return pos;
304  }
305 
307 
310  iterator erase(iterator first, iterator last) {
311  if (end() - last > 0) {
312  std::memmove(first, last, (end() - last) * sizeof(T));
313  }
314  ebo_.size -= static_cast<size_type>(last - first);
315  return first;
316  }
317 
319 
326  void resize(size_type ns, const T& val = T()) {
327  if (ns > size()) {
328  ns <= capacity() ? detail::fill(end(), end()+(ns-size()), val) : append_realloc(ns-size(), val);
329  }
330  ebo_.size = ns;
331  }
332 
334 
342  void reserve(size_type n) {
343  if (n > capacity()) {
344  T* temp = ebo_.allocate(n);
345  std::memcpy(temp, ebo_.buf, size()*sizeof(T));
346  ebo_.release();
347  ebo_.buf = temp;
348  ebo_.cap = n;
349  }
350  }
351 
352  void swap(pod_vector& other) {
353  std::swap(ebo_.buf, other.ebo_.buf);
354  std::swap(ebo_.size, other.ebo_.size);
355  std::swap(ebo_.cap, other.ebo_.cap);
356  }
357 
359  void push_back(const T& x) {
360  if (size() < capacity()) {
361  new ((ebo_.buf+ebo_.size++)) T(x);
362  }
363  else {
364  append_realloc(1, x);
365  }
366  }
367 
369 
372  void pop_back() {
373  assert(!empty());
374  --ebo_.size;
375  }
376 
378 
385  iterator insert(iterator pos, const T& val) {
386  return insert(pos, (size_type)1, val);
387  }
388 
390 
393  iterator insert(iterator pos, size_type n, const T& val) {
394  size_type off = static_cast<size_type>(pos-begin());
395  insert_impl(pos, n, detail::Fill<T>(val));
396  return ebo_.buf + off;
397  }
398 
400 
407  template <class Iter>
408  void insert(iterator pos, Iter first, Iter last, typename detail::disable_if<detail::IterType<Iter>::num>::type* = 0) {
409  insert_range(pos, first, last, typename std::iterator_traits<Iter>::iterator_category());
410  }
411 
412 
417 
419 
427  void resize_no_init(size_type ns) {
428  reserve(ns);
429  ebo_.size = ns;
430  }
432 private:
433  size_type grow_size(size_type n) {
434  size_type new_cap = size() + n;
435  assert(new_cap > size() && "pod_vector: max size exceeded!");
436  assert(new_cap > capacity());
437  if (new_cap < 4) new_cap = 1 << (new_cap+1);
438  size_type x = (capacity()*3)>>1;
439  if (new_cap < x) new_cap = x;
440  return new_cap;
441  }
442  void append_realloc(size_type n, const T& x) {
443  size_type new_cap = grow_size(n);
444  pointer temp = ebo_.allocate(new_cap);
445  std::memcpy(temp, ebo_.buf, size()*sizeof(T));
446  detail::fill(temp+size(), temp+size()+n, x);
447  ebo_.release();
448  ebo_.buf = temp;
449  ebo_.cap = new_cap;
450  ebo_.size+= n;
451  }
452  void move_right(iterator pos, size_type n) {
453  assert( (pos || n == 0) && (ebo_.eos() - pos) >= (int)n);
454  std::memmove(pos + n, pos, (end() - pos) * sizeof(T));
455  }
456  template <class It>
457  void insert_range(iterator pos, It first, It last, std::random_access_iterator_tag,
458  typename detail::disable_if<detail::same_type<pointer, It>::value == 0 && detail::same_type<const_pointer, It>::value == 0>::type* = 0) {
459  assert( (first < begin() || first >= end()) && "pod_vec::insert(): Precondition violated!");
460  typename allocator_type::difference_type diff = std::distance(first, last);
461  assert(diff == 0 || (static_cast<size_type>(size()+diff) > size() && "pod_vector: max size exceeded!"));
462  insert_impl(pos, static_cast<size_type>(diff), detail::Memcpy<T>(first));
463  }
464  template <class It>
465  void insert_range(iterator pos, It first, It last, std::forward_iterator_tag) {
466  typename allocator_type::difference_type diff = std::distance(first, last);
467  assert(diff == 0 || (static_cast<size_type>(size()+diff) > size() && "pod_vector: max size exceeded!"));
468  insert_impl(pos, static_cast<size_type>(diff), detail::Copy<It>(first, last));
469  }
470  template <class Iter>
471  void insert_range(iterator pos, Iter first, Iter last, std::input_iterator_tag) {
472  pod_vector<T> temp;
473  while (first != last) temp.push_back(*first++);
474  insert(pos, temp.begin(), temp.end());
475  }
476 
477  // NOTE: template parameter ST should always equal size_type
478  // and is only needed to workaround an internal compiler error
479  // in gcc 3.4.3
480  template <class ST, class P>
481  void insert_impl(iterator pos, ST n, const P& pred) {
482  assert(n == 0 || (size()+n) > size() );
483  if (size()+n <= capacity()) {
484  move_right(pos, n);
485  pred(pos, n);
486  ebo_.size += n;
487  }
488  else {
489  size_type new_cap = grow_size(n);
490  pointer temp = ebo_.allocate(new_cap);
491  size_type prefix = static_cast<size_type>(pos-begin());
492  // copy prefix
493  std::memcpy(temp, begin(), prefix*sizeof(T));
494  // insert new stuff
495  pred(temp+prefix, n);
496  // copy suffix
497  std::memcpy(temp+prefix+n, pos, (end()-pos)*sizeof(T));
498  ebo_.release();
499  ebo_.buf = temp;
500  ebo_.size+= n;
501  ebo_.cap = new_cap;
502  }
503  }
504  struct ebo : public Allocator { // empty-base-optimization
505  typedef typename this_type::size_type size_type;
506  typedef typename this_type::allocator_type A;
507  pointer buf; // pointer to array
508  size_type size; // current size (used elements)
509  size_type cap; // max size before regrow
510  ebo(size_type n, const Allocator& a) : Allocator(a), buf(0), size(0), cap(n) {
511  if (n > 0) { buf = A::allocate(n); }
512  }
513  ~ebo() { release(); }
514  void release() { if (buf) A::deallocate(buf, cap); }
515  T* eos() const { return buf + cap; }
516  } ebo_;
517 };
518 
519 template <class T, class A>
520 inline bool operator==(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
521  return lhs.size() == rhs.size()
522  && std::equal(lhs.begin(), lhs.end(), rhs.begin());
523 }
524 
525 template <class T, class A>
526 inline bool operator!=(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
527  return ! (lhs == rhs);
528 }
529 
530 template <class T, class A>
531 inline bool operator<(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
532  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
533 }
534 
535 template <class T, class A>
536 inline bool operator>(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
537  return rhs < lhs;
538 }
539 
540 template <class T, class A>
541 inline bool operator<=(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
542  return !(rhs < lhs);
543 }
544 
545 template <class T, class A>
546 inline bool operator>=(const pod_vector<T, A>& lhs, const pod_vector<T, A>& rhs) {
547  return !(lhs < rhs);
548 }
549 
550 template <class T, class A>
552  lhs.swap(rhs);
553 }
554 
555 }
556 
557 #endif
558 
BinderType type
Definition: statements.cc:1283
Definition: pod_vector.h:102
const T & val_
Definition: pod_vector.h:72
void operator()(T *out, std::size_t n) const
Definition: pod_vector.h:79
const T * first_
Definition: pod_vector.h:89
Definition: pod_vector.h:100
bool operator!=(const pod_vector< T, A > &lhs, const pod_vector< T, A > &rhs)
Definition: pod_vector.h:526
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: pod_vector.h:127
ULit pred(NAF naf, UTerm &&arg)
Definition: lit_helper.hh:69
void operator()(T *out, std::size_t n) const
Definition: pod_vector.h:86
tuple s
Definition: server.py:45
UTerm lhs
Definition: literals.cc:185
bool operator>(const pod_vector< T, A > &lhs, const pod_vector< T, A > &rhs)
Definition: pod_vector.h:536
Allocator::const_pointer const_pointer
Definition: pod_vector.h:125
Allocator allocator_type
Definition: pod_vector.h:119
tuple a
Definition: pyclingo.py:6
bool operator==(const pod_vector< T, A > &lhs, const pod_vector< T, A > &rhs)
Definition: pod_vector.h:520
Memcpy(const T *first)
Definition: pod_vector.h:85
Iter last_
Definition: pod_vector.h:81
std::unique_ptr< ValTerm > val(Value v)
Definition: term_helper.hh:31
Definition: pod_vector.h:94
Term & rhs
Definition: literals.cc:186
Definition: pod_vector.h:69
Definition: pod_vector.h:84
char(& no_type)[2]
Definition: pod_vector.h:92
void operator()(T *first, std::size_t n) const
Definition: pod_vector.h:71
Definition: pod_vector.h:76
char yes_type
Definition: pod_vector.h:91
static yes_type isPtr(const volatile void *)
void copy(Iter first, Iter last, std::size_t s, T *out)
Definition: pod_vector.h:51
static yes_type isLong(int64)
unsigned num
Definition: dependency.cc:114
UTerm assign
Definition: literals.cc:59
bool operator>=(const pod_vector< T, A > &lhs, const pod_vector< T, A > &rhs)
Definition: pod_vector.h:546
Copy(Iter first, Iter last)
Definition: pod_vector.h:77
Allocator::reference reference
Definition: pod_vector.h:120
Definition: type_manip.h:36
Allocator::const_reference const_reference
Definition: pod_vector.h:121
int x
Definition: utility.cc:65
void fill(T *first, T *last, const T &x)
Definition: pod_vector.h:31
Gringo::IntervalSet< T >::const_iterator begin(Gringo::IntervalSet< T > const &x)
Definition: intervals.hh:311
Allocator::const_pointer const_iterator
Definition: pod_vector.h:123
Allocator::pointer iterator
Definition: pod_vector.h:122
Definition: pod_vector.h:101
Allocator::pointer pointer
Definition: pod_vector.h:124
pod_vector< T, Allocator > this_type
Definition: pod_vector.h:118
A std::vector-replacement for POD-Types.
Definition: pod_vector.h:115
Fill(const T &val)
Definition: pod_vector.h:70
T value_type
Definition: pod_vector.h:128
void swap(pod_vector< T, A > &lhs, pod_vector< T, A > &rhs)
Definition: pod_vector.h:551
LparseOutputter & out
Definition: output.cc:685
Iter first_
Definition: pod_vector.h:80
int end
Definition: literals.cc:62
std::reverse_iterator< iterator > reverse_iterator
Definition: pod_vector.h:126