|
Boost Users : |
From: Michael W Daniels (daniels_at_[hidden])
Date: 2005-03-11 09:23:21
At 02:09 AM 3/11/2005, Eric Niebler wrote:
>It's impossible to say, since I don't know how hashed_array_tree is
>defined and I don't have a way to find out. If you could post a minimal,
>complete example that reproduces the problem, I could probably tell you
>what's wrong.
The trouble is that I wasn't sure how to make things any more minimal,
since I don't know what aspects of the container's definition are relevant;
I'll attach the headers for the hashed_array_tree, though.
// -*- c++ -*-
#pragma once
namespace cphstl {
template <class T, class A = allocator<T> >
class hashed_array_tree {
template <class T, class A = allocator<T> > friend class hat_iterator;
template <class T, class A = allocator<T> > friend class hat_const_iterator;
private:
inline void find_index (unsigned int n, int& leaf, int& index) {
leaf = n >> _power;
index = n & _mask;
}
inline int find_leafsize (unsigned int n) {
int leafsize = 1, capacity = 1;
while (capacity < (int) n) {
leafsize <<= 1;
capacity <<= 2;
}
return leafsize;
}
public:
typedef T value_type;
typedef A allocator_type;
typedef typename A::size_type size_type;
typedef typename A::difference_type difference_type;
typedef hat_iterator<T, A> iterator;
typedef hat_const_iterator<T, A> const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
hashed_array_tree (const size_type c = 1,
const value_type& val = value_type(),
const A& a = A())
: _alloc(a), _size(0) {
// Find the initial capacity as the square of a power of two
// that corresponds best to the initial_capacity.
_leafsize = find_leafsize((unsigned int)c);
_top_array = _palloc.allocate(_leafsize);
int leafs = (int)(c / _leafsize + (c % _leafsize ? 1 : 0));
for (int i = 0; i < leafs; i++) {
_top_array[i] = _alloc.allocate(_leafsize);
for (int j = 0; j < _leafsize; j++)
_alloc.construct(&_top_array[i][j], val);
}
_capacity = _leafsize * leafs;
_power = log_2_ceil(_leafsize);
_mask = (1 << _power) - 1;
}
hashed_array_tree(const hashed_array_tree& v, const A& a = A())
: _leafsize(v._leafsize), _mask(v._mask),
_power(v._power), _alloc(a),
_capacity(v._capacity), _size(v._size) {
// Allocate the top array and the leafs.
_top_array = _palloc.allocate(_leafsize);
// Copy the elements.
int leafs = (int)(_capacity / _leafsize);
for (int i = 0; i < leafs; i++) {
_top_array[i] = _alloc.allocate(_leafsize);
for (int j = 0; j < _leafsize; j++) {
_alloc.construct(&_top_array[i][j], v._top_array[i][j]);
}
}
}
~hashed_array_tree () {
int leafs = (int)(_capacity / _leafsize);
for (int i = 0; i < leafs; i++) {
for (int j = 0; j < _leafsize; j++)
_alloc.destroy(&_top_array[i][j]);
_alloc.deallocate(_top_array[i], _leafsize);
}
_palloc.deallocate(_top_array, _leafsize);
}
iterator begin() {return iterator(0, this);}
iterator end() {return iterator(_size, this);}
const_iterator begin() const {return const_iterator(0, this);}
const_iterator end() const {return const_iterator(_size, this);}
reverse_iterator rbegin() {
return reverse_iterator(iterator(_size, this));
}
reverse_iterator rend() {
return reverse_iterator(iterator(0, this));
}
const_reverse_iterator rbegin() const {
return const_reverse_iterator(const_iterator(_size, this));
}
const_reverse_iterator rend() const {
return const_reverse_iterator(const_iterator(0, this));
}
reference operator[] (size_type n) {
return _top_array[n >> _power][n & _mask];
}
const_reference operator[] (size_type n) const {
return _top_array[n >> _power][n & _mask];
}
reference front() {
return _size == 0 ? 0 : _top_array[0][0];
}
const_reference front() const {
return _size == 0 ? 0 : _top_array[0][0];
}
reference back() {
if (_size == 0) return 0;
return _top_array[_size >> _power][_size & _mask];
}
const_reference back() const {
if (_size == 0) return 0;
return _top_array[_size >> _power][_size & _mask];
}
hashed_array_tree& operator=(const hashed_array_tree& v) {
// If the leafsize of the two trees are different we just
// deallocate everything and allocate new leafs.
if (_leafsize != v._leafsize) {
// Destroy and deallocate everything.
int leafs = _capacity / _leafsize;
for (int i = 0; i < leafs; i++) {
for (int j = 0; j < _leafsize; j++)
_alloc.destroy(&_top_array[i][j]);
_alloc.deallocate(_top_array[i], _leafsize);
}
_palloc.deallocate(_top_array, _leafsize);
// Allocate a new top_array and allocate the new
// elements. While doing this we copy the values from v into
// the new leafs.
_top_array = _palloc.allocate(v._leafsize);
int need = v._capacity / v._leafsize;
for (int i = 0; i < need; i++) {
_top_array[i] = _alloc.allocate(v._leafsize);
for (int j = 0; j < v._leafsize; j++)
_alloc.construct(&_top_array[i][j], v._top_array[i][j]);
}
_leafsize = v._leafsize;
_mask = v._mask;
_power = v._power;
} else {
// The leafsizes are the same. Now we free the space that is
// no longer needed or allocate extra leafs if they are
// needed.
int leafs = _capacity / _leafsize;
int need = v._capacity / _leafsize;
if (leafs < need) {
// We have to allocate extra leafs.
for (int i = leafs; i < need; i++)
_top_array[i] = _alloc.allocate(_leafsize);
} else {
// We might have to deallocate some leafs.
for (int i = need; i < leafs; i++) {
for (int j = 0; j < _leafsize; j++)
_alloc.destroy(&_top_array[i][j]);
_alloc.deallocate(_top_array[i], _leafsize);
}
// We set leafs to need to make sure that element copying
// works.
leafs = need;
}
// Copy the data from v into the new storage. First we copy
// into the old leafs where destruction of old elements are
// needed.
for (int i = 0; i < leafs; i++) {
for (int j = 0; j < _leafsize; j++) {
_alloc.destroy(&_top_array[i][j]);
_alloc.construct(&_top_array[i][j], v._top_array[i][j]);
}
}
// Then we copy into the new leafs that doesn't need
// destruction of elements.
for (int i = leafs; i < need; i++) {
for (int j = 0; j < _leafsize; j++)
_alloc.construct(&_top_array[i][j], v._top_array[i][j]);
}
}
_size = v._size;
_capacity = v._capacity;
return *this;
}
void reserve(size_type n) {
if (n <= _capacity) return;
// There are two cases here, one where we have to change the
// leafsize and one where we can reserve the space without
// changing the leafsize.
int new_leafsize = find_leafsize(n);
int needed_leafs = n / new_leafsize + (n % new_leafsize ? 1 : 0);
value_type val = value_type();
if (_leafsize == new_leafsize) {
for (int i = _capacity / _leafsize; i < needed_leafs; i++) {
_top_array[i] = _alloc.allocate(_leafsize);
for (int j = 0; j < _leafsize; j++)
_alloc.construct(&_top_array[i][j], val);
_capacity += _leafsize;
}
} else {
pointer* new_top_array = _palloc.allocate(new_leafsize);
// For each new leaf that is needed we allocate it and either
// copy the old value into the position or construct it with
// the default value val. First we allocate the new leafs.
for (int i = 0; i < needed_leafs; i++)
new_top_array[i] = _alloc.allocate(new_leafsize);
// Then we copy the elements from the old top_array.
// x is the number of old leafs that fit into one new leaf.
int x = new_leafsize / _leafsize;
int leafs = _capacity / _leafsize;
for (int i = 0; i < leafs; i++) {
for (int j = 0; j < _leafsize; j++) {
_alloc.construct(&new_top_array[i/x][(i%x) * _leafsize + j],
_top_array[i][j]);
_alloc.destroy(&_top_array[i][j]);
}
_alloc.deallocate(_top_array[i], _leafsize);
}
// Now we have to check wether one of the leafs have not been
// fully constructed.
int idx = (_capacity / new_leafsize +
(_capacity % new_leafsize ? 1 : 0)) - 1;
int start;
if ((start = _capacity % new_leafsize) != 0) {
for (int i = start; i < new_leafsize; i++)
_alloc.construct(&new_top_array[idx][i], val);
idx++;
}
// The rest of the needed leafs only needs to be constructed
// with the standard value val.
for (int i = idx; i < needed_leafs; i++) {
for (int j = 0; j < new_leafsize; j++)
_alloc.construct(&new_top_array[i][j], val);
}
_top_array = new_top_array;
_leafsize = new_leafsize;
_capacity = _leafsize * needed_leafs;
_power = log_2_ceil(_leafsize);
_mask = (1 << _power) - 1;
}
}
void swap (hashed_array_tree& v) {
int tmp_leafsize = _leafsize;
unsigned int tmp_power = _power;
unsigned int tmp_mask = _mask;
unsigned int tmp_capacity = _capacity;
unsigned int tmp_size = _size;
value_type **tmp_top_array = _top_array;
_leafsize = v._leafsize;
_power = v._power;
_mask = v._mask;
_capacity = v._capacity;
_size = v._size;
_top_array = v._top_array;
v._leafsize = tmp_leafsize;
v._power = tmp_power;
v._mask = tmp_mask;
v._capacity = tmp_capacity;
v._size = tmp_size;
v._top_array = tmp_top_array;
}
void push_back (const_reference x) {
// Check to see is extra storage must be allocated.
if (_size == _capacity) {
// Check to see if we need to change leafsize.
if (_size == (unsigned int)_leafsize * _leafsize) {
int new_leafsize = _leafsize << 1;
pointer* new_top_array = _palloc.allocate(new_leafsize);
// The is one special case here and that's when the old
// leafsize is 1. This is handled separately here. This is a
// special case because the moving of old elements does not
// completely fill the new leafs of the new top_array.
if (_leafsize == 1) {
new_top_array[0] = _alloc.allocate(2);
_alloc.construct(&new_top_array[0][0], _top_array[0][0]);
_alloc.construct(&new_top_array[0][1], x);
_alloc.destroy(&_top_array[0][0]);
_alloc.deallocate(_top_array[0], _leafsize);
_palloc.deallocate(_top_array, _leafsize);
_top_array = new_top_array;
_leafsize = 2;
_capacity = 2;
_power = 1;
_mask = 1;
} else {
// This loops over the new leafs needed by the objects in
// the old leafs.
_power += 1;
size_type last_leaf = _size >> _power;
for (size_type i = 0; i < last_leaf; i++) {
new_top_array[i] = _alloc.allocate(new_leafsize);
size_type pos = 0; // The starting position in this new leaf.
// This loops over the next two old leafs that need to
// be copied into new leafs.
size_type stop_index = (i + 1) * 2;
for (size_type j = i * 2; j < stop_index; j++) {
// Copy the actual elements.
for (int k = 0; k < _leafsize; k++) {
_alloc.construct(&new_top_array[i][pos++],
_top_array[j][k]);
_alloc.destroy(&_top_array[j][k]);
}
_alloc.deallocate(_top_array[j], _leafsize);
}
}
_palloc.deallocate(_top_array, _leafsize);
_top_array = new_top_array;
// Allocate the extra leaf that we wanted to begin with.
_top_array[last_leaf] = _alloc.allocate(new_leafsize);
value_type val = value_type();
for (int i = 1; i < new_leafsize; i++)
_alloc.construct(&_top_array[last_leaf][i], val);
_leafsize = new_leafsize;
_capacity += _leafsize;
_mask = (_mask<<1)|1;
// Insert the element.
_alloc.construct(&_top_array[last_leaf][0], x);
}
} else {
// If no change in leafsize is needed we just allocate an
// extra leaf.
size_type new_leaf = _capacity >> _power;
value_type val = value_type();
_top_array[new_leaf] = _alloc.allocate(_leafsize);
for (int i = 1; i < _leafsize; i++)
_alloc.construct(&_top_array[new_leaf][i], val);
_capacity += _leafsize;
// Insert the element.
_alloc.construct(&_top_array[new_leaf][0], x);
}
} else {
// Insert the new element.
int leaf = (int)(_size >> _power);
int leaf_idx = (int)(_size & _mask);
_alloc.destroy(&_top_array[leaf][leaf_idx]);
_alloc.construct(&_top_array[leaf][leaf_idx], x);
}
_size += 1;
}
void pop_back () {
value_type val = value_type();
size_type max_capacity = _leafsize * _leafsize;
_size -= 1;
// Check if resizing is needed.
if (_capacity != 1 && _size <= max_capacity / 8) {
int new_leafsize = _leafsize >> 1;
pointer* new_top_array = _palloc.allocate(new_leafsize);
size_type last_leaf = _size >> _power;
size_type last_idx = _size & _mask;
size_type cur_new_leaf = 0;
// Start by allocating the leafs that are needed in the new
// top_array.
size_type new_leafs = _size / new_leafsize +
(_size % new_leafsize ? 1 : 0);
if (new_leafs == 0) new_leafs = 1; // If _size is 0.
for (size_type i = 0; i < new_leafs; i++)
new_top_array[i] = _alloc.allocate(new_leafsize);
// For every leaf containing data in the old top_array but
// the last one.
for (size_type i = 0; i < last_leaf; i++) {
for (int j = 0; j < new_leafsize; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j],
_top_array[i][j]);
cur_new_leaf++;
for (int j = new_leafsize; j < _leafsize; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j%new_leafsize],
_top_array[i][j]);
cur_new_leaf++;
}
// Now take care of the last leaf. First check to see if
// index == 0 in which case no more elements must be moved.
if (last_idx != 0) {
// See if two new leafs are needed.
if ((int)last_idx > new_leafsize) {
// Fill the first leaf.
for (int j = 0; j < new_leafsize; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j],
_top_array[last_leaf][j]);
cur_new_leaf++;
// And copy the elements until n into the last leaf.
for (size_type j = new_leafsize; j < last_idx; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j%new_leafsize],
_top_array[last_leaf][j]);
// Construct the empty spaces.
for (int j = last_idx%new_leafsize; j < new_leafsize; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j], val);
} else {
for (size_type j = 0; j < last_idx; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j],
_top_array[last_leaf][j]);
// Construct the empty spaces.
for (int j = last_idx; j < new_leafsize; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j], val);
}
}
// Destroy the elements in the old top_array.
last_leaf = _capacity / _leafsize;
for (size_type i = 0; i < last_leaf; i++) {
for (int j = 0; j < _leafsize; j++)
_alloc.destroy(&_top_array[i][j]);
_alloc.deallocate(_top_array[i], _leafsize);
}
_palloc.deallocate(_top_array, _leafsize);
_top_array = new_top_array;
_leafsize = new_leafsize;
_capacity = new_leafs * _leafsize;
_power -= 1;
_mask = _mask >> 1;
} else {
// No resizing is needed.
size_type last_leaf = _size >> _power;
size_type last_idx = _size & _mask;
_alloc.destroy(&_top_array[last_leaf][last_idx]);
_alloc.construct(&_top_array[last_leaf][last_idx], val);
// Check to see if there are two empty leafs. If so we
// deallocate the last one.
last_leaf = (_capacity - 1) >> _power;
if (last_leaf >= ((_size - 1) >> _power) + 2) {
for (int i = 0; i < _leafsize; i++)
_alloc.destroy(&_top_array[last_leaf][i]);
_alloc.deallocate(_top_array[last_leaf], _leafsize);
_capacity -= _leafsize;
}
}
}
// This function could be optimized when a resize is done by
// moving elements while copying them from the old top_array. It
// has not been done because of 1) time, 2) it's not necessary for
// what I'm meassuring in my report.
iterator insert(iterator pos, const value_type& x) {
// Allocate an extra leaf if this is needed.
if (_size == _capacity) {
value_type val = value_type();
// Check to see if we need to change leafsize.
if (_size == (unsigned int)_leafsize * _leafsize) {
int new_leafsize = _leafsize << 1;
pointer* new_top_array = _palloc.allocate(new_leafsize);
// The is one special case here and that's when the old
// leafsize is 1. This is handled separately here. This is a
// special case because the moving of old elements does not
// completely fill the new leafs of the new top_array.
if (_leafsize == 1) {
new_top_array[0] = _alloc.allocate(2);
_alloc.construct(&new_top_array[0][0], _top_array[0][0]);
_alloc.construct(&new_top_array[0][1], val);
_alloc.destroy(&_top_array[0][0]);
_alloc.deallocate(_top_array[0], _leafsize);
_palloc.deallocate(_top_array, _leafsize);
_top_array = new_top_array;
_leafsize = 2;
_capacity = 2;
_power = 1;
_mask = 1;
} else {
// This loops over the new leafs needed by the objects in
// the old leafs.
int last_leaf = _size / new_leafsize;
for (int i = 0; i < last_leaf; i++) {
new_top_array[i] = _alloc.allocate(new_leafsize);
int pos = 0; // The starting position in this new leaf.
// This loops over the next two old leafs that need to
// be copied into new leafs.
for (int j = i * 2; j < (i + 1) * 2; j++) {
// Copy the actual elements.
for (int k = 0; k < _leafsize; k++) {
_alloc.construct(&new_top_array[i][pos++],
_top_array[j][k]);
_alloc.destroy(&_top_array[j][k]);
}
_alloc.deallocate(_top_array[j], _leafsize);
}
}
_palloc.deallocate(_top_array, _leafsize);
_top_array = new_top_array;
// Allocate the extra leaf that we wanted to begin with.
_top_array[last_leaf] = _alloc.allocate(new_leafsize);
for (int i = 0; i < new_leafsize; i++)
_alloc.construct(&_top_array[last_leaf][i], val);
_leafsize = new_leafsize;
_capacity += _leafsize;
_power = log_2_ceil(_leafsize);
_mask = (1 << _power) - 1;
}
} else {
// If no change in leafsize is needed we just allocate an
// extra leaf.
int new_leaf = _capacity / _leafsize;
_top_array[new_leaf] = _alloc.allocate(_leafsize);
for (int i = 0; i < _leafsize; i++)
_alloc.construct(&_top_array[new_leaf][i], val);
_capacity += _leafsize;
}
}
// Insert the element into position n.
int index = pos - this->begin();
int leaf = index / _leafsize;
int n = index % _leafsize; // The index in the leaf.
// Now move all the elements in front of position n one space up
// in the tree.
int last_leaf, move_from;
find_index(_size - 1, last_leaf, move_from);
// This loops over the leaf from the last one to the one that
// contains n.
for (int i = last_leaf; i >= leaf; i--) {
// First we check to see if we need to move the last element
// in the leaf into the leaf in front of this one.
if (move_from == _leafsize - 1) {
_alloc.destroy(&_top_array[i+1][0]);
_alloc.construct(&_top_array[i+1][0],
_top_array[i][move_from--]);
}
// The we move the rest of the elements inside of the leaf. If
// this is the leaf that contains n we only move the elements
// until the n'th position.
if (i == leaf) {
for (int j = move_from; j >= n; j--) {
_alloc.destroy(&_top_array[i][j+1]);
_alloc.construct(&_top_array[i][j+1], _top_array[i][j]);
}
} else {
for (int j = move_from; j >= 0; j--) {
_alloc.destroy(&_top_array[i][j+1]);
_alloc.construct(&_top_array[i][j+1], _top_array[i][j]);
}
}
move_from = _leafsize - 1;
}
// Insert x into the hole that has appeared.
_alloc.destroy(&_top_array[leaf][n]);
_alloc.construct(&_top_array[leaf][n], x);
_size += 1;
return iterator(n, this);
}
iterator erase(iterator pos) {
int n = pos - this->begin();
value_type val = value_type();
// Check if we need to change to another leafsize after this
// erase. We change leafsize if the size is 1/8 of the max
// capacity with the current leafsize.
unsigned int max_cap = _leafsize * _leafsize;
if (_capacity != 1 && _size - 1 <= max_cap / 8) {
int new_leafsize = _leafsize >> 1;
pointer *new_top_array = _palloc.allocate(new_leafsize);
int last_leaf = (_size - 1) / _leafsize;
int last_idx = (_size - 1) % _leafsize;
int n_leaf = n / _leafsize;
int n_idx = n % _leafsize;
int cur_new_leaf = 0;
// Start by allocating the leafs that are needed in the new
// top_array.
int new_leafs = new_leafsize == 1 ? 1 : (_size - 1) /
new_leafsize + ((_size - 1) % new_leafsize ? 1 : 0);
for (int i = 0; i < new_leafs; i++)
new_top_array[i] = _alloc.allocate(new_leafsize);
// For every leaf containing data in the old top_array.
for (int i = 0; i <= last_leaf; i++) {
// If this is before the leaf that contain n we just copy
// the elements.
if (i < n_leaf) {
int split;
for (int j = 0; j < _leafsize; j++) {
split = j >= new_leafsize ? 1 : 0;
_alloc.construct(&new_top_array[cur_new_leaf+split]
[j-new_leafsize*split], _top_array[i][j]);
}
} else if (i == n_leaf) {
// If this is exactly the leaf that contain n.
int split;
for (int j = 0; j < n_idx; j++) {
split = j >= new_leafsize ? 1 : 0;
_alloc.construct(&new_top_array[cur_new_leaf+split]
[j-new_leafsize*split], _top_array[i][j]);
}
// Now we have to check if this is the last leaf in which
// case we only have to copy the elements until last_idx.
if (i == last_leaf) {
for (int j = n_idx; j < last_idx; j++) {
split = j >= new_leafsize ? 1 : 0;
_alloc.construct(&new_top_array[cur_new_leaf+split]
[j-new_leafsize*split],
_top_array[i][j+1]);
}
// Now we need to construct the last elements in
// new_top_array.
int leaf, idx;
if (last_idx >= new_leafsize) {
leaf = cur_new_leaf + 1;
idx = last_idx - new_leafsize;
if (idx != 0) {
for (int j = idx + 1; j < new_leafsize; j++)
_alloc.construct(&new_top_array[leaf][j], val);
}
} else {
if (n_idx != 0) {
for (int j = last_idx + 1; j < new_leafsize; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j], val);
}
}
} else {
// If this is not the last leaf we copy all the elements
// from this leaf (after the n'th position) into the new
// leafs. When that is done we copy the first element
// from the next leaf into the last position of the new
// leaf.
for (int j = n_idx; j < _leafsize - 1; j++) {
split = j >= new_leafsize ? 1 : 0;
_alloc.construct(&new_top_array[cur_new_leaf+split]
[j-new_leafsize*split],
_top_array[i][j+1]);
}
_alloc.construct(&new_top_array[cur_new_leaf+1]
[new_leafsize-1], _top_array[i+1][0]);
}
} else {
// If this is a leaf that comes after the leaf that contain n.
int split;
// If this is the last leaf we just copy over the elements
// from this leaf.
if (i == last_leaf) {
for (int j = 0; j < last_idx; j++) {
split = j >= new_leafsize ? 1 : 0;
_alloc.construct(&new_top_array[cur_new_leaf+split]
[j-new_leafsize*split],
_top_array[i][j+1]);
}
// Now we construct the last elements of the new leaf.
int leaf, idx;
if (last_idx >= new_leafsize) {
leaf = cur_new_leaf + 1;
idx = last_idx - new_leafsize;
if (idx != 0) {
for (int j = idx + 1; j < new_leafsize; j++)
_alloc.construct(&new_top_array[leaf][j], val);
}
} else {
if (last_idx != 0) {
for (int j = last_idx + 1; j < new_leafsize; j++)
_alloc.construct(&new_top_array[cur_new_leaf][j], val);
}
}
} else {
for (int j = 0; j < _leafsize - 1; j++) {
split = j >= new_leafsize ? 1 : 0;
_alloc.construct(&new_top_array[cur_new_leaf+split]
[j-new_leafsize*split],
_top_array[i][j+1]);
}
_alloc.construct(&new_top_array[cur_new_leaf+1]
[new_leafsize-1], _top_array[i+1][0]);
}
}
cur_new_leaf += 2;
}
// Destroy the elements in the old top_array.
last_leaf = _capacity / _leafsize;
for (int i = 0; i < last_leaf; i++) {
for (int j = 0; j < _leafsize; j++)
_alloc.destroy(&_top_array[i][j]);
_alloc.deallocate(_top_array[i], _leafsize);
}
_palloc.deallocate(_top_array, _leafsize);
_top_array = new_top_array;
_leafsize = new_leafsize;
_capacity = new_leafs * _leafsize;
_power -= 1;
_mask = _mask >> 1;
} else {
// If no resizing of leafs is necessary we just rearrange the
// elements in the existing structure. We just start from the
// n'th position and run forward through the leafs.
int last_leaf = (_size - 1) / _leafsize;
int last_idx = (_size - 1) % _leafsize;
int n_leaf = n / _leafsize;
int start_idx = n % _leafsize;
for (int i = n_leaf; i <= last_leaf; i++) {
// If this is the last leaf with data in it we only move
// elements until last_idx.
if (i == last_leaf) {
for (int j = start_idx; j < last_idx; j++) {
_alloc.destroy(&_top_array[i][j]);
_alloc.construct(&_top_array[i][j], _top_array[i][j+1]);
}
_alloc.destroy(&_top_array[i][last_idx]);
_alloc.construct(&_top_array[i][last_idx], val);
} else {
for (int j = start_idx; j < _leafsize - 1; j++) {
_alloc.destroy(&_top_array[i][j]);
_alloc.construct(&_top_array[i][j], _top_array[i][j+1]);
}
// Move the first element from the next leaf into the last
// position in this leaf. This makes the hole that is
// needed to start rearranging the next leaf.
_alloc.destroy(&_top_array[i][_leafsize-1]);
_alloc.construct(&_top_array[i][_leafsize-1],
_top_array[i+1][0]);
}
start_idx = 0;
}
// Check to see if there are two empty leafs. If so we
// deallocate the last one.
last_leaf = _capacity / _leafsize - 1;
if (last_leaf >= (int)((_size - 2) / _leafsize + 2)) {
for (int i = 0; i < _leafsize; i++)
_alloc.destroy(&_top_array[last_leaf][i]);
_alloc.deallocate(_top_array[last_leaf], _leafsize);
_capacity -= _leafsize;
}
}
_size -= 1;
return iterator(n, this);
}
void clear() {
int last = (int)(_capacity / _leafsize);
for (int i = 0; i < last; i++) {
for (int j = 0; j < _leafsize; j++)
_alloc.destroy(&_top_array[i][j]);
_alloc.deallocate(_top_array[i], _leafsize);
}
_palloc.deallocate(_top_array, _leafsize);
_size = 0;
_capacity = 1;
_leafsize = 1;
_power = 0;
_mask = 0;
_top_array = _palloc.allocate(1);
_top_array[0] = _alloc.allocate(1);
_alloc.construct(&_top_array[0][0], value_type());
}
template <class T, class A> friend bool operator==(const hashed_array_tree<T, A>& v1,
const hashed_array_tree<T, A>& v2);
template <class T, class A> friend bool operator<(const hashed_array_tree<T, A>& v1,
const hashed_array_tree<T, A>& v2);
const size_type size() const {
return _size;
}
private:
int _leafsize;
unsigned int _mask;
unsigned int _power;
typedef typename A::rebind<typename A::pointer>::other palloc;
palloc _palloc;
allocator_type _alloc;
protected:
size_type _capacity;
size_type _size;
pointer *_top_array;
};
template <class T, class A>
bool operator==(const hashed_array_tree<T, A>& v1,
const hashed_array_tree<T, A>& v2) {
if (v1._size != v2._size)
return false;
else {
for (unsigned int i = 0; i < v1._size; i++) {
if (v1[i] != v2[i])
return false;
}
return true;
}
}
template <class T, class A>
bool operator<(const hashed_array_tree<T, A>& v1,
const hashed_array_tree<T, A>& v2) {
unsigned int size = v1._size < v2._size ? v1._size : v2._size;
for (unsigned int i = 0; i < size; i++) {
if (v1[i] < v2[i])
return true;
else if (v1[i] > v2[i])
return false;
}
return (v1._size < v2._size);
}
};
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
/** A logarithm function that computes \lfloor \log_2(x) \rfloor in
LaTeX codes :-)
This function computes the 2-logarithm of the parameter rounded
down to the nearest integer.
\param x The integer to calculate the 2-logarithm for.
\return The rounded down result of the 2-logarithm function. */
inline unsigned int log_2 (unsigned int x) {
unsigned int r = 0;
x >>= 1;
while (x) {
r++;
x >>= 1;
}
return r;
}
/** A logarithm function that computes \lceil \log_2(x) \rceil.
This function computes the 2-logarithm of the parameter rounded up
to the nearest integer.
\param x The integer to calculate the 2-logarithm for.
\return The rounded down result of the 2-logarithm function.
*/
inline unsigned int log_2_ceil (unsigned int x) {
if (x == 0) return 0;
unsigned int x_copy = x;
unsigned int r = 0;
x >>= 1;
while (x) {
r++;
x >>= 1;
}
if (x_copy - (1<<r) != 0) r++;
return r;
}
/** A power-of-2 shorthand.
This define calculates the value of the power of two that is given
in the parameter. This is just to make the code easier to read.
\param x The power of 2 to calculate.
\return The computed power of 2.
*/
#define pow_2(x) (1 << x)
#endif
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net