NEST  2.6.0,not_revisioned_source_dir@0
sparsetable.h
Go to the documentation of this file.
1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 // ---
31 //
32 //
33 // A sparsetable is a random container that implements a sparse array,
34 // that is, an array that uses very little memory to store unassigned
35 // indices (in this case, between 1-2 bits per unassigned index). For
36 // instance, if you allocate an array of size 5 and assign a[2] = <big
37 // struct>, then a[2] will take up a lot of memory but a[0], a[1],
38 // a[3], and a[4] will not. Array elements that have a value are
39 // called "assigned". Array elements that have no value yet, or have
40 // had their value cleared using erase() or clear(), are called
41 // "unassigned".
42 //
43 // Unassigned values seem to have the default value of T (see below).
44 // Nevertheless, there is a difference between an unassigned index and
45 // one explicitly assigned the value of T(). The latter is considered
46 // assigned.
47 //
48 // Access to an array element is constant time, as is insertion and
49 // deletion. Insertion and deletion may be fairly slow, however:
50 // because of this container's memory economy, each insert and delete
51 // causes a memory reallocation.
52 //
53 // NOTE: You should not test(), get(), or set() any index that is
54 // greater than sparsetable.size(). If you need to do that, call
55 // resize() first.
56 //
57 // --- Template parameters
58 // PARAMETER DESCRIPTION DEFAULT
59 // T The value of the array: the type of --
60 // object that is stored in the array.
61 //
62 // GROUP_SIZE How large each "group" in the table 48
63 // is (see below). Larger values use
64 // a little less memory but cause most
65 // operations to be a little slower
66 //
67 // Alloc: Allocator to use to allocate memory. libc_allocator_with_realloc
68 //
69 // --- Model of
70 // Random Access Container
71 //
72 // --- Type requirements
73 // T must be Copy Constructible. It need not be Assignable.
74 //
75 // --- Public base classes
76 // None.
77 //
78 // --- Members
79 // Type members
80 //
81 // MEMBER WHERE DEFINED DESCRIPTION
82 // value_type container The type of object, T, stored in the array
83 // allocator_type container Allocator to use
84 // pointer container Pointer to p
85 // const_pointer container Const pointer to p
86 // reference container Reference to t
87 // const_reference container Const reference to t
88 // size_type container An unsigned integral type
89 // difference_type container A signed integral type
90 // iterator [*] container Iterator used to iterate over a sparsetable
91 // const_iterator container Const iterator used to iterate over a table
92 // reverse_iterator reversible Iterator used to iterate backwards over
93 // container a sparsetable
94 // const_reverse_iterator reversible container Guess
95 // nonempty_iterator [+] sparsetable Iterates over assigned
96 // array elements only
97 // const_nonempty_iterator sparsetable Iterates over assigned
98 // array elements only
99 // reverse_nonempty_iterator sparsetable Iterates backwards over
100 // assigned array elements only
101 // const_reverse_nonempty_iterator sparsetable Iterates backwards over
102 // assigned array elements only
103 //
104 // [*] All iterators are const in a sparsetable (though nonempty_iterators
105 // may not be). Use get() and set() to assign values, not iterators.
106 //
107 // [+] iterators are random-access iterators. nonempty_iterators are
108 // bidirectional iterators.
109 
110 // Iterator members
111 // MEMBER WHERE DEFINED DESCRIPTION
112 //
113 // iterator begin() container An iterator to the beginning of the table
114 // iterator end() container An iterator to the end of the table
115 // const_iterator container A const_iterator pointing to the
116 // begin() const beginning of a sparsetable
117 // const_iterator container A const_iterator pointing to the
118 // end() const end of a sparsetable
119 //
120 // reverse_iterator reversable Points to beginning of a reversed
121 // rbegin() container sparsetable
122 // reverse_iterator reversable Points to end of a reversed table
123 // rend() container
124 // const_reverse_iterator reversable Points to beginning of a
125 // rbegin() const container reversed sparsetable
126 // const_reverse_iterator reversable Points to end of a reversed table
127 // rend() const container
128 //
129 // nonempty_iterator sparsetable Points to first assigned element
130 // begin() of a sparsetable
131 // nonempty_iterator sparsetable Points past last assigned element
132 // end() of a sparsetable
133 // const_nonempty_iterator sparsetable Points to first assigned element
134 // begin() const of a sparsetable
135 // const_nonempty_iterator sparsetable Points past last assigned element
136 // end() const of a sparsetable
137 //
138 // reverse_nonempty_iterator sparsetable Points to first assigned element
139 // begin() of a reversed sparsetable
140 // reverse_nonempty_iterator sparsetable Points past last assigned element
141 // end() of a reversed sparsetable
142 // const_reverse_nonempty_iterator sparsetable Points to first assigned
143 // begin() const elt of a reversed sparsetable
144 // const_reverse_nonempty_iterator sparsetable Points past last assigned
145 // end() const elt of a reversed sparsetable
146 //
147 //
148 // Other members
149 // MEMBER WHERE DEFINED DESCRIPTION
150 // sparsetable() sparsetable A table of size 0; must resize()
151 // before using.
152 // sparsetable(size_type size) sparsetable A table of size size. All
153 // indices are unassigned.
154 // sparsetable(
155 // const sparsetable &tbl) sparsetable Copy constructor
156 // ~sparsetable() sparsetable The destructor
157 // sparsetable &operator=( sparsetable The assignment operator
158 // const sparsetable &tbl)
159 //
160 // void resize(size_type size) sparsetable Grow or shrink a table to
161 // have size indices [*]
162 //
163 // void swap(sparsetable &x) sparsetable Swap two sparsetables
164 // void swap(sparsetable &x, sparsetable Swap two sparsetables
165 // sparsetable &y) (global, not member, function)
166 //
167 // size_type size() const sparsetable Number of "buckets" in the table
168 // size_type max_size() const sparsetable Max allowed size of a sparsetable
169 // bool empty() const sparsetable true if size() == 0
170 // size_type num_nonempty() const sparsetable Number of assigned "buckets"
171 //
172 // const_reference get( sparsetable Value at index i, or default
173 // size_type i) const value if i is unassigned
174 // const_reference operator[]( sparsetable Identical to get(i) [+]
175 // difference_type i) const
176 // reference set(size_type i, sparsetable Set element at index i to
177 // const_reference val) be a copy of val
178 // bool test(size_type i) sparsetable True if element at index i
179 // const has been assigned to
180 // bool test(iterator pos) sparsetable True if element pointed to
181 // const by pos has been assigned to
182 // void erase(iterator pos) sparsetable Set element pointed to by
183 // pos to be unassigned [!]
184 // void erase(size_type i) sparsetable Set element i to be unassigned
185 // void erase(iterator start, sparsetable Erases all elements between
186 // iterator end) start and end
187 // void clear() sparsetable Erases all elements in the table
188 //
189 // I/O versions exist for both FILE* and for File* (Google2-style files):
190 // bool write_metadata(FILE *fp) sparsetable Writes a sparsetable to the
191 // bool write_metadata(File *fp) given file. true if write
192 // completes successfully
193 // bool read_metadata(FILE *fp) sparsetable Replaces sparsetable with
194 // bool read_metadata(File *fp) version read from fp. true
195 // if read completes sucessfully
196 // bool write_nopointer_data(FILE *fp) Read/write the data stored in
197 // bool read_nopointer_data(FILE*fp) the table, if it's simple
198 //
199 // bool operator==( forward Tests two tables for equality.
200 // const sparsetable &t1, container This is a global function,
201 // const sparsetable &t2) not a member function.
202 // bool operator<( forward Lexicographical comparison.
203 // const sparsetable &t1, container This is a global function,
204 // const sparsetable &t2) not a member function.
205 //
206 // [*] If you shrink a sparsetable using resize(), assigned elements
207 // past the end of the table are removed using erase(). If you grow
208 // a sparsetable, new unassigned indices are created.
209 //
210 // [+] Note that operator[] returns a const reference. You must use
211 // set() to change the value of a table element.
212 //
213 // [!] Unassignment also calls the destructor.
214 //
215 // Iterators are invalidated whenever an item is inserted or
216 // deleted (ie set() or erase() is used) or when the size of
217 // the table changes (ie resize() or clear() is used).
218 //
219 // See doc/sparsetable.html for more information about how to use this class.
220 
221 // Note: this uses STL style for naming, rather than Google naming.
222 // That's because this is an STL-y container
223 
224 #ifndef UTIL_GTL_SPARSETABLE_H_
225 #define UTIL_GTL_SPARSETABLE_H_
226 
227 #include <sparseconfig.h>
228 #include <stdlib.h> // for malloc/free
229 #include <stdio.h> // to read/write tables
230 #include <string.h> // for memcpy
231 #ifdef HAVE_STDINT_H
232 #include <stdint.h> // the normal place uint16_t is defined
233 #endif
234 #ifdef HAVE_SYS_TYPES_H
235 #include <sys/types.h> // the normal place u_int16_t is defined
236 #endif
237 #ifdef HAVE_INTTYPES_H
238 #include <inttypes.h> // a third place for uint16_t or u_int16_t
239 #endif
240 #include <assert.h> // for bounds checking
241 #include <iterator> // to define reverse_iterator for me
242 #include <algorithm> // equal, lexicographical_compare, swap,...
243 #include <memory> // uninitialized_copy, uninitialized_fill
244 #include <vector> // a sparsetable is a vector of groups
245 #include <type_traits.h>
246 #include <hashtable-common.h>
248 
249 // A lot of work to get a type that's guaranteed to be 16 bits...
250 #ifndef HAVE_U_INT16_T
251 # if defined HAVE_UINT16_T
252  typedef uint16_t u_int16_t; // true on solaris, possibly other C99 libc's
253 # elif defined HAVE___UINT16
254  typedef __int16 int16_t; // true on vc++7
255  typedef unsigned __int16 u_int16_t;
256 # else
257  // Cannot find a 16-bit integer type. Hoping for the best with "short"...
258  typedef short int int16_t;
259  typedef unsigned short int u_int16_t;
260 # endif
261 #endif
262 
263 _START_GOOGLE_NAMESPACE_
264 
265 namespace base { // just to make google->opensource transition easier
268 using GOOGLE_NAMESPACE::integral_constant;
269 using GOOGLE_NAMESPACE::has_trivial_copy;
270 using GOOGLE_NAMESPACE::has_trivial_destructor;
271 using GOOGLE_NAMESPACE::is_same;
272 }
273 
274 
275 // The smaller this is, the faster lookup is (because the group bitmap is
276 // smaller) and the faster insert is, because there's less to move.
277 // On the other hand, there are more groups. Since group::size_type is
278 // a short, this number should be of the form 32*x + 16 to avoid waste.
279 static const u_int16_t DEFAULT_SPARSEGROUP_SIZE = 48; // fits in 1.5 words
280 
281 
282 // Our iterator as simple as iterators can be: basically it's just
283 // the index into our table. Dereference, the only complicated
284 // thing, we punt to the table class. This just goes to show how
285 // much machinery STL requires to do even the most trivial tasks.
286 //
287 // A NOTE ON ASSIGNING:
288 // A sparse table does not actually allocate memory for entries
289 // that are not filled. Because of this, it becomes complicated
290 // to have a non-const iterator: we don't know, if the iterator points
291 // to a not-filled bucket, whether you plan to fill it with something
292 // or whether you plan to read its value (in which case you'll get
293 // the default bucket value). Therefore, while we can define const
294 // operations in a pretty 'normal' way, for non-const operations, we
295 // define something that returns a helper object with operator= and
296 // operator& that allocate a bucket lazily. We use this for table[]
297 // and also for regular table iterators.
298 
299 template <class tabletype>
301  public:
302  typedef typename tabletype::value_type value_type;
303  typedef typename tabletype::size_type size_type;
304  typedef typename tabletype::reference reference;
305  typedef typename tabletype::pointer pointer;
306 
308  : table(tbl), pos(p) { }
310  table->set(pos, val);
311  return *this;
312  }
313  operator value_type() { return table->get(pos); } // we look like a value
314  pointer operator& () { return &table->mutating_get(pos); }
315 
316  private:
317  tabletype* table;
319 };
320 
321 // Our iterator as simple as iterators can be: basically it's just
322 // the index into our table. Dereference, the only complicated
323 // thing, we punt to the table class. This just goes to show how
324 // much machinery STL requires to do even the most trivial tasks.
325 //
326 // By templatizing over tabletype, we have one iterator type which
327 // we can use for both sparsetables and sparsebins. In fact it
328 // works on any class that allows size() and operator[] (eg vector),
329 // as long as it does the standard STL typedefs too (eg value_type).
330 
331 template <class tabletype>
333  public:
335 
336  typedef std::random_access_iterator_tag iterator_category;
337  typedef typename tabletype::value_type value_type;
338  typedef typename tabletype::difference_type difference_type;
339  typedef typename tabletype::size_type size_type;
342 
343  // The "real" constructor
344  table_iterator(tabletype *tbl, size_type p)
345  : table(tbl), pos(p) { }
346  // The default constructor, used when I define vars of type table::iterator
347  table_iterator() : table(NULL), pos(0) { }
348  // The copy constructor, for when I say table::iterator foo = tbl.begin()
349  // The default destructor is fine; we don't define one
350  // The default operator= is fine; we don't define one
351 
352  // The main thing our iterator does is dereference. If the table entry
353  // we point to is empty, we return the default value type.
354  // This is the big different function from the const iterator.
357  }
358  pointer operator->() { return &(operator*()); }
359 
360  // Helper function to assert things are ok; eg pos is still in range
361  void check() const {
362  assert(table);
363  assert(pos <= table->size());
364  }
365 
366  // Arithmetic: we just do arithmetic on pos. We don't even need to
367  // do bounds checking, since STL doesn't consider that its job. :-)
368  iterator& operator+=(size_type t) { pos += t; check(); return *this; }
369  iterator& operator-=(size_type t) { pos -= t; check(); return *this; }
370  iterator& operator++() { ++pos; check(); return *this; }
371  iterator& operator--() { --pos; check(); return *this; }
372  iterator operator++(int) { iterator tmp(*this); // for x++
373  ++pos; check(); return tmp; }
374  iterator operator--(int) { iterator tmp(*this); // for x--
375  --pos; check(); return tmp; }
377  tmp += i; return tmp; }
379  tmp -= i; return tmp; }
380  difference_type operator-(iterator it) const { // for "x = it2 - it"
381  assert(table == it.table);
382  return pos - it.pos;
383  }
385  return *(*this + n); // simple though not totally efficient
386  }
387 
388  // Comparisons.
389  bool operator==(const iterator& it) const {
390  return table == it.table && pos == it.pos;
391  }
392  bool operator<(const iterator& it) const {
393  assert(table == it.table); // life is bad bad bad otherwise
394  return pos < it.pos;
395  }
396  bool operator!=(const iterator& it) const { return !(*this == it); }
397  bool operator<=(const iterator& it) const { return !(it < *this); }
398  bool operator>(const iterator& it) const { return it < *this; }
399  bool operator>=(const iterator& it) const { return !(*this < it); }
400 
401  // Here's the info we actually need to be an iterator
402  tabletype *table; // so we can dereference and bounds-check
403  size_type pos; // index into the table
404 };
405 
406 // support for "3 + iterator" has to be defined outside the class, alas
407 template<class T>
409  table_iterator<T> it) {
410  return it + i; // so people can say it2 = 3 + it
411 }
412 
413 template <class tabletype>
415  public:
418 
419  typedef std::random_access_iterator_tag iterator_category;
420  typedef typename tabletype::value_type value_type;
421  typedef typename tabletype::difference_type difference_type;
422  typedef typename tabletype::size_type size_type;
423  typedef typename tabletype::const_reference reference; // we're const-only
424  typedef typename tabletype::const_pointer pointer;
425 
426  // The "real" constructor
427  const_table_iterator(const tabletype *tbl, size_type p)
428  : table(tbl), pos(p) { }
429  // The default constructor, used when I define vars of type table::iterator
430  const_table_iterator() : table(NULL), pos(0) { }
431  // The copy constructor, for when I say table::iterator foo = tbl.begin()
432  // Also converts normal iterators to const iterators
434  : table(from.table), pos(from.pos) { }
435  // The default destructor is fine; we don't define one
436  // The default operator= is fine; we don't define one
437 
438  // The main thing our iterator does is dereference. If the table entry
439  // we point to is empty, we return the default value type.
440  reference operator*() const { return (*table)[pos]; }
441  pointer operator->() const { return &(operator*()); }
442 
443  // Helper function to assert things are ok; eg pos is still in range
444  void check() const {
445  assert(table);
446  assert(pos <= table->size());
447  }
448 
449  // Arithmetic: we just do arithmetic on pos. We don't even need to
450  // do bounds checking, since STL doesn't consider that its job. :-)
451  const_iterator& operator+=(size_type t) { pos += t; check(); return *this; }
452  const_iterator& operator-=(size_type t) { pos -= t; check(); return *this; }
453  const_iterator& operator++() { ++pos; check(); return *this; }
454  const_iterator& operator--() { --pos; check(); return *this; }
455  const_iterator operator++(int) { const_iterator tmp(*this); // for x++
456  ++pos; check(); return tmp; }
457  const_iterator operator--(int) { const_iterator tmp(*this); // for x--
458  --pos; check(); return tmp; }
460  tmp += i; return tmp; }
462  tmp -= i; return tmp; }
463  difference_type operator-(const_iterator it) const { // for "x = it2 - it"
464  assert(table == it.table);
465  return pos - it.pos;
466  }
468  return *(*this + n); // simple though not totally efficient
469  }
470 
471  // Comparisons.
472  bool operator==(const const_iterator& it) const {
473  return table == it.table && pos == it.pos;
474  }
475  bool operator<(const const_iterator& it) const {
476  assert(table == it.table); // life is bad bad bad otherwise
477  return pos < it.pos;
478  }
479  bool operator!=(const const_iterator& it) const { return !(*this == it); }
480  bool operator<=(const const_iterator& it) const { return !(it < *this); }
481  bool operator>(const const_iterator& it) const { return it < *this; }
482  bool operator>=(const const_iterator& it) const { return !(*this < it); }
483 
484  // Here's the info we actually need to be an iterator
485  const tabletype *table; // so we can dereference and bounds-check
486  size_type pos; // index into the table
487 };
488 
489 // support for "3 + iterator" has to be defined outside the class, alas
490 template<class T>
494  return it + i; // so people can say it2 = 3 + it
495 }
496 
497 
498 // ---------------------------------------------------------------------------
499 
500 
501 /*
502 // This is a 2-D iterator. You specify a begin and end over a list
503 // of *containers*. We iterate over each container by iterating over
504 // it. It's actually simple:
505 // VECTOR.begin() VECTOR[0].begin() --------> VECTOR[0].end() ---,
506 // | ________________________________________________/
507 // | \_> VECTOR[1].begin() --------> VECTOR[1].end() -,
508 // | ___________________________________________________/
509 // v \_> ......
510 // VECTOR.end()
511 //
512 // It's impossible to do random access on one of these things in constant
513 // time, so it's just a bidirectional iterator.
514 //
515 // Unfortunately, because we need to use this for a non-empty iterator,
516 // we use nonempty_begin() and nonempty_end() instead of begin() and end()
517 // (though only going across, not down).
518 */
519 
520 #define TWOD_BEGIN_ nonempty_begin
521 #define TWOD_END_ nonempty_end
522 #define TWOD_ITER_ nonempty_iterator
523 #define TWOD_CONST_ITER_ const_nonempty_iterator
524 
525 template <class containertype>
527  public:
529 
530  typedef std::bidirectional_iterator_tag iterator_category;
531  // apparently some versions of VC++ have trouble with two ::'s in a typename
532  typedef typename containertype::value_type _tmp_vt;
533  typedef typename _tmp_vt::value_type value_type;
534  typedef typename _tmp_vt::difference_type difference_type;
535  typedef typename _tmp_vt::reference reference;
536  typedef typename _tmp_vt::pointer pointer;
537 
538  // The "real" constructor. begin and end specify how many rows we have
539  // (in the diagram above); we always iterate over each row completely.
540  two_d_iterator(typename containertype::iterator begin,
541  typename containertype::iterator end,
542  typename containertype::iterator curr)
543  : row_begin(begin), row_end(end), row_current(curr), col_current() {
544  if ( row_current != row_end ) {
545  col_current = row_current->TWOD_BEGIN_();
546  advance_past_end(); // in case cur->begin() == cur->end()
547  }
548  }
549  // If you want to start at an arbitrary place, you can, I guess
550  two_d_iterator(typename containertype::iterator begin,
551  typename containertype::iterator end,
552  typename containertype::iterator curr,
553  typename containertype::value_type::TWOD_ITER_ col)
554  : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
555  advance_past_end(); // in case cur->begin() == cur->end()
556  }
557  // The default constructor, used when I define vars of type table::iterator
559  // The default destructor is fine; we don't define one
560  // The default operator= is fine; we don't define one
561 
562  // Happy dereferencer
563  reference operator*() const { return *col_current; }
564  pointer operator->() const { return &(operator*()); }
565 
566  // Arithmetic: we just do arithmetic on pos. We don't even need to
567  // do bounds checking, since STL doesn't consider that its job. :-)
568  // NOTE: this is not amortized constant time! What do we do about it?
569  void advance_past_end() { // used when col_current points to end()
570  while ( col_current == row_current->TWOD_END_() ) { // end of current row
571  ++row_current; // go to beginning of next
572  if ( row_current != row_end ) // col is irrelevant at end
573  col_current = row_current->TWOD_BEGIN_();
574  else
575  break; // don't go past row_end
576  }
577  }
578 
580  assert(row_current != row_end); // how to ++ from there?
581  ++col_current;
582  advance_past_end(); // in case col_current is at end()
583  return *this;
584  }
586  while ( row_current == row_end ||
587  col_current == row_current->TWOD_BEGIN_() ) {
589  --row_current;
590  col_current = row_current->TWOD_END_(); // this is 1 too far
591  }
592  --col_current;
593  return *this;
594  }
595  iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
596  iterator operator--(int) { iterator tmp(*this); --*this; return tmp; }
597 
598 
599  // Comparisons.
600  bool operator==(const iterator& it) const {
601  return ( row_begin == it.row_begin &&
602  row_end == it.row_end &&
603  row_current == it.row_current &&
604  (row_current == row_end || col_current == it.col_current) );
605  }
606  bool operator!=(const iterator& it) const { return !(*this == it); }
607 
608 
609  // Here's the info we actually need to be an iterator
610  // These need to be public so we convert from iterator to const_iterator
611  typename containertype::iterator row_begin, row_end, row_current;
612  typename containertype::value_type::TWOD_ITER_ col_current;
613 };
614 
615 // The same thing again, but this time const. :-(
616 template <class containertype>
618  public:
620 
621  typedef std::bidirectional_iterator_tag iterator_category;
622  // apparently some versions of VC++ have trouble with two ::'s in a typename
623  typedef typename containertype::value_type _tmp_vt;
624  typedef typename _tmp_vt::value_type value_type;
625  typedef typename _tmp_vt::difference_type difference_type;
626  typedef typename _tmp_vt::const_reference reference;
627  typedef typename _tmp_vt::const_pointer pointer;
628 
629  const_two_d_iterator(typename containertype::const_iterator begin,
630  typename containertype::const_iterator end,
631  typename containertype::const_iterator curr)
632  : row_begin(begin), row_end(end), row_current(curr), col_current() {
633  if ( curr != end ) {
634  col_current = curr->TWOD_BEGIN_();
635  advance_past_end(); // in case cur->begin() == cur->end()
636  }
637  }
638  const_two_d_iterator(typename containertype::const_iterator begin,
639  typename containertype::const_iterator end,
640  typename containertype::const_iterator curr,
641  typename containertype::value_type::TWOD_CONST_ITER_ col)
642  : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
643  advance_past_end(); // in case cur->begin() == cur->end()
644  }
647  }
648  // Need this explicitly so we can convert normal iterators to const iterators
651  col_current(it.col_current) { }
652 
653  typename containertype::const_iterator row_begin, row_end, row_current;
654  typename containertype::value_type::TWOD_CONST_ITER_ col_current;
655 
656 
657  // EVERYTHING FROM HERE DOWN IS THE SAME AS THE NON-CONST ITERATOR
658  reference operator*() const { return *col_current; }
659  pointer operator->() const { return &(operator*()); }
660 
661  void advance_past_end() { // used when col_current points to end()
662  while ( col_current == row_current->TWOD_END_() ) { // end of current row
663  ++row_current; // go to beginning of next
664  if ( row_current != row_end ) // col is irrelevant at end
665  col_current = row_current->TWOD_BEGIN_();
666  else
667  break; // don't go past row_end
668  }
669  }
671  assert(row_current != row_end); // how to ++ from there?
672  ++col_current;
673  advance_past_end(); // in case col_current is at end()
674  return *this;
675  }
677  while ( row_current == row_end ||
678  col_current == row_current->TWOD_BEGIN_() ) {
680  --row_current;
681  col_current = row_current->TWOD_END_(); // this is 1 too far
682  }
683  --col_current;
684  return *this;
685  }
686  iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
687  iterator operator--(int) { iterator tmp(*this); --*this; return tmp; }
688 
689  bool operator==(const iterator& it) const {
690  return ( row_begin == it.row_begin &&
691  row_end == it.row_end &&
692  row_current == it.row_current &&
693  (row_current == row_end || col_current == it.col_current) );
694  }
695  bool operator!=(const iterator& it) const { return !(*this == it); }
696 };
697 
698 // We provide yet another version, to be as frugal with memory as
699 // possible. This one frees each block of memory as it finishes
700 // iterating over it. By the end, the entire table is freed.
701 // For understandable reasons, you can only iterate over it once,
702 // which is why it's an input iterator
703 template <class containertype>
705  public:
707 
708  typedef std::input_iterator_tag iterator_category;
709  // apparently some versions of VC++ have trouble with two ::'s in a typename
710  typedef typename containertype::value_type _tmp_vt;
711  typedef typename _tmp_vt::value_type value_type;
712  typedef typename _tmp_vt::difference_type difference_type;
713  typedef typename _tmp_vt::reference reference;
714  typedef typename _tmp_vt::pointer pointer;
715 
716  destructive_two_d_iterator(typename containertype::iterator begin,
717  typename containertype::iterator end,
718  typename containertype::iterator curr)
719  : row_begin(begin), row_end(end), row_current(curr), col_current() {
720  if ( curr != end ) {
721  col_current = curr->TWOD_BEGIN_();
722  advance_past_end(); // in case cur->begin() == cur->end()
723  }
724  }
725  destructive_two_d_iterator(typename containertype::iterator begin,
726  typename containertype::iterator end,
727  typename containertype::iterator curr,
728  typename containertype::value_type::TWOD_ITER_ col)
729  : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
730  advance_past_end(); // in case cur->begin() == cur->end()
731  }
734  }
735 
736  typename containertype::iterator row_begin, row_end, row_current;
737  typename containertype::value_type::TWOD_ITER_ col_current;
738 
739  // This is the part that destroys
740  void advance_past_end() { // used when col_current points to end()
741  while ( col_current == row_current->TWOD_END_() ) { // end of current row
742  row_current->clear(); // the destructive part
743  // It would be nice if we could decrement sparsetable->num_buckets here
744  ++row_current; // go to beginning of next
745  if ( row_current != row_end ) // col is irrelevant at end
746  col_current = row_current->TWOD_BEGIN_();
747  else
748  break; // don't go past row_end
749  }
750  }
751 
752  // EVERYTHING FROM HERE DOWN IS THE SAME AS THE REGULAR ITERATOR
753  reference operator*() const { return *col_current; }
754  pointer operator->() const { return &(operator*()); }
755 
757  assert(row_current != row_end); // how to ++ from there?
758  ++col_current;
759  advance_past_end(); // in case col_current is at end()
760  return *this;
761  }
762  iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
763 
764  bool operator==(const iterator& it) const {
765  return ( row_begin == it.row_begin &&
766  row_end == it.row_end &&
767  row_current == it.row_current &&
768  (row_current == row_end || col_current == it.col_current) );
769  }
770  bool operator!=(const iterator& it) const { return !(*this == it); }
771 };
772 
773 #undef TWOD_BEGIN_
774 #undef TWOD_END_
775 #undef TWOD_ITER_
776 #undef TWOD_CONST_ITER_
777 
778 
779 
780 
781 // SPARSE-TABLE
782 // ------------
783 // The idea is that a table with (logically) t buckets is divided
784 // into t/M *groups* of M buckets each. (M is a constant set in
785 // GROUP_SIZE for efficiency.) Each group is stored sparsely.
786 // Thus, inserting into the table causes some array to grow, which is
787 // slow but still constant time. Lookup involves doing a
788 // logical-position-to-sparse-position lookup, which is also slow but
789 // constant time. The larger M is, the slower these operations are
790 // but the less overhead (slightly).
791 //
792 // To store the sparse array, we store a bitmap B, where B[i] = 1 iff
793 // bucket i is non-empty. Then to look up bucket i we really look up
794 // array[# of 1s before i in B]. This is constant time for fixed M.
795 //
796 // Terminology: the position of an item in the overall table (from
797 // 1 .. t) is called its "location." The logical position in a group
798 // (from 1 .. M ) is called its "position." The actual location in
799 // the array (from 1 .. # of non-empty buckets in the group) is
800 // called its "offset."
801 
802 template <class T, u_int16_t GROUP_SIZE, class Alloc>
803 class sparsegroup {
804  private:
805  typedef typename Alloc::template rebind<T>::other value_alloc_type;
806 
807  public:
808  // Basic types
809  typedef T value_type;
810  typedef Alloc allocator_type;
811  typedef typename value_alloc_type::reference reference;
812  typedef typename value_alloc_type::const_reference const_reference;
813  typedef typename value_alloc_type::pointer pointer;
814  typedef typename value_alloc_type::const_pointer const_pointer;
815 
821  typedef u_int16_t size_type; // max # of buckets
823  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
824  typedef std::reverse_iterator<iterator> reverse_iterator; // from iterator.h
825 
826  // These are our special iterators, that go over non-empty buckets in a
827  // group. These aren't const-only because you can change non-empty bcks.
830  typedef std::reverse_iterator<nonempty_iterator> reverse_nonempty_iterator;
831  typedef std::reverse_iterator<const_nonempty_iterator> const_reverse_nonempty_iterator;
832 
833  // Iterator functions
834  iterator begin() { return iterator(this, 0); }
835  const_iterator begin() const { return const_iterator(this, 0); }
836  iterator end() { return iterator(this, size()); }
837  const_iterator end() const { return const_iterator(this, size()); }
842 
843  // We'll have versions for our special non-empty iterator too
847  return group + settings.num_buckets;
848  }
850  return group + settings.num_buckets;
851  }
854  }
857  }
860  }
863  }
864 
865 
866  // This gives us the "default" value to return for an empty bucket.
867  // We just use the default constructor on T, the template type
869  static value_type defaultval = value_type();
870  return defaultval;
871  }
872 
873 
874  private:
875  // We need to do all this bit manipulation, of course. ick
876  static size_type charbit(size_type i) { return i >> 3; }
877  static size_type modbit(size_type i) { return 1 << (i&7); }
878  int bmtest(size_type i) const { return bitmap[charbit(i)] & modbit(i); }
879  void bmset(size_type i) { bitmap[charbit(i)] |= modbit(i); }
880  void bmclear(size_type i) { bitmap[charbit(i)] &= ~modbit(i); }
881 
883  pointer retval = settings.allocate(n);
884  if (retval == NULL) {
885  // We really should use PRIuS here, but I don't want to have to add
886  // a whole new configure option, with concomitant macro namespace
887  // pollution, just to print this (unlikely) error message. So I cast.
888  fprintf(stderr, "sparsehash FATAL ERROR: failed to allocate %lu groups\n",
889  static_cast<unsigned long>(n));
890  exit(1);
891  }
892  return retval;
893  }
894 
895  void free_group() {
896  if (!group) return;
897  pointer end_it = group + settings.num_buckets;
898  for (pointer p = group; p != end_it; ++p)
899  p->~value_type();
900  settings.deallocate(group, settings.num_buckets);
901  group = NULL;
902  }
903 
904  static size_type bits_in_char(unsigned char c) {
905  // We could make these ints. The tradeoff is size (eg does it overwhelm
906  // the cache?) vs efficiency in referencing sub-word-sized array elements.
907  static const char bits_in[256] = {
908  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
909  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
910  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
911  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
912  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
913  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
914  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
915  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
916  1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
917  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
918  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
919  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
920  2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
921  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
922  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
923  4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
924  };
925  return bits_in[c];
926  }
927 
928  public: // get_iter() in sparsetable needs it
929  // We need a small function that tells us how many set bits there are
930  // in positions 0..i-1 of the bitmap. It uses a big table.
931  // We make it static so templates don't allocate lots of these tables.
932  // There are lots of ways to do this calculation (called 'popcount').
933  // The 8-bit table lookup is one of the fastest, though this
934  // implementation suffers from not doing any loop unrolling. See, eg,
935  // http://www.dalkescientific.com/writings/diary/archive/2008/07/03/hakmem_and_other_popcounts.html
936  // http://gurmeetsingh.wordpress.com/2008/08/05/fast-bit-counting-routines/
937  static size_type pos_to_offset(const unsigned char *bm, size_type pos) {
938  size_type retval = 0;
939 
940  // [Note: condition pos > 8 is an optimization; convince yourself we
941  // give exactly the same result as if we had pos >= 8 here instead.]
942  for ( ; pos > 8; pos -= 8 ) // bm[0..pos/8-1]
943  retval += bits_in_char(*bm++); // chars we want *all* bits in
944  return retval + bits_in_char(*bm & ((1 << pos)-1)); // char including pos
945  }
946 
947  size_type pos_to_offset(size_type pos) const { // not static but still const
948  return pos_to_offset(bitmap, pos);
949  }
950 
951  // Returns the (logical) position in the bm[] array, i, such that
952  // bm[i] is the offset-th set bit in the array. It is the inverse
953  // of pos_to_offset. get_pos() uses this function to find the index
954  // of an nonempty_iterator in the table. Bit-twiddling from
955  // http://hackersdelight.org/basics.pdf
956  static size_type offset_to_pos(const unsigned char *bm, size_type offset) {
957  size_type retval = 0;
958  // This is sizeof(this->bitmap).
959  const size_type group_size = (GROUP_SIZE-1) / 8 + 1;
960  for (size_type i = 0; i < group_size; i++) { // forward scan
961  const size_type pop_count = bits_in_char(*bm);
962  if (pop_count > offset) {
963  unsigned char last_bm = *bm;
964  for (; offset > 0; offset--) {
965  last_bm &= (last_bm-1); // remove right-most set bit
966  }
967  // Clear all bits to the left of the rightmost bit (the &),
968  // and then clear the rightmost bit but set all bits to the
969  // right of it (the -1).
970  last_bm = (last_bm & -last_bm) - 1;
971  retval += bits_in_char(last_bm);
972  return retval;
973  }
974  offset -= pop_count;
975  retval += 8;
976  bm++;
977  }
978  return retval;
979  }
980 
982  return offset_to_pos(bitmap, offset);
983  }
984 
985 
986  public:
987  // Constructors -- default and copy -- and destructor
990  memset(bitmap, 0, sizeof(bitmap));
991  }
993  if ( settings.num_buckets ) {
995  std::uninitialized_copy(x.group, x.group + x.settings.num_buckets, group);
996  }
997  memcpy(bitmap, x.bitmap, sizeof(bitmap));
998  }
1000 
1001  // Operator= is just like the copy constructor, I guess
1002  // TODO(austern): Make this exception safe. Handle exceptions in value_type's
1003  // copy constructor.
1005  if ( &x == this ) return *this; // x = x
1006  if ( x.settings.num_buckets == 0 ) {
1007  free_group();
1008  } else {
1010  std::uninitialized_copy(x.group, x.group + x.settings.num_buckets, p);
1011  free_group();
1012  group = p;
1013  }
1014  memcpy(bitmap, x.bitmap, sizeof(bitmap));
1016  return *this;
1017  }
1018 
1019  // Many STL algorithms use swap instead of copy constructors
1020  void swap(sparsegroup& x) {
1021  std::swap(group, x.group); // defined in <algorithm>
1022  for ( int i = 0; i < sizeof(bitmap) / sizeof(*bitmap); ++i )
1023  std::swap(bitmap[i], x.bitmap[i]); // swap not defined on arrays
1025  // we purposefully don't swap the allocator, which may not be swap-able
1026  }
1027 
1028  // It's always nice to be able to clear a table without deallocating it
1029  void clear() {
1030  free_group();
1031  memset(bitmap, 0, sizeof(bitmap));
1032  settings.num_buckets = 0;
1033  }
1034 
1035  // Functions that tell you about size. Alas, these aren't so useful
1036  // because our table is always fixed size.
1037  size_type size() const { return GROUP_SIZE; }
1038  size_type max_size() const { return GROUP_SIZE; }
1039  bool empty() const { return false; }
1040  // We also may want to know how many *used* buckets there are
1042 
1043 
1044  // get()/set() are explicitly const/non-const. You can use [] if
1045  // you want something that can be either (potentially more expensive).
1047  if ( bmtest(i) ) // bucket i is occupied
1048  return group[pos_to_offset(bitmap, i)];
1049  else
1050  return default_value(); // return the default reference
1051  }
1052 
1053  // TODO(csilvers): make protected + friend
1054  // This is used by sparse_hashtable to get an element from the table
1055  // when we know it exists.
1057  assert(bmtest(i));
1058  return group[pos_to_offset(bitmap, i)];
1059  }
1060 
1061  // TODO(csilvers): make protected + friend
1062  reference mutating_get(size_type i) { // fills bucket i before getting
1063  if ( !bmtest(i) )
1064  set(i, default_value());
1065  return group[pos_to_offset(bitmap, i)];
1066  }
1067 
1068  // Syntactic sugar. It's easy to return a const reference. To
1069  // return a non-const reference, we need to use the assigner adaptor.
1071  return get(i);
1072  }
1073 
1075  return element_adaptor(this, i);
1076  }
1077 
1078  private:
1079  // Create space at group[offset], assuming value_type has trivial
1080  // copy constructor and destructor, and the allocator_type is
1081  // the default libc_allocator_with_alloc. (Really, we want it to have
1082  // "trivial move", because that's what realloc and memmove both do.
1083  // But there's no way to capture that using type_traits, so we
1084  // pretend that move(x, y) is equivalent to "x.~T(); new(x) T(y);"
1085  // which is pretty much correct, if a bit conservative.)
1088  // This is equivalent to memmove(), but faster on my Intel P4,
1089  // at least with gcc4.1 -O2 / glibc 2.3.6.
1090  for (size_type i = settings.num_buckets; i > offset; --i)
1091  memcpy(group + i, group + i-1, sizeof(*group));
1092  }
1093 
1094  // Create space at group[offset], without special assumptions about value_type
1095  // and allocator_type.
1097  // This is valid because 0 <= offset <= num_buckets
1099  std::uninitialized_copy(group, group + offset, p);
1100  std::uninitialized_copy(group + offset, group + settings.num_buckets,
1101  p + offset + 1);
1102  free_group();
1103  group = p;
1104  }
1105 
1106  public:
1107  // This returns a reference to the inserted item (which is a copy of val).
1108  // TODO(austern): Make this exception safe: handle exceptions from
1109  // value_type's copy constructor.
1111  size_type offset = pos_to_offset(bitmap, i); // where we'll find (or insert)
1112  if ( bmtest(i) ) {
1113  // Delete the old value, which we're replacing with the new one
1114  group[offset].~value_type();
1115  } else {
1116  typedef base::integral_constant<bool,
1117  (base::has_trivial_copy<value_type>::value &&
1118  base::has_trivial_destructor<value_type>::value &&
1119  base::is_same<
1122  realloc_and_memmove_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)"
1123  set_aux(offset, realloc_and_memmove_ok());
1125  bmset(i);
1126  }
1127  // This does the actual inserting. Since we made the array using
1128  // malloc, we use "placement new" to just call the constructor.
1129  new(&group[offset]) value_type(val);
1130  return group[offset];
1131  }
1132 
1133  // We let you see if a bucket is non-empty without retrieving it
1134  bool test(size_type i) const {
1135  return bmtest(i) != 0;
1136  }
1137  bool test(iterator pos) const {
1138  return bmtest(pos.pos) != 0;
1139  }
1140 
1141  private:
1142  // Shrink the array, assuming value_type has trivial copy
1143  // constructor and destructor, and the allocator_type is the default
1144  // libc_allocator_with_alloc. (Really, we want it to have "trivial
1145  // move", because that's what realloc and memmove both do. But
1146  // there's no way to capture that using type_traits, so we pretend
1147  // that move(x, y) is equivalent to ""x.~T(); new(x) T(y);"
1148  // which is pretty much correct, if a bit conservative.)
1150  // This isn't technically necessary, since we know we have a
1151  // trivial destructor, but is a cheap way to get a bit more safety.
1152  group[offset].~value_type();
1153  // This is equivalent to memmove(), but faster on my Intel P4,
1154  // at lesat with gcc4.1 -O2 / glibc 2.3.6.
1156  for (size_type i = offset; i < settings.num_buckets-1; ++i)
1157  memcpy(group + i, group + i+1, sizeof(*group)); // hopefully inlined!
1159  }
1160 
1161  // Shrink the array, without any special assumptions about value_type and
1162  // allocator_type.
1164  // This is valid because 0 <= offset < num_buckets. Note the inequality.
1166  std::uninitialized_copy(group, group + offset, p);
1167  std::uninitialized_copy(group + offset + 1, group + settings.num_buckets,
1168  p + offset);
1169  free_group();
1170  group = p;
1171  }
1172 
1173  public:
1174  // This takes the specified elements out of the group. This is
1175  // "undefining", rather than "clearing".
1176  // TODO(austern): Make this exception safe: handle exceptions from
1177  // value_type's copy constructor.
1178  void erase(size_type i) {
1179  if ( bmtest(i) ) { // trivial to erase empty bucket
1180  size_type offset = pos_to_offset(bitmap,i); // where we'll find (or insert)
1181  if ( settings.num_buckets == 1 ) {
1182  free_group();
1183  group = NULL;
1184  } else {
1185  typedef base::integral_constant<bool,
1186  (base::has_trivial_copy<value_type>::value &&
1187  base::has_trivial_destructor<value_type>::value &&
1188  base::is_same<
1191  realloc_and_memmove_ok; // pretend mv(x,y) == "x.~T(); new(x) T(y)"
1192  erase_aux(offset, realloc_and_memmove_ok());
1193  }
1195  bmclear(i);
1196  }
1197  }
1198 
1199  void erase(iterator pos) {
1200  erase(pos.pos);
1201  }
1202 
1203  void erase(iterator start_it, iterator end_it) {
1204  // This could be more efficient, but to do so we'd need to make
1205  // bmclear() clear a range of indices. Doesn't seem worth it.
1206  for ( ; start_it != end_it; ++start_it )
1207  erase(start_it);
1208  }
1209 
1210 
1211  // I/O
1212  // We support reading and writing groups to disk. We don't store
1213  // the actual array contents (which we don't know how to store),
1214  // just the bitmap and size. Meant to be used with table I/O.
1215 
1216  template <typename OUTPUT> bool write_metadata(OUTPUT *fp) const {
1217  // we explicitly set to u_int16_t
1218  assert(sizeof(settings.num_buckets) == 2);
1220  2) )
1221  return false;
1222  if ( !sparsehash_internal::write_data(fp, bitmap, sizeof(bitmap)) )
1223  return false;
1224  return true;
1225  }
1226 
1227  // Reading destroys the old group contents! Returns true if all was ok.
1228  template <typename INPUT> bool read_metadata(INPUT *fp) {
1229  clear();
1231  2) )
1232  return false;
1233  if ( !sparsehash_internal::read_data(fp, bitmap, sizeof(bitmap)) )
1234  return false;
1235  // We'll allocate the space, but we won't fill it: it will be
1236  // left as uninitialized raw memory.
1238  return true;
1239  }
1240 
1241  // Again, only meaningful if value_type is a POD.
1242  template <typename INPUT> bool read_nopointer_data(INPUT *fp) {
1243  for ( nonempty_iterator it = nonempty_begin();
1244  it != nonempty_end(); ++it ) {
1245  if ( !sparsehash_internal::read_data(fp, &(*it), sizeof(*it)) )
1246  return false;
1247  }
1248  return true;
1249  }
1250 
1251  // If your keys and values are simple enough, we can write them
1252  // to disk for you. "simple enough" means POD and no pointers.
1253  // However, we don't try to normalize endianness.
1254  template <typename OUTPUT> bool write_nopointer_data(OUTPUT *fp) const {
1256  it != nonempty_end(); ++it ) {
1257  if ( !sparsehash_internal::write_data(fp, &(*it), sizeof(*it)) )
1258  return false;
1259  }
1260  return true;
1261  }
1262 
1263 
1264  // Comparisons. We only need to define == and < -- we get
1265  // != > <= >= via relops.h (which we happily included above).
1266  // Note the comparisons are pretty arbitrary: we compare
1267  // values of the first index that isn't equal (using default
1268  // value for empty buckets).
1269  bool operator==(const sparsegroup& x) const {
1270  return ( settings.num_buckets == x.settings.num_buckets &&
1271  memcmp(bitmap, x.bitmap, sizeof(bitmap)) == 0 &&
1272  std::equal(begin(), end(), x.begin()) ); // from <algorithm>
1273  }
1274 
1275  bool operator<(const sparsegroup& x) const { // also from <algorithm>
1276  return std::lexicographical_compare(begin(), end(), x.begin(), x.end());
1277  }
1278  bool operator!=(const sparsegroup& x) const { return !(*this == x); }
1279  bool operator<=(const sparsegroup& x) const { return !(x < *this); }
1280  bool operator>(const sparsegroup& x) const { return x < *this; }
1281  bool operator>=(const sparsegroup& x) const { return !(*this < x); }
1282 
1283  private:
1284  template <class A>
1285  class alloc_impl : public A {
1286  public:
1287  typedef typename A::pointer pointer;
1288  typedef typename A::size_type size_type;
1289 
1290  // Convert a normal allocator to one that has realloc_or_die()
1291  alloc_impl(const A& a) : A(a) { }
1292 
1293  // realloc_or_die should only be used when using the default
1294  // allocator (libc_allocator_with_realloc).
1296  fprintf(stderr, "realloc_or_die is only supported for "
1297  "libc_allocator_with_realloc\n");
1298  exit(1);
1299  return NULL;
1300  }
1301  };
1302 
1303  // A template specialization of alloc_impl for
1304  // libc_allocator_with_realloc that can handle realloc_or_die.
1305  template <class A>
1307  : public libc_allocator_with_realloc<A> {
1308  public:
1311 
1313  : libc_allocator_with_realloc<A>(a) { }
1314 
1316  pointer retval = this->reallocate(ptr, n);
1317  if (retval == NULL) {
1318  fprintf(stderr, "sparsehash: FATAL ERROR: failed to reallocate "
1319  "%lu elements for ptr %p", static_cast<unsigned long>(n), (void*) ptr);
1320  exit(1);
1321  }
1322  return retval;
1323  }
1324  };
1325 
1326  // Package allocator with num_buckets to eliminate memory needed for the
1327  // zero-size allocator.
1328  // If new fields are added to this class, we should add them to
1329  // operator= and swap.
1330  class Settings : public alloc_impl<value_alloc_type> {
1331  public:
1334  Settings(const Settings& s)
1336 
1337  u_int16_t num_buckets; // limits GROUP_SIZE to 64K
1338  };
1339 
1340  // The actual data
1341  pointer group; // (small) array of T's
1342  Settings settings; // allocator and num_buckets
1343  unsigned char bitmap[(GROUP_SIZE-1)/8 + 1]; // fancy math is so we round up
1344 };
1345 
1346 // We need a global swap as well
1347 template <class T, u_int16_t GROUP_SIZE, class Alloc>
1350  x.swap(y);
1351 }
1352 
1353 // ---------------------------------------------------------------------------
1354 
1355 
1356 template <class T, u_int16_t GROUP_SIZE = DEFAULT_SPARSEGROUP_SIZE,
1357  class Alloc = libc_allocator_with_realloc<T> >
1359  private:
1360  typedef typename Alloc::template rebind<T>::other value_alloc_type;
1361  typedef typename Alloc::template rebind<
1363 
1364  public:
1365  // Basic types
1366  typedef T value_type; // stolen from stl_vector.h
1367  typedef Alloc allocator_type;
1368  typedef typename value_alloc_type::size_type size_type;
1369  typedef typename value_alloc_type::difference_type difference_type;
1370  typedef typename value_alloc_type::reference reference;
1371  typedef typename value_alloc_type::const_reference const_reference;
1372  typedef typename value_alloc_type::pointer pointer;
1373  typedef typename value_alloc_type::const_pointer const_pointer;
1379  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1380  typedef std::reverse_iterator<iterator> reverse_iterator; // from iterator.h
1381 
1382  // These are our special iterators, that go over non-empty buckets in a
1383  // table. These aren't const only because you can change non-empty bcks.
1384  typedef two_d_iterator< std::vector< sparsegroup<value_type, GROUP_SIZE,
1386  vector_alloc> >
1388  typedef const_two_d_iterator< std::vector< sparsegroup<value_type,
1389  GROUP_SIZE,
1391  vector_alloc> >
1393  typedef std::reverse_iterator<nonempty_iterator> reverse_nonempty_iterator;
1394  typedef std::reverse_iterator<const_nonempty_iterator> const_reverse_nonempty_iterator;
1395  // Another special iterator: it frees memory as it iterates (used to resize)
1396  typedef destructive_two_d_iterator< std::vector< sparsegroup<value_type,
1397  GROUP_SIZE,
1399  vector_alloc> >
1401 
1402  // Iterator functions
1403  iterator begin() { return iterator(this, 0); }
1404  const_iterator begin() const { return const_iterator(this, 0); }
1405  iterator end() { return iterator(this, size()); }
1406  const_iterator end() const { return const_iterator(this, size()); }
1411 
1412  // Versions for our special non-empty iterator
1414  return nonempty_iterator(groups.begin(), groups.end(), groups.begin());
1415  }
1417  return const_nonempty_iterator(groups.begin(),groups.end(), groups.begin());
1418  }
1420  return nonempty_iterator(groups.begin(), groups.end(), groups.end());
1421  }
1423  return const_nonempty_iterator(groups.begin(), groups.end(), groups.end());
1424  }
1427  }
1430  }
1433  }
1436  }
1438  return destructive_iterator(groups.begin(), groups.end(), groups.begin());
1439  }
1441  return destructive_iterator(groups.begin(), groups.end(), groups.end());
1442  }
1443 
1445  typedef std::vector<group_type, vector_alloc > group_vector_type;
1446 
1447  typedef typename group_vector_type::reference GroupsReference;
1448  typedef typename group_vector_type::const_reference GroupsConstReference;
1449  typedef typename group_vector_type::iterator GroupsIterator;
1450  typedef typename group_vector_type::const_iterator GroupsConstIterator;
1451 
1452  // How to deal with the proper group
1453  static size_type num_groups(size_type num) { // how many to hold num buckets
1454  return num == 0 ? 0 : ((num-1) / GROUP_SIZE) + 1;
1455  }
1456 
1458  return static_cast<u_int16_t>(i % GROUP_SIZE);
1459  }
1461  return i / GROUP_SIZE;
1462  }
1464  return groups[group_num(i)];
1465  }
1467  return groups[group_num(i)];
1468  }
1469 
1470  public:
1471  // Constructors -- default, normal (when you specify size), and copy
1472  explicit sparsetable(size_type sz = 0, Alloc alloc = Alloc())
1473  : groups(vector_alloc(alloc)), settings(alloc, sz) {
1474  groups.resize(num_groups(sz), group_type(settings));
1475  }
1476  // We can get away with using the default copy constructor,
1477  // and default destructor, and hence the default operator=. Huzzah!
1478 
1479  // Many STL algorithms use swap instead of copy constructors
1480  void swap(sparsetable& x) {
1481  std::swap(groups, x.groups); // defined in stl_algobase.h
1484  }
1485 
1486  // It's always nice to be able to clear a table without deallocating it
1487  void clear() {
1488  GroupsIterator group;
1489  for ( group = groups.begin(); group != groups.end(); ++group ) {
1490  group->clear();
1491  }
1492  settings.num_buckets = 0;
1493  }
1494 
1495  // ACCESSOR FUNCTIONS for the things we templatize on, basically
1497  return allocator_type(settings);
1498  }
1499 
1500 
1501  // Functions that tell you about size.
1502  // NOTE: empty() is non-intuitive! It does not tell you the number
1503  // of not-empty buckets (use num_nonempty() for that). Instead
1504  // it says whether you've allocated any buckets or not.
1505  size_type size() const { return settings.table_size; }
1506  size_type max_size() const { return settings.max_size(); }
1507  bool empty() const { return settings.table_size == 0; }
1508  // We also may want to know how many *used* buckets there are
1510 
1511  // OK, we'll let you resize one of these puppies
1512  void resize(size_type new_size) {
1513  groups.resize(num_groups(new_size), group_type(settings));
1514  if ( new_size < settings.table_size) {
1515  // lower num_buckets, clear last group
1516  if ( pos_in_group(new_size) > 0 ) // need to clear inside last group
1517  groups.back().erase(groups.back().begin() + pos_in_group(new_size),
1518  groups.back().end());
1519  settings.num_buckets = 0; // refigure # of used buckets
1520  GroupsConstIterator group;
1521  for ( group = groups.begin(); group != groups.end(); ++group )
1522  settings.num_buckets += group->num_nonempty();
1523  }
1524  settings.table_size = new_size;
1525  }
1526 
1527 
1528  // We let you see if a bucket is non-empty without retrieving it
1529  bool test(size_type i) const {
1530  assert(i < settings.table_size);
1531  return which_group(i).test(pos_in_group(i));
1532  }
1533  bool test(iterator pos) const {
1534  return which_group(pos.pos).test(pos_in_group(pos.pos));
1535  }
1536  bool test(const_iterator pos) const {
1537  return which_group(pos.pos).test(pos_in_group(pos.pos));
1538  }
1539 
1540  // We only return const_references because it's really hard to
1541  // return something settable for empty buckets. Use set() instead.
1543  assert(i < settings.table_size);
1544  return which_group(i).get(pos_in_group(i));
1545  }
1546 
1547  // TODO(csilvers): make protected + friend
1548  // This is used by sparse_hashtable to get an element from the table
1549  // when we know it exists (because the caller has called test(i)).
1551  assert(i < settings.table_size);
1552  assert(test(i));
1553  return which_group(i).unsafe_get(pos_in_group(i));
1554  }
1555 
1556  // TODO(csilvers): make protected + friend element_adaptor
1557  reference mutating_get(size_type i) { // fills bucket i before getting
1558  assert(i < settings.table_size);
1559  typename group_type::size_type old_numbuckets = which_group(i).num_nonempty();
1560  reference retval = which_group(i).mutating_get(pos_in_group(i));
1561  settings.num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1562  return retval;
1563  }
1564 
1565  // Syntactic sugar. As in sparsegroup, the non-const version is harder
1567  return get(i);
1568  }
1569 
1571  return element_adaptor(this, i);
1572  }
1573 
1574  // Needed for hashtables, gets as a nonempty_iterator. Crashes for empty bcks
1576  assert(test(i)); // how can a nonempty_iterator point to an empty bucket?
1577  return const_nonempty_iterator(
1578  groups.begin(), groups.end(),
1579  groups.begin() + group_num(i),
1580  (groups[group_num(i)].nonempty_begin() +
1581  groups[group_num(i)].pos_to_offset(pos_in_group(i))));
1582  }
1583  // For nonempty we can return a non-const version
1585  assert(test(i)); // how can a nonempty_iterator point to an empty bucket?
1586  return nonempty_iterator(
1587  groups.begin(), groups.end(),
1588  groups.begin() + group_num(i),
1589  (groups[group_num(i)].nonempty_begin() +
1590  groups[group_num(i)].pos_to_offset(pos_in_group(i))));
1591  }
1592 
1593  // And the reverse transformation.
1595  difference_type current_row = it.row_current - it.row_begin;
1596  difference_type current_col = (it.col_current -
1597  groups[current_row].nonempty_begin());
1598  return ((current_row * GROUP_SIZE) +
1599  groups[current_row].offset_to_pos(current_col));
1600  }
1601 
1602 
1603  // This returns a reference to the inserted item (which is a copy of val)
1604  // The trick is to figure out whether we're replacing or inserting anew
1606  assert(i < settings.table_size);
1607  typename group_type::size_type old_numbuckets = which_group(i).num_nonempty();
1608  reference retval = which_group(i).set(pos_in_group(i), val);
1609  settings.num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1610  return retval;
1611  }
1612 
1613  // This takes the specified elements out of the table. This is
1614  // "undefining", rather than "clearing".
1615  void erase(size_type i) {
1616  assert(i < settings.table_size);
1617  typename group_type::size_type old_numbuckets = which_group(i).num_nonempty();
1618  which_group(i).erase(pos_in_group(i));
1619  settings.num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1620  }
1621 
1622  void erase(iterator pos) {
1623  erase(pos.pos);
1624  }
1625 
1626  void erase(iterator start_it, iterator end_it) {
1627  // This could be more efficient, but then we'd need to figure
1628  // out if we spanned groups or not. Doesn't seem worth it.
1629  for ( ; start_it != end_it; ++start_it )
1630  erase(start_it);
1631  }
1632 
1633 
1634  // We support reading and writing tables to disk. We don't store
1635  // the actual array contents (which we don't know how to store),
1636  // just the groups and sizes. Returns true if all went ok.
1637 
1638  private:
1639  // Every time the disk format changes, this should probably change too
1640  typedef unsigned long MagicNumberType;
1641  static const MagicNumberType MAGIC_NUMBER = 0x24687531;
1642 
1643  // Old versions of this code write all data in 32 bits. We need to
1644  // support these files as well as having support for 64-bit systems.
1645  // So we use the following encoding scheme: for values < 2^32-1, we
1646  // store in 4 bytes in big-endian order. For values > 2^32, we
1647  // store 0xFFFFFFF followed by 8 bytes in big-endian order. This
1648  // causes us to mis-read old-version code that stores exactly
1649  // 0xFFFFFFF, but I don't think that is likely to have happened for
1650  // these particular values.
1651  template <typename OUTPUT, typename IntType>
1652  static bool write_32_or_64(OUTPUT* fp, IntType value) {
1653  if ( value < 0xFFFFFFFFULL ) { // fits in 4 bytes
1654  if ( !sparsehash_internal::write_bigendian_number(fp, value, 4) )
1655  return false;
1656  } else {
1657  if ( !sparsehash_internal::write_bigendian_number(fp, 0xFFFFFFFFUL, 4) )
1658  return false;
1659  if ( !sparsehash_internal::write_bigendian_number(fp, value, 8) )
1660  return false;
1661  }
1662  return true;
1663  }
1664 
1665  template <typename INPUT, typename IntType>
1666  static bool read_32_or_64(INPUT* fp, IntType *value) { // reads into value
1667  MagicNumberType first4 = 0; // a convenient 32-bit unsigned type
1668  if ( !sparsehash_internal::read_bigendian_number(fp, &first4, 4) )
1669  return false;
1670  if ( first4 < 0xFFFFFFFFULL ) {
1671  *value = first4;
1672  } else {
1673  if ( !sparsehash_internal::read_bigendian_number(fp, value, 8) )
1674  return false;
1675  }
1676  return true;
1677  }
1678 
1679  public:
1680  // read/write_metadata() and read_write/nopointer_data() are DEPRECATED.
1681  // Use serialize() and unserialize(), below, for new code.
1682 
1683  template <typename OUTPUT> bool write_metadata(OUTPUT *fp) const {
1684  if ( !write_32_or_64(fp, MAGIC_NUMBER) ) return false;
1685  if ( !write_32_or_64(fp, settings.table_size) ) return false;
1686  if ( !write_32_or_64(fp, settings.num_buckets) ) return false;
1687 
1688  GroupsConstIterator group;
1689  for ( group = groups.begin(); group != groups.end(); ++group )
1690  if ( group->write_metadata(fp) == false ) return false;
1691  return true;
1692  }
1693 
1694  // Reading destroys the old table contents! Returns true if read ok.
1695  template <typename INPUT> bool read_metadata(INPUT *fp) {
1696  size_type magic_read = 0;
1697  if ( !read_32_or_64(fp, &magic_read) ) return false;
1698  if ( magic_read != MAGIC_NUMBER ) {
1699  clear(); // just to be consistent
1700  return false;
1701  }
1702 
1703  if ( !read_32_or_64(fp, &settings.table_size) ) return false;
1704  if ( !read_32_or_64(fp, &settings.num_buckets) ) return false;
1705 
1706  resize(settings.table_size); // so the vector's sized ok
1707  GroupsIterator group;
1708  for ( group = groups.begin(); group != groups.end(); ++group )
1709  if ( group->read_metadata(fp) == false ) return false;
1710  return true;
1711  }
1712 
1713  // This code is identical to that for SparseGroup
1714  // If your keys and values are simple enough, we can write them
1715  // to disk for you. "simple enough" means no pointers.
1716  // However, we don't try to normalize endianness
1717  bool write_nopointer_data(FILE *fp) const {
1719  it != nonempty_end(); ++it ) {
1720  if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false;
1721  }
1722  return true;
1723  }
1724 
1725  // When reading, we have to override the potential const-ness of *it
1726  bool read_nopointer_data(FILE *fp) {
1727  for ( nonempty_iterator it = nonempty_begin();
1728  it != nonempty_end(); ++it ) {
1729  if ( !fread(reinterpret_cast<void*>(&(*it)), sizeof(*it), 1, fp) )
1730  return false;
1731  }
1732  return true;
1733  }
1734 
1735  // INPUT and OUTPUT must be either a FILE, *or* a C++ stream
1736  // (istream, ostream, etc) *or* a class providing
1737  // Read(void*, size_t) and Write(const void*, size_t)
1738  // (respectively), which writes a buffer into a stream
1739  // (which the INPUT/OUTPUT instance presumably owns).
1740 
1742 
1743  // ValueSerializer: a functor. operator()(OUTPUT*, const value_type&)
1744  template <typename ValueSerializer, typename OUTPUT>
1745  bool serialize(ValueSerializer serializer, OUTPUT *fp) {
1746  if ( !write_metadata(fp) )
1747  return false;
1749  it != nonempty_end(); ++it ) {
1750  if ( !serializer(fp, *it) ) return false;
1751  }
1752  return true;
1753  }
1754 
1755  // ValueSerializer: a functor. operator()(INPUT*, value_type*)
1756  template <typename ValueSerializer, typename INPUT>
1757  bool unserialize(ValueSerializer serializer, INPUT *fp) {
1758  clear();
1759  if ( !read_metadata(fp) )
1760  return false;
1761  for ( nonempty_iterator it = nonempty_begin();
1762  it != nonempty_end(); ++it ) {
1763  if ( !serializer(fp, &*it) ) return false;
1764  }
1765  return true;
1766  }
1767 
1768  // Comparisons. Note the comparisons are pretty arbitrary: we
1769  // compare values of the first index that isn't equal (using default
1770  // value for empty buckets).
1771  bool operator==(const sparsetable& x) const {
1772  return ( settings.table_size == x.settings.table_size &&
1774  groups == x.groups );
1775  }
1776 
1777  bool operator<(const sparsetable& x) const {
1778  return std::lexicographical_compare(begin(), end(), x.begin(), x.end());
1779  }
1780  bool operator!=(const sparsetable& x) const { return !(*this == x); }
1781  bool operator<=(const sparsetable& x) const { return !(x < *this); }
1782  bool operator>(const sparsetable& x) const { return x < *this; }
1783  bool operator>=(const sparsetable& x) const { return !(*this < x); }
1784 
1785 
1786  private:
1787  // Package allocator with table_size and num_buckets to eliminate memory
1788  // needed for the zero-size allocator.
1789  // If new fields are added to this class, we should add them to
1790  // operator= and swap.
1791  class Settings : public allocator_type {
1792  public:
1793  typedef typename allocator_type::size_type size_type;
1794 
1796  : allocator_type(a), table_size(sz), num_buckets(n) { }
1797 
1798  Settings(const Settings& s)
1799  : allocator_type(s),
1801 
1802  size_type table_size; // how many buckets they want
1803  size_type num_buckets; // number of non-empty buckets
1804  };
1805 
1806  // The actual data
1807  group_vector_type groups; // our list of groups
1808  Settings settings; // allocator, table size, buckets
1809 };
1810 
1811 // We need a global swap as well
1812 template <class T, u_int16_t GROUP_SIZE, class Alloc>
1815  x.swap(y);
1816 }
1817 
1818 _END_GOOGLE_NAMESPACE_
1819 
1820 #endif // UTIL_GTL_SPARSETABLE_H_
sparsegroup< value_type, GROUP_SIZE, allocator_type > group_type
Definition: sparsetable.h:1444
containertype::iterator row_begin
Definition: sparsetable.h:736
T value_type
Definition: sparsetable.h:809
static size_type offset_to_pos(const unsigned char *bm, size_type offset)
Definition: sparsetable.h:956
bool operator<(const sparsetable &x) const
Definition: sparsetable.h:1777
group_vector_type::reference GroupsReference
Definition: sparsetable.h:1447
bool write_data(OUTPUT *fp, const void *data, size_t length)
Definition: hashtable-common.h:158
destructive_two_d_iterator< std::vector< sparsegroup< value_type, GROUP_SIZE, value_alloc_type >, vector_alloc > > destructive_iterator
Definition: sparsetable.h:1400
const_table_iterator(const iterator &from)
Definition: sparsetable.h:433
integral_constant< bool, true > true_type
Definition: template_util.h:87
pointer operator->() const
Definition: sparsetable.h:441
destructive_two_d_iterator()
Definition: sparsetable.h:732
Alloc::template rebind< T >::other value_alloc_type
Definition: sparsetable.h:1360
bool operator==(const sparsetable &x) const
Definition: sparsetable.h:1771
iterator begin()
Definition: sparsetable.h:1403
iterator begin()
Definition: sparsetable.h:834
_tmp_vt::pointer pointer
Definition: sparsetable.h:714
void erase(size_type i)
Definition: sparsetable.h:1615
value_alloc_type::size_type size_type
Definition: sparsetable.h:1368
reference operator*() const
Definition: sparsetable.h:440
void check() const
Definition: sparsetable.h:444
_tmp_vt::value_type value_type
Definition: sparsetable.h:711
size_type table_size
Definition: sparsetable.h:1802
static size_type num_groups(size_type num)
Definition: sparsetable.h:1453
element_adaptor operator[](size_type i)
Definition: sparsetable.h:1074
reference operator*() const
Definition: sparsetable.h:658
const_iterator operator+(difference_type i) const
Definition: sparsetable.h:459
reference operator*() const
Definition: sparsetable.h:563
bool operator<(const const_iterator &it) const
Definition: sparsetable.h:475
Settings settings
Definition: sparsetable.h:1342
Definition: sparsetable.h:526
tabletype::value_type value_type
Definition: sparsetable.h:420
Definition: hashtable-common.h:200
const_reference unsafe_get(size_type i) const
Definition: sparsetable.h:1056
const_iterator end() const
Definition: sparsetable.h:837
bool write_nopointer_data(FILE *fp) const
Definition: sparsetable.h:1717
alloc_impl(const libc_allocator_with_realloc< A > &a)
Definition: sparsetable.h:1312
size_type size() const
Definition: sparsetable.h:1505
iterator & operator++()
Definition: sparsetable.h:756
const_iterator operator-(difference_type i) const
Definition: sparsetable.h:461
bool operator>=(const sparsetable &x) const
Definition: sparsetable.h:1783
static bool write_32_or_64(OUTPUT *fp, IntType value)
Definition: sparsetable.h:1652
const_iterator & operator--()
Definition: sparsetable.h:454
two_d_iterator()
Definition: sparsetable.h:558
reverse_nonempty_iterator nonempty_rbegin()
Definition: sparsetable.h:852
bool operator!=(const iterator &it) const
Definition: sparsetable.h:770
const Name offset("offset")
Miscellaneous parameters.
Definition: nest_names.h:211
iterator operator++(int)
Definition: sparsetable.h:595
reference operator*() const
Definition: sparsetable.h:753
destructive_two_d_iterator(typename containertype::iterator begin, typename containertype::iterator end, typename containertype::iterator curr, typename containertype::value_type::TWOD_ITER_ col)
Definition: sparsetable.h:725
table_element_adaptor< sparsetable< T, GROUP_SIZE, Alloc > > element_adaptor
Definition: sparsetable.h:1378
_tmp_vt::const_reference reference
Definition: sparsetable.h:626
tabletype::reference reference
Definition: sparsetable.h:304
void resize(size_type new_size)
Definition: sparsetable.h:1512
bool read_data(INPUT *fp, void *data, size_t length)
Definition: hashtable-common.h:153
bool read_nopointer_data(FILE *fp)
Definition: sparsetable.h:1726
pointer allocate_group(size_type n)
Definition: sparsetable.h:882
const_iterator & operator++()
Definition: sparsetable.h:453
void bmclear(size_type i)
Definition: sparsetable.h:880
void free_group()
Definition: sparsetable.h:895
bool operator==(const iterator &it) const
Definition: sparsetable.h:689
table_iterator iterator
Definition: sparsetable.h:334
nonempty_iterator nonempty_begin()
Definition: sparsetable.h:1413
void advance_past_end()
Definition: sparsetable.h:661
const tabletype * table
Definition: sparsetable.h:485
iterator end()
Definition: sparsetable.h:1405
bool operator!=(const sparsetable &x) const
Definition: sparsetable.h:1780
nonempty_iterator nonempty_end()
Definition: sparsetable.h:846
const_reverse_iterator rbegin() const
Definition: sparsetable.h:839
GroupsReference which_group(size_type i)
Definition: sparsetable.h:1463
Settings(const alloc_impl< value_alloc_type > &a, u_int16_t n=0)
Definition: sparsetable.h:1332
std::random_access_iterator_tag iterator_category
Definition: sparsetable.h:419
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: sparsetable.h:823
value_alloc_type::difference_type difference_type
Definition: sparsetable.h:1369
nonempty_iterator nonempty_end()
Definition: sparsetable.h:1419
table_iterator(tabletype *tbl, size_type p)
Definition: sparsetable.h:344
void clear()
Definition: sparsetable.h:1487
bool empty() const
Definition: sparsetable.h:1039
void advance_past_end()
Definition: sparsetable.h:740
GroupsConstReference which_group(size_type i) const
Definition: sparsetable.h:1466
reference mutating_get(size_type i)
Definition: sparsetable.h:1557
bool operator<=(const sparsetable &x) const
Definition: sparsetable.h:1781
_tmp_vt::difference_type difference_type
Definition: sparsetable.h:712
_tmp_vt::difference_type difference_type
Definition: sparsetable.h:534
Definition: sparsetable.h:704
iterator & operator++()
Definition: sparsetable.h:670
void clear()
Definition: sparsetable.h:1029
iterator & operator--()
Definition: sparsetable.h:371
sparsegroup & operator=(const sparsegroup &x)
Definition: sparsetable.h:1004
reverse_nonempty_iterator nonempty_rend()
Definition: sparsetable.h:858
bool write_nopointer_data(OUTPUT *fp) const
Definition: sparsetable.h:1254
std::reverse_iterator< const_nonempty_iterator > const_reverse_nonempty_iterator
Definition: sparsetable.h:1394
iterator & operator+=(size_type t)
Definition: sparsetable.h:368
bool operator>(const iterator &it) const
Definition: sparsetable.h:398
iterator operator--(int)
Definition: sparsetable.h:596
iterator operator--(int)
Definition: sparsetable.h:374
table_iterator< tabletype > iterator
Definition: sparsetable.h:416
pointer operator->()
Definition: sparsetable.h:358
_tmp_vt::reference reference
Definition: sparsetable.h:713
bool operator<(const sparsegroup &x) const
Definition: sparsetable.h:1275
const_table_iterator()
Definition: sparsetable.h:430
sparsegroup(allocator_type &a)
Definition: sparsetable.h:988
bool operator!=(const iterator &it) const
Definition: sparsetable.h:606
reverse_nonempty_iterator nonempty_rend()
Definition: sparsetable.h:1431
const Name a("a")
Specific to Brette & Gerstner 2005 (aeif_cond-*)
Definition: nest_names.h:41
containertype::value_type::TWOD_CONST_ITER_ col_current
Definition: sparsetable.h:654
Settings(const Settings &s)
Definition: sparsetable.h:1798
reverse_nonempty_iterator nonempty_rbegin()
Definition: sparsetable.h:1425
pointer operator->() const
Definition: sparsetable.h:754
bool operator==(const const_iterator &it) const
Definition: sparsetable.h:472
__int16 int16_t
Definition: sparsetable.h:254
assert(pNet!=0)
containertype::const_iterator row_begin
Definition: sparsetable.h:653
bool operator<(const iterator &it) const
Definition: sparsetable.h:392
allocator_type::size_type size_type
Definition: sparsetable.h:1793
_tmp_vt::value_type value_type
Definition: sparsetable.h:624
Definition: libc_allocator_with_realloc.h:43
std::reverse_iterator< iterator > reverse_iterator
Definition: sparsetable.h:824
containertype::const_iterator row_end
Definition: sparsetable.h:653
bool read_metadata(INPUT *fp)
Definition: sparsetable.h:1228
const_two_d_iterator iterator
Definition: sparsetable.h:619
Definition: sparsetable.h:1285
u_int16_t size_type
Definition: sparsetable.h:821
size_type pos
Definition: sparsetable.h:403
iterator operator++(int)
Definition: sparsetable.h:372
Alloc::template rebind< sparsegroup< T, GROUP_SIZE, value_alloc_type > >::other vector_alloc
Definition: sparsetable.h:1362
group_vector_type::iterator GroupsIterator
Definition: sparsetable.h:1449
value_alloc_type::pointer pointer
Definition: sparsetable.h:813
bool operator>=(const const_iterator &it) const
Definition: sparsetable.h:482
static size_type modbit(size_type i)
Definition: sparsetable.h:877
bool empty() const
Definition: sparsetable.h:1507
table_iterator< T > operator+(typename table_iterator< T >::difference_type i, table_iterator< T > it)
Definition: sparsetable.h:408
containertype::iterator row_begin
Definition: sparsetable.h:611
const_reference operator[](size_type i) const
Definition: sparsetable.h:1566
void erase(iterator pos)
Definition: sparsetable.h:1199
bool test(size_type i) const
Definition: sparsetable.h:1134
const_table_iterator const_iterator
Definition: sparsetable.h:417
void check() const
Definition: sparsetable.h:361
unsigned char bitmap[(GROUP_SIZE-1)/8+1]
Definition: sparsetable.h:1343
tabletype::size_type size_type
Definition: sparsetable.h:339
const_nonempty_iterator nonempty_begin() const
Definition: sparsetable.h:1416
reverse_iterator rend()
Definition: sparsetable.h:840
value_alloc_type::pointer pointer
Definition: sparsetable.h:1372
bool operator!=(const iterator &it) const
Definition: sparsetable.h:396
tabletype::const_pointer pointer
Definition: sparsetable.h:424
destructive_two_d_iterator(typename containertype::iterator begin, typename containertype::iterator end, typename containertype::iterator curr)
Definition: sparsetable.h:716
size_type max_size() const
Definition: sparsetable.h:1038
const_table_iterator< sparsegroup< T, GROUP_SIZE, Alloc > > const_iterator
Definition: sparsetable.h:818
Alloc allocator_type
Definition: sparsetable.h:810
Alloc::template rebind< T >::other value_alloc_type
Definition: sparsetable.h:805
const Name y("y")
Definition: topology_names.h:52
reference set(size_type i, const_reference val)
Definition: sparsetable.h:1605
_tmp_vt::pointer pointer
Definition: sparsetable.h:536
size_type pos
Definition: sparsetable.h:486
const_reference operator[](size_type i) const
Definition: sparsetable.h:1070
Definition: sparsetable.h:1791
element_adaptor operator[](size_type i)
Definition: sparsetable.h:1570
static size_type bits_in_char(unsigned char c)
Definition: sparsetable.h:904
value_alloc_type::reference reference
Definition: sparsetable.h:811
Alloc allocator_type
Definition: sparsetable.h:1367
static bool read_32_or_64(INPUT *fp, IntType *value)
Definition: sparsetable.h:1666
pointer operator&()
Definition: sparsetable.h:314
bool write_bigendian_number(OUTPUT *fp, IntType value, size_t length)
Definition: hashtable-common.h:182
table_element_adaptor< sparsegroup< T, GROUP_SIZE, Alloc > > element_adaptor
Definition: sparsetable.h:820
sparsegroup(const sparsegroup &x)
Definition: sparsetable.h:992
table_iterator< sparsegroup< T, GROUP_SIZE, Alloc > > iterator
Definition: sparsetable.h:816
table_iterator()
Definition: sparsetable.h:347
const Name other("other")
Node type.
Definition: nest_names.h:216
bool unserialize(ValueSerializer serializer, INPUT *fp)
Definition: sparsetable.h:1757
sparsetable(size_type sz=0, Alloc alloc=Alloc())
Definition: sparsetable.h:1472
sparsehash_internal::pod_serializer< value_type > NopointerSerializer
Definition: sparsetable.h:1741
size_type pos
Definition: sparsetable.h:318
iterator & operator--()
Definition: sparsetable.h:676
void set_aux(size_type offset, base::false_type)
Definition: sparsetable.h:1096
std::reverse_iterator< const_nonempty_iterator > const_reverse_nonempty_iterator
Definition: sparsetable.h:831
_tmp_vt::difference_type difference_type
Definition: sparsetable.h:625
tabletype::difference_type difference_type
Definition: sparsetable.h:338
size_type num_nonempty() const
Definition: sparsetable.h:1509
libc_allocator_with_realloc< A >::size_type size_type
Definition: sparsetable.h:1310
value_alloc_type::const_reference const_reference
Definition: sparsetable.h:812
void swap(sparsegroup< T, GROUP_SIZE, Alloc > &x, sparsegroup< T, GROUP_SIZE, Alloc > &y)
Definition: sparsetable.h:1348
std::reverse_iterator< nonempty_iterator > reverse_nonempty_iterator
Definition: sparsetable.h:830
void erase(size_type i)
Definition: sparsetable.h:1178
tabletype::size_type size_type
Definition: sparsetable.h:303
void bmset(size_type i)
Definition: sparsetable.h:879
tabletype::size_type size_type
Definition: sparsetable.h:422
iterator operator++(int)
Definition: sparsetable.h:762
containertype::value_type _tmp_vt
Definition: sparsetable.h:710
const_two_d_iterator(typename containertype::const_iterator begin, typename containertype::const_iterator end, typename containertype::const_iterator curr)
Definition: sparsetable.h:629
size_type pos_to_offset(size_type pos) const
Definition: sparsetable.h:947
const_iterator begin() const
Definition: sparsetable.h:835
void erase(iterator start_it, iterator end_it)
Definition: sparsetable.h:1203
const_iterator & operator-=(size_type t)
Definition: sparsetable.h:452
iterator operator+(difference_type i) const
Definition: sparsetable.h:376
iterator & operator--()
Definition: sparsetable.h:585
containertype::iterator row_end
Definition: sparsetable.h:611
two_d_iterator iterator
Definition: sparsetable.h:528
const_two_d_iterator(typename containertype::const_iterator begin, typename containertype::const_iterator end, typename containertype::const_iterator curr, typename containertype::value_type::TWOD_CONST_ITER_ col)
Definition: sparsetable.h:638
bool test(iterator pos) const
Definition: sparsetable.h:1533
const_nonempty_iterator nonempty_end() const
Definition: sparsetable.h:1422
iterator & operator-=(size_type t)
Definition: sparsetable.h:369
Definition: sparsetable.h:803
static size_type charbit(size_type i)
Definition: sparsetable.h:876
destructive_iterator destructive_begin()
Definition: sparsetable.h:1437
const_reverse_nonempty_iterator nonempty_rbegin() const
Definition: sparsetable.h:1428
value_alloc_type::reference reference
Definition: sparsetable.h:1370
containertype::iterator row_current
Definition: sparsetable.h:611
pointer realloc_or_die(pointer ptr, size_type n)
Definition: sparsetable.h:1315
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: sparsetable.h:1379
bool operator==(const sparsegroup &x) const
Definition: sparsetable.h:1269
size_type size() const
Definition: sparsetable.h:1037
table_iterator< sparsetable< T, GROUP_SIZE, Alloc > > iterator
Definition: sparsetable.h:1374
bool test(iterator pos) const
Definition: sparsetable.h:1137
value_alloc_type::const_pointer const_pointer
Definition: sparsetable.h:1373
const_reference unsafe_get(size_type i) const
Definition: sparsetable.h:1550
u_int16_t pos_in_group(size_type i) const
Definition: sparsetable.h:1457
std::random_access_iterator_tag iterator_category
Definition: sparsetable.h:336
pointer group
Definition: sparsetable.h:1341
table_element_adaptor & operator=(const value_type &val)
Definition: sparsetable.h:309
group_vector_type::const_iterator GroupsConstIterator
Definition: sparsetable.h:1450
reference operator[](difference_type n) const
Definition: sparsetable.h:384
group_vector_type::const_reference GroupsConstReference
Definition: sparsetable.h:1448
const Name x("x")
current scaling factor of the synaptic weight [0...1] (Tsodyks2_connection)
Definition: nest_names.h:356
const_iterator & operator+=(size_type t)
Definition: sparsetable.h:451
reverse_iterator rend()
Definition: sparsetable.h:1409
void swap(sparsegroup &x)
Definition: sparsetable.h:1020
Definition: sparsetable.h:414
iterator operator++(int)
Definition: sparsetable.h:686
size_type get_pos(const const_nonempty_iterator it) const
Definition: sparsetable.h:1594
containertype::iterator row_current
Definition: sparsetable.h:736
size_type group_num(size_type i) const
Definition: sparsetable.h:1460
bool write_metadata(OUTPUT *fp) const
Definition: sparsetable.h:1683
bool read_bigendian_number(INPUT *fp, IntType *value, size_t length)
Definition: hashtable-common.h:168
std::reverse_iterator< iterator > reverse_iterator
Definition: sparsetable.h:1380
bool write_metadata(OUTPUT *fp) const
Definition: sparsetable.h:1216
bool operator>(const sparsegroup &x) const
Definition: sparsetable.h:1280
pointer operator->() const
Definition: sparsetable.h:659
const_iterator operator--(int)
Definition: sparsetable.h:457
std::bidirectional_iterator_tag iterator_category
Definition: sparsetable.h:530
~sparsegroup()
Definition: sparsetable.h:999
const_nonempty_iterator nonempty_end() const
Definition: sparsetable.h:849
const_two_d_iterator()
Definition: sparsetable.h:645
iterator & operator++()
Definition: sparsetable.h:370
A::pointer pointer
Definition: sparsetable.h:1287
const_iterator operator++(int)
Definition: sparsetable.h:455
value_alloc_type::const_reference const_reference
Definition: sparsetable.h:1371
int16_t difference_type
Definition: sparsetable.h:822
const_reverse_nonempty_iterator nonempty_rbegin() const
Definition: sparsetable.h:855
reverse_iterator rbegin()
Definition: sparsetable.h:1407
tabletype::pointer pointer
Definition: sparsetable.h:305
bool operator>(const sparsetable &x) const
Definition: sparsetable.h:1782
bool operator==(const iterator &it) const
Definition: sparsetable.h:389
static const u_int16_t DEFAULT_SPARSEGROUP_SIZE
Definition: sparsetable.h:279
void erase(iterator start_it, iterator end_it)
Definition: sparsetable.h:1626
tabletype::difference_type difference_type
Definition: sparsetable.h:421
bool test(size_type i) const
Definition: sparsetable.h:1529
difference_type operator-(const_iterator it) const
Definition: sparsetable.h:463
uint16_t u_int16_t
Definition: sparsetable.h:252
bool operator==(const iterator &it) const
Definition: sparsetable.h:764
containertype::value_type _tmp_vt
Definition: sparsetable.h:532
size_type num_buckets
Definition: sparsetable.h:1803
alloc_impl(const A &a)
Definition: sparsetable.h:1291
reference set(size_type i, const_reference val)
Definition: sparsetable.h:1110
void erase_aux(size_type offset, base::false_type)
Definition: sparsetable.h:1163
iterator end()
Definition: sparsetable.h:836
table_element_adaptor< tabletype > reference
Definition: sparsetable.h:340
const_nonempty_iterator nonempty_begin() const
Definition: sparsetable.h:845
bool operator<=(const const_iterator &it) const
Definition: sparsetable.h:480
containertype::const_iterator row_current
Definition: sparsetable.h:653
iterator operator-(difference_type i) const
Definition: sparsetable.h:378
pointer operator->() const
Definition: sparsetable.h:564
containertype::value_type::TWOD_ITER_ col_current
Definition: sparsetable.h:737
void erase(iterator pos)
Definition: sparsetable.h:1622
bool operator==(const iterator &it) const
Definition: sparsetable.h:600
const Name n("n")
Number of synaptic release sites (int >=0) (Tsodyks2_connection)
Definition: nest_names.h:202
const_reverse_nonempty_iterator nonempty_rend() const
Definition: sparsetable.h:1434
pointer realloc_or_die(pointer, size_type)
Definition: sparsetable.h:1295
static size_type pos_to_offset(const unsigned char *bm, size_type pos)
Definition: sparsetable.h:937
destructive_two_d_iterator iterator
Definition: sparsetable.h:706
nonempty_iterator nonempty_begin()
Definition: sparsetable.h:844
value_alloc_type::const_pointer const_pointer
Definition: sparsetable.h:814
const_two_d_iterator(const two_d_iterator< containertype > &it)
Definition: sparsetable.h:649
reverse_iterator rbegin()
Definition: sparsetable.h:838
Settings(const allocator_type &a, size_type sz=0, size_type n=0)
Definition: sparsetable.h:1795
Definition: sparsetable.h:617
libc_allocator_with_realloc< A >::pointer pointer
Definition: sparsetable.h:1309
unsigned long MagicNumberType
Definition: sparsetable.h:1640
bool operator!=(const sparsegroup &x) const
Definition: sparsetable.h:1278
const_pointer const_nonempty_iterator
Definition: sparsetable.h:829
int bmtest(size_type i) const
Definition: sparsetable.h:878
static const MagicNumberType MAGIC_NUMBER
Definition: sparsetable.h:1641
nonempty_iterator get_iter(size_type i)
Definition: sparsetable.h:1584
tabletype * table
Definition: sparsetable.h:402
reference mutating_get(size_type i)
Definition: sparsetable.h:1062
size_type num_nonempty() const
Definition: sparsetable.h:1041
tabletype::value_type value_type
Definition: sparsetable.h:337
void swap(sparsetable &x)
Definition: sparsetable.h:1480
bool read_metadata(INPUT *fp)
Definition: sparsetable.h:1695
u_int16_t num_buckets
Definition: sparsetable.h:1337
const Name A("A")
Definition: nest_names.h:40
size_type offset_to_pos(size_type offset) const
Definition: sparsetable.h:981
table_element_adaptor< tabletype > * pointer
Definition: sparsetable.h:341
const_nonempty_iterator get_iter(size_type i) const
Definition: sparsetable.h:1575
_tmp_vt::reference reference
Definition: sparsetable.h:535
tabletype * table
Definition: sparsetable.h:317
std::reverse_iterator< nonempty_iterator > reverse_nonempty_iterator
Definition: sparsetable.h:1393
Settings(const Settings &s)
Definition: sparsetable.h:1334
bool operator!=(const const_iterator &it) const
Definition: sparsetable.h:479
const_table_iterator(const tabletype *tbl, size_type p)
Definition: sparsetable.h:427
bool serialize(ValueSerializer serializer, OUTPUT *fp)
Definition: sparsetable.h:1745
bool operator>=(const sparsegroup &x) const
Definition: sparsetable.h:1281
bool read_nopointer_data(INPUT *fp)
Definition: sparsetable.h:1242
bool operator!=(const iterator &it) const
Definition: sparsetable.h:695
const_reverse_iterator rend() const
Definition: sparsetable.h:841
two_d_iterator(typename containertype::iterator begin, typename containertype::iterator end, typename containertype::iterator curr)
Definition: sparsetable.h:540
Definition: sparsetable.h:1358
table_element_adaptor(tabletype *tbl, size_type p)
Definition: sparsetable.h:307
bool operator>=(const iterator &it) const
Definition: sparsetable.h:399
_tmp_vt::const_pointer pointer
Definition: sparsetable.h:627
bool test(const_iterator pos) const
Definition: sparsetable.h:1536
Definition: sparsetable.h:1330
two_d_iterator(typename containertype::iterator begin, typename containertype::iterator end, typename containertype::iterator curr, typename containertype::value_type::TWOD_ITER_ col)
Definition: sparsetable.h:550
difference_type operator-(iterator it) const
Definition: sparsetable.h:380
const_reverse_iterator rbegin() const
Definition: sparsetable.h:1408
void set_aux(size_type offset, base::true_type)
Definition: sparsetable.h:1086
Settings settings
Definition: sparsetable.h:1808
void erase_aux(size_type offset, base::true_type)
Definition: sparsetable.h:1149
const Name p("p")
current release probability (Tsodyks2_connection)
Definition: nest_names.h:218
size_type max_size() const
Definition: sparsetable.h:1506
bool operator<=(const sparsegroup &x) const
Definition: sparsetable.h:1279
reference operator*()
Definition: sparsetable.h:355
T value_type
Definition: sparsetable.h:1366
const Name c("c")
Specific to Izhikevich 2003.
Definition: nest_names.h:62
const_table_iterator< sparsetable< T, GROUP_SIZE, Alloc > > const_iterator
Definition: sparsetable.h:1376
destructive_iterator destructive_end()
Definition: sparsetable.h:1440
void advance_past_end()
Definition: sparsetable.h:569
containertype::iterator row_end
Definition: sparsetable.h:736
allocator_type get_allocator() const
Definition: sparsetable.h:1496
const_iterator end() const
Definition: sparsetable.h:1406
tabletype::value_type value_type
Definition: sparsetable.h:302
tabletype::const_reference reference
Definition: sparsetable.h:423
A::size_type size_type
Definition: sparsetable.h:1288
const_reference default_value() const
Definition: sparsetable.h:868
containertype::value_type _tmp_vt
Definition: sparsetable.h:623
reference operator[](difference_type n) const
Definition: sparsetable.h:467
iterator operator--(int)
Definition: sparsetable.h:687
containertype::value_type::TWOD_ITER_ col_current
Definition: sparsetable.h:612
two_d_iterator< std::vector< sparsegroup< value_type, GROUP_SIZE, value_alloc_type >, vector_alloc > > nonempty_iterator
Definition: sparsetable.h:1387
std::vector< group_type, vector_alloc > group_vector_type
Definition: sparsetable.h:1445
_tmp_vt::value_type value_type
Definition: sparsetable.h:533
iterator & operator++()
Definition: sparsetable.h:579
bool operator<=(const iterator &it) const
Definition: sparsetable.h:397
bool operator>(const const_iterator &it) const
Definition: sparsetable.h:481
const_two_d_iterator< std::vector< sparsegroup< value_type, GROUP_SIZE, value_alloc_type >, vector_alloc > > const_nonempty_iterator
Definition: sparsetable.h:1392
std::bidirectional_iterator_tag iterator_category
Definition: sparsetable.h:621
pointer nonempty_iterator
Definition: sparsetable.h:828
std::input_iterator_tag iterator_category
Definition: sparsetable.h:708
group_vector_type groups
Definition: sparsetable.h:1807
Definition: sparsetable.h:300
Definition: sparsetable.h:332
integral_constant< bool, false > false_type
Definition: template_util.h:88
const_iterator begin() const
Definition: sparsetable.h:1404
const_reverse_iterator rend() const
Definition: sparsetable.h:1410
const_reverse_nonempty_iterator nonempty_rend() const
Definition: sparsetable.h:861