--- /dev/null
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+#include <iostream>
+
+
+#include "binmap.h"
+
+using namespace swift;
+
+namespace swift {
+
+inline size_t _max_(const size_t x, const size_t y)
+{
+ return x < y ? y : x;
+}
+
+typedef binmap_t::ref_t ref_t;
+typedef binmap_t::bitmap_t bitmap_t;
+
+/* Bitmap constants */
+const bitmap_t BITMAP_EMPTY = static_cast<bitmap_t>(0);
+const bitmap_t BITMAP_FILLED = static_cast<bitmap_t>(-1);
+
+const bin_t::uint_t BITMAP_LAYER_BITS = 2 * 8 * sizeof(bitmap_t) - 1;
+
+const ref_t ROOT_REF = 0;
+
+#ifdef _MSC_VER
+# pragma warning (push)
+# pragma warning ( disable:4309 )
+#endif
+
+const bitmap_t BITMAP[] = {
+ static_cast<bitmap_t>(0x00000001), static_cast<bitmap_t>(0x00000003),
+ static_cast<bitmap_t>(0x00000002), static_cast<bitmap_t>(0x0000000f),
+ static_cast<bitmap_t>(0x00000004), static_cast<bitmap_t>(0x0000000c),
+ static_cast<bitmap_t>(0x00000008), static_cast<bitmap_t>(0x000000ff),
+ static_cast<bitmap_t>(0x00000010), static_cast<bitmap_t>(0x00000030),
+ static_cast<bitmap_t>(0x00000020), static_cast<bitmap_t>(0x000000f0),
+ static_cast<bitmap_t>(0x00000040), static_cast<bitmap_t>(0x000000c0),
+ static_cast<bitmap_t>(0x00000080), static_cast<bitmap_t>(0x0000ffff),
+ static_cast<bitmap_t>(0x00000100), static_cast<bitmap_t>(0x00000300),
+ static_cast<bitmap_t>(0x00000200), static_cast<bitmap_t>(0x00000f00),
+ static_cast<bitmap_t>(0x00000400), static_cast<bitmap_t>(0x00000c00),
+ static_cast<bitmap_t>(0x00000800), static_cast<bitmap_t>(0x0000ff00),
+ static_cast<bitmap_t>(0x00001000), static_cast<bitmap_t>(0x00003000),
+ static_cast<bitmap_t>(0x00002000), static_cast<bitmap_t>(0x0000f000),
+ static_cast<bitmap_t>(0x00004000), static_cast<bitmap_t>(0x0000c000),
+ static_cast<bitmap_t>(0x00008000), static_cast<bitmap_t>(0xffffffff),
+ static_cast<bitmap_t>(0x00010000), static_cast<bitmap_t>(0x00030000),
+ static_cast<bitmap_t>(0x00020000), static_cast<bitmap_t>(0x000f0000),
+ static_cast<bitmap_t>(0x00040000), static_cast<bitmap_t>(0x000c0000),
+ static_cast<bitmap_t>(0x00080000), static_cast<bitmap_t>(0x00ff0000),
+ static_cast<bitmap_t>(0x00100000), static_cast<bitmap_t>(0x00300000),
+ static_cast<bitmap_t>(0x00200000), static_cast<bitmap_t>(0x00f00000),
+ static_cast<bitmap_t>(0x00400000), static_cast<bitmap_t>(0x00c00000),
+ static_cast<bitmap_t>(0x00800000), static_cast<bitmap_t>(0xffff0000),
+ static_cast<bitmap_t>(0x01000000), static_cast<bitmap_t>(0x03000000),
+ static_cast<bitmap_t>(0x02000000), static_cast<bitmap_t>(0x0f000000),
+ static_cast<bitmap_t>(0x04000000), static_cast<bitmap_t>(0x0c000000),
+ static_cast<bitmap_t>(0x08000000), static_cast<bitmap_t>(0xff000000),
+ static_cast<bitmap_t>(0x10000000), static_cast<bitmap_t>(0x30000000),
+ static_cast<bitmap_t>(0x20000000), static_cast<bitmap_t>(0xf0000000),
+ static_cast<bitmap_t>(0x40000000), static_cast<bitmap_t>(0xc0000000),
+ static_cast<bitmap_t>(0x80000000), /* special */ static_cast<bitmap_t>(0xffffffff) /* special */
+};
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+
+/**
+ * Get the leftmost bin that corresponded to bitmap (the bin is filled in bitmap)
+ */
+bin_t::uint_t bitmap_to_bin(register bitmap_t b)
+{
+ static const unsigned char BITMAP_TO_BIN[] = {
+ 0xff, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 8, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 10, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 9, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 12, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 8, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 10, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 9, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 14, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 8, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 10, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 9, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 13, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 8, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 10, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 3,
+ 11, 0, 2, 1, 4, 0, 2, 1, 6, 0, 2, 1, 5, 0, 2, 7
+ };
+
+ assert (sizeof(bitmap_t) <= 4);
+ assert (b != BITMAP_EMPTY);
+
+ unsigned char t;
+
+ t = BITMAP_TO_BIN[ b & 0xff ];
+ if (t < 16) {
+ if (t != 7) {
+ return static_cast<bin_t::uint_t>(t);
+ }
+
+ b += 1;
+ b &= -b;
+ if (0 == b) {
+ return BITMAP_LAYER_BITS / 2;
+ }
+ if (0 == (b & 0xffff)) {
+ return 15;
+ }
+ return 7;
+ }
+
+ b >>= 8;
+ t = BITMAP_TO_BIN[ b & 0xff ];
+ if (t <= 15) {
+ return 16 + t;
+ }
+
+ /* Recursion */
+ // return 32 + bitmap_to_bin( b >> 8 );
+
+ assert (sizeof(bitmap_t) == 4);
+
+ b >>= 8;
+ t = BITMAP_TO_BIN[ b & 0xff ];
+ if (t < 16) {
+ if (t != 7) {
+ return 32 + static_cast<bin_t::uint_t>(t);
+ }
+
+ b += 1;
+ b &= -b;
+ if (0 == (b & 0xffff)) {
+ return 47;
+ }
+ return 39;
+ }
+
+ b >>= 8;
+ return 48 + BITMAP_TO_BIN[ b & 0xff ];
+}
+
+
+/**
+ * Get the leftmost bin that corresponded to bitmap (the bin is filled in bitmap)
+ */
+bin_t bitmap_to_bin(const bin_t& bin, const bitmap_t bitmap)
+{
+ assert (bitmap != BITMAP_EMPTY);
+
+ if (bitmap == BITMAP_FILLED) {
+ return bin;
+ }
+
+ return bin_t(bin.base_left().toUInt() + bitmap_to_bin(bitmap));
+}
+
+} /* namespace */
+
+
+/* Methods */
+
+
+/**
+ * Constructor
+ */
+binmap_t::binmap_t()
+ : root_bin_(63)
+{
+ assert (sizeof(bitmap_t) <= 4);
+
+ cell_ = NULL;
+ cells_number_ = 0;
+ allocated_cells_number_ = 0;
+ free_top_ = ROOT_REF;
+
+ const ref_t root_ref = alloc_cell();
+
+ assert (root_ref == ROOT_REF && cells_number_ > 0);
+}
+
+
+/**
+ * Destructor
+ */
+binmap_t::~binmap_t()
+{
+ if (cell_) {
+ free(cell_);
+ }
+}
+
+
+/**
+ * Allocates one cell (dirty allocation)
+ */
+ref_t binmap_t::_alloc_cell()
+{
+ assert (allocated_cells_number_ < cells_number_);
+
+ /* Pop an element from the free cell list */
+ const ref_t ref = free_top_;
+ assert (cell_[ref].is_free_);
+
+ free_top_ = cell_[ ref ].free_next_;
+
+ assert (!(cell_[ ref ].is_free_ = false)); /* Reset flag in DEBUG */
+
+ ++allocated_cells_number_;
+
+ return ref;
+}
+
+
+/**
+ * Allocates one cell
+ */
+ref_t binmap_t::alloc_cell()
+{
+ if (!reserve_cells(1)) {
+ return ROOT_REF /* MEMORY ERROR or OVERFLOW ERROR */;
+ }
+
+ const ref_t ref = _alloc_cell();
+
+ /* Cleans cell */
+ memset(&cell_[ref], 0, sizeof(cell_[0]));
+
+ return ref;
+}
+
+
+/**
+ * Reserve cells allocation capacity
+ */
+bool binmap_t::reserve_cells(size_t count)
+{
+ if (cells_number_ - allocated_cells_number_ < count) {
+ /* Finding new sizeof of the buffer */
+ const size_t old_cells_number = cells_number_;
+ const size_t new_cells_number = _max_(16U, _max_(2 * old_cells_number, allocated_cells_number_ + count));
+
+ /* Check for reference capacity */
+ if (static_cast<ref_t>(new_cells_number) < old_cells_number) {
+ fprintf(stderr, "Warning: binmap_t::reserve_cells: REFERENCE LIMIT ERROR\n");
+ return false /* REFERENCE LIMIT ERROR */;
+ }
+
+ /* Check for integer overflow */
+ static const size_t MAX_NUMBER = (static_cast<size_t>(-1) / sizeof(cell_[0]));
+ if (MAX_NUMBER < new_cells_number) {
+ fprintf(stderr, "Warning: binmap_t::reserve_cells: INTEGER OVERFLOW\n");
+ return false /* INTEGER OVERFLOW */;
+ }
+
+ /* Reallocate memory */
+ cell_t* const cell = static_cast<cell_t*>(realloc(cell_, new_cells_number * sizeof(cell_[0])));
+ if (cell == NULL) {
+ fprintf(stderr, "Warning: binmap_t::reserve_cells: MEMORY ERROR\n");
+ return false /* MEMORY ERROR */;
+ }
+
+ cell_ = cell;
+ cells_number_ = new_cells_number;
+
+ /* Insert new cells to the free cell list */
+ const size_t stop_idx = old_cells_number - 1;
+ size_t idx = new_cells_number - 1;
+
+ cell_[ idx ].is_free_ = true;
+ cell_[ idx ].free_next_ = free_top_;
+
+ for (--idx; idx != stop_idx; --idx) {
+ cell_[ idx ].is_free_ = true;
+ cell_[ idx ].free_next_ = static_cast<ref_t>(idx + 1);
+ }
+
+ free_top_ = static_cast<ref_t>(old_cells_number);
+ }
+
+ return true;
+}
+
+
+/**
+ * Releases the cell
+ */
+void binmap_t::free_cell(ref_t ref)
+{
+ assert (ref > 0);
+ assert (!cell_[ref].is_free_);
+
+ if (cell_[ref].is_left_ref_) {
+ free_cell(cell_[ref].left_.ref_);
+ }
+ if (cell_[ref].is_right_ref_) {
+ free_cell(cell_[ref].right_.ref_);
+ }
+ assert ((cell_[ref].is_free_ = true)); /* Set flag in DEBUG */
+ cell_[ref].free_next_ = free_top_;
+
+ free_top_ = ref;
+
+ --allocated_cells_number_;
+}
+
+
+/**
+ * Extend root
+ */
+bool binmap_t::extend_root()
+{
+ assert (!root_bin_.is_all());
+
+ if (!cell_[ROOT_REF].is_left_ref_ && !cell_[ROOT_REF].is_right_ref_ && cell_[ROOT_REF].left_.bitmap_ == cell_[ROOT_REF].right_.bitmap_) {
+ /* Setup the root cell */
+ cell_[ROOT_REF].right_.bitmap_ = BITMAP_EMPTY;
+
+ } else {
+ /* Allocate new cell */
+ const ref_t ref = alloc_cell();
+ if (ref == ROOT_REF) {
+ return false /* ALLOC ERROR */;
+ }
+
+ /* Move old root to the cell */
+ cell_[ref] = cell_[ROOT_REF];
+
+ /* Setup new root */
+ cell_[ROOT_REF].is_left_ref_ = true;
+ cell_[ROOT_REF].is_right_ref_ = false;
+
+ cell_[ROOT_REF].left_.ref_ = ref;
+ cell_[ROOT_REF].right_.bitmap_ = BITMAP_EMPTY;
+ }
+
+ /* Reset bin */
+ root_bin_.to_parent();
+ return true;
+}
+
+
+/**
+ * Pack a trace of cells
+ */
+void binmap_t::pack_cells(ref_t* href)
+{
+ ref_t ref = *href--;
+ if (ref == ROOT_REF) {
+ return;
+ }
+
+ if (cell_[ref].is_left_ref_ || cell_[ref].is_right_ref_ ||
+ cell_[ref].left_.bitmap_ != cell_[ref].right_.bitmap_) {
+ return;
+ }
+
+ const bitmap_t bitmap = cell_[ref].left_.bitmap_;
+
+ do {
+ ref = *href--;
+
+ if (!cell_[ref].is_left_ref_) {
+ if (cell_[ref].left_.bitmap_ != bitmap) {
+ break;
+ }
+
+ } else if (!cell_[ref].is_right_ref_) {
+ if (cell_[ref].right_.bitmap_ != bitmap) {
+ break;
+ }
+
+ } else {
+ break;
+ }
+
+ } while (ref != ROOT_REF);
+
+ const ref_t par_ref = href[2];
+
+ if (cell_[ref].is_left_ref_ && cell_[ref].left_.ref_ == par_ref) {
+ cell_[ref].is_left_ref_ = false;
+ cell_[ref].left_.bitmap_ = bitmap;
+ } else {
+ cell_[ref].is_right_ref_ = false;
+ cell_[ref].right_.bitmap_ = bitmap;
+ }
+
+ free_cell(par_ref);
+}
+
+
+/**
+ * Whether binmap is empty
+ */
+bool binmap_t::is_empty() const
+{
+ const cell_t& cell = cell_[ROOT_REF];
+
+ return !cell.is_left_ref_ && !cell.is_right_ref_ &&
+ cell.left_.bitmap_ == BITMAP_EMPTY && cell.right_.bitmap_ == BITMAP_EMPTY;
+}
+
+
+/**
+ * Whether binmap is filled
+ */
+bool binmap_t::is_filled() const
+{
+ const cell_t& cell = cell_[ROOT_REF];
+
+ return root_bin_.is_all() && !cell.is_left_ref_ && !cell.is_right_ref_ &&
+ cell.left_.bitmap_ == BITMAP_FILLED && cell.right_.bitmap_ == BITMAP_FILLED;
+}
+
+
+/**
+ * Whether range/bin is empty
+ */
+bool binmap_t::is_empty(const bin_t& bin) const
+{
+ /* Process hi-layers case */
+ if (!root_bin_.contains(bin)) {
+ return !bin.contains(root_bin_) || is_empty();
+ }
+
+ /* Trace the bin */
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ trace(&cur_ref, &cur_bin, bin);
+
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ /* Process common case */
+ const cell_t& cell = cell_[cur_ref];
+
+ if (bin.layer_bits() > BITMAP_LAYER_BITS) {
+ if (bin < cur_bin) {
+ return cell.left_.bitmap_ == BITMAP_EMPTY;
+ }
+ if (cur_bin < bin) {
+ return cell.right_.bitmap_ == BITMAP_EMPTY;
+ }
+ return !cell.is_left_ref_ && !cell.is_right_ref_ &&
+ cell.left_.bitmap_ == BITMAP_EMPTY && cell.right_.bitmap_ == BITMAP_EMPTY;
+ }
+
+ /* Process low-layers case */
+ assert (bin != cur_bin);
+
+ const bitmap_t bm1 = (bin < cur_bin) ? cell.left_.bitmap_ : cell.right_.bitmap_;
+ const bitmap_t bm2 = BITMAP[ BITMAP_LAYER_BITS & bin.toUInt() ];
+
+ return (bm1 & bm2) == BITMAP_EMPTY;
+}
+
+
+/**
+ * Whether range/bin is filled
+ */
+bool binmap_t::is_filled(const bin_t& bin) const
+{
+ /* Process hi-layers case */
+ if (!root_bin_.contains(bin)) {
+ return false;
+ }
+
+ /* Trace the bin */
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ trace(&cur_ref, &cur_bin, bin);
+
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ /* Process common case */
+ const cell_t& cell = cell_[cur_ref];
+
+ if (bin.layer_bits() > BITMAP_LAYER_BITS) {
+ if (bin < cur_bin) {
+ return cell.left_.bitmap_ == BITMAP_FILLED;
+ }
+ if (cur_bin < bin) {
+ return cell.right_.bitmap_ == BITMAP_FILLED;
+ }
+ return !cell.is_left_ref_ && !cell.is_right_ref_ &&
+ cell.left_.bitmap_ == BITMAP_FILLED && cell.right_.bitmap_ == BITMAP_FILLED;
+ }
+
+ /* Process low-layers case */
+ assert (bin != cur_bin);
+
+ const bitmap_t bm1 = (bin < cur_bin) ? cell.left_.bitmap_ : cell.right_.bitmap_;
+ const bitmap_t bm2 = BITMAP[ BITMAP_LAYER_BITS & bin.toUInt() ];
+
+ return (bm1 & bm2) == bm2;
+}
+
+
+/**
+ * Return the topmost solid bin which covers the specified bin
+ */
+bin_t binmap_t::cover(const bin_t& bin) const
+{
+ /* Process hi-layers case */
+ if (!root_bin_.contains(bin)) {
+ if (!bin.contains(root_bin_)) {
+ return root_bin_.sibling();
+ }
+ if (is_empty()) {
+ return bin_t::ALL;
+ }
+ return bin_t::NONE;
+ }
+
+ /* Trace the bin */
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ trace(&cur_ref, &cur_bin, bin);
+
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ /* Process common case */
+ const cell_t& cell = cell_[cur_ref];
+
+ if (bin.layer_bits() > BITMAP_LAYER_BITS) {
+ if (bin < cur_bin) {
+ if (cell.left_.bitmap_ == BITMAP_EMPTY || cell.left_.bitmap_ == BITMAP_FILLED) {
+ return cur_bin.left();
+ }
+ return bin_t::NONE;
+ }
+ if (cur_bin < bin) {
+ if (cell.right_.bitmap_ == BITMAP_EMPTY || cell.right_.bitmap_ == BITMAP_FILLED) {
+ return cur_bin.right();
+ }
+ return bin_t::NONE;
+ }
+ if (cell.is_left_ref_ || cell.is_right_ref_) {
+ return bin_t::NONE;
+ }
+ if (cell.left_.bitmap_ != cell.right_.bitmap_) {
+ return bin_t::NONE;
+ }
+ assert (cur_bin == root_bin_);
+ if (cell.left_.bitmap_ == BITMAP_EMPTY) {
+ return bin_t::ALL;
+ }
+ if (cell.left_.bitmap_ == BITMAP_FILLED) {
+ return cur_bin;
+ }
+ return bin_t::NONE;
+ }
+
+ /* Process low-layers case */
+ assert (bin != cur_bin);
+
+ bitmap_t bm1;
+ if (bin < cur_bin) {
+ bm1 = cell.left_.bitmap_;
+ cur_bin.to_left();
+ } else {
+ bm1 = cell.right_.bitmap_;
+ cur_bin.to_right();
+ }
+
+ if (bm1 == BITMAP_EMPTY) {
+ if (is_empty()) {
+ return bin_t::ALL;
+ }
+ return cur_bin;
+ }
+ if (bm1 == BITMAP_FILLED) {
+ if (is_filled()) {
+ return bin_t::ALL;
+ }
+ return cur_bin;
+ }
+
+ /* Trace the bitmap */
+ bin_t b = bin;
+ bitmap_t bm2 = BITMAP[ BITMAP_LAYER_BITS & b.toUInt() ];
+
+ if ((bm1 & bm2) == BITMAP_EMPTY) {
+ do {
+ cur_bin = b;
+ b.to_parent();
+ bm2 = BITMAP[ BITMAP_LAYER_BITS & b.toUInt() ];
+ } while ((bm1 & bm2) == BITMAP_EMPTY);
+
+ return cur_bin;
+
+ } else if ((bm1 & bm2) == bm2) {
+ do {
+ cur_bin = b;
+ b.to_parent();
+ bm2 = BITMAP[ BITMAP_LAYER_BITS & b.toUInt() ];
+ } while ((bm1 & bm2) == bm2);
+
+ return cur_bin;
+ }
+
+ return bin_t::NONE;
+}
+
+
+/**
+ * Find first empty bin
+ */
+bin_t binmap_t::find_empty() const
+{
+ /* Trace the bin */
+ bitmap_t bitmap = BITMAP_FILLED;
+
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ do {
+ /* Processing the root */
+ if (cell_[ROOT_REF].is_left_ref_) {
+ cur_ref = cell_[ROOT_REF].left_.ref_;
+ cur_bin = root_bin_.left();
+ } else if (cell_[ROOT_REF].left_.bitmap_ != BITMAP_FILLED) {
+ if (cell_[ ROOT_REF].left_.bitmap_ == BITMAP_EMPTY) {
+ if (!cell_[ ROOT_REF].is_right_ref_ && cell_[ ROOT_REF ].right_.bitmap_ == BITMAP_EMPTY) {
+ return bin_t::ALL;
+ }
+ return root_bin_.left();
+ }
+ bitmap = cell_[ROOT_REF].left_.bitmap_;
+ cur_bin = root_bin_.left();
+ break;
+ } else if (cell_[ROOT_REF].is_right_ref_) {
+ cur_ref = cell_[ROOT_REF].right_.ref_;
+ cur_bin = root_bin_.right();
+ } else {
+ if (cell_[ROOT_REF].right_.bitmap_ == BITMAP_FILLED) {
+ if (root_bin_.is_all()) {
+ return bin_t::NONE;
+ }
+ return root_bin_.sibling();
+ }
+ bitmap = cell_[ROOT_REF].right_.bitmap_;
+ cur_bin = root_bin_.right();
+ break;
+ }
+
+ /* Processing middle layers */
+ for ( ;;) {
+ if (cell_[cur_ref].is_left_ref_) {
+ cur_ref = cell_[cur_ref].left_.ref_;
+ cur_bin.to_left();
+ } else if (cell_[cur_ref].left_.bitmap_ != BITMAP_FILLED) {
+ bitmap = cell_[cur_ref].left_.bitmap_;
+ cur_bin.to_left();
+ break;
+ } else if (cell_[cur_ref].is_right_ref_) {
+ cur_ref = cell_[cur_ref].right_.ref_;
+ cur_bin.to_right();
+ } else {
+ assert (cell_[cur_ref].right_.bitmap_ != BITMAP_FILLED);
+ bitmap = cell_[cur_ref].right_.bitmap_;
+ cur_bin.to_right();
+ break;
+ }
+ }
+
+ } while (false);
+
+ /* Getting result */
+ assert (bitmap != BITMAP_FILLED);
+
+ return bitmap_to_bin(cur_bin, ~bitmap);
+}
+
+
+/**
+ * Find first filled bin
+ */
+bin_t binmap_t::find_filled() const
+{
+ /* Trace the bin */
+ bitmap_t bitmap = BITMAP_EMPTY;
+
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ do {
+ /* Processing the root */
+ if (cell_[ROOT_REF].is_left_ref_) {
+ cur_ref = cell_[ROOT_REF].left_.ref_;
+ cur_bin = root_bin_.left();
+ } else if (cell_[ROOT_REF].left_.bitmap_ != BITMAP_EMPTY) {
+ if (cell_[ ROOT_REF].left_.bitmap_ == BITMAP_FILLED) {
+ if (!cell_[ ROOT_REF].is_right_ref_ && cell_[ ROOT_REF ].right_.bitmap_ == BITMAP_FILLED) {
+ return root_bin_;
+ }
+ return root_bin_.left();
+ }
+ bitmap = cell_[ROOT_REF].left_.bitmap_;
+ cur_bin = root_bin_.left();
+ break;
+ } else if (cell_[ROOT_REF].is_right_ref_) {
+ cur_ref = cell_[ROOT_REF].right_.ref_;
+ cur_bin = root_bin_.right();
+ } else {
+ if (cell_[ROOT_REF].right_.bitmap_ == BITMAP_EMPTY) {
+ return bin_t::NONE;
+ }
+ bitmap = cell_[ROOT_REF].right_.bitmap_;
+ cur_bin = root_bin_.right();
+ break;
+ }
+
+ /* Processing middle layers */
+ for ( ;;) {
+ if (cell_[cur_ref].is_left_ref_) {
+ cur_ref = cell_[cur_ref].left_.ref_;
+ cur_bin.to_left();
+ } else if (cell_[cur_ref].left_.bitmap_ != BITMAP_EMPTY) {
+ bitmap = cell_[cur_ref].left_.bitmap_;
+ cur_bin.to_left();
+ break;
+ } else if (cell_[cur_ref].is_right_ref_) {
+ cur_ref = cell_[cur_ref].right_.ref_;
+ cur_bin.to_right();
+ } else {
+ assert (cell_[cur_ref].right_.bitmap_ != BITMAP_EMPTY);
+ bitmap = cell_[cur_ref].right_.bitmap_;
+ cur_bin.to_right();
+ break;
+ }
+ }
+
+ } while (false);
+
+ /* Getting result */
+ assert (bitmap != BITMAP_EMPTY);
+
+ return bitmap_to_bin(cur_bin, bitmap);
+}
+
+
+#define LR_LEFT (0x00)
+#define RL_RIGHT (0x01)
+#define RL_LEFT (0x02)
+#define LR_RIGHT (0x03)
+
+
+#define SSTACK() \
+ int _top_ = 0; \
+ bin_t _bin_[64]; \
+ ref_t _sref_[64]; \
+ char _dir_[64];
+
+#define DSTACK() \
+ int _top_ = 0; \
+ bin_t _bin_[64]; \
+ ref_t _dref_[64]; \
+ char _dir_[64];
+
+#define SDSTACK() \
+ int _top_ = 0; \
+ bin_t _bin_[64]; \
+ ref_t _sref_[64]; \
+ ref_t _dref_[64]; \
+ char _dir_[64];
+
+
+#define SPUSH(b, sr, twist) \
+ do { \
+ _bin_[_top_] = b; \
+ _sref_[_top_] = sr; \
+ _dir_[_top_] = (0 != (twist & (b.base_length() >> 1))); \
+ ++_top_; \
+ } while (false)
+
+#define DPUSH(b, dr, twist) \
+ do { \
+ _bin_[_top_] = b; \
+ _dref_[_top_] = dr; \
+ _dir_[_top_] = (0 != (twist & (b.base_length() >> 1))); \
+ ++_top_; \
+ } while (false)
+
+#define SDPUSH(b, sr, dr, twist) \
+ do { \
+ _bin_[_top_] = b; \
+ _sref_[_top_] = sr; \
+ _dref_[_top_] = dr; \
+ _dir_[_top_] = (0 != (twist & (b.base_length() >> 1))); \
+ ++_top_; \
+ } while (false)
+
+
+#define SPOP() \
+ assert (_top_ < 65); \
+ --_top_; \
+ const bin_t b = _bin_[_top_]; \
+ const cell_t& sc = source.cell_[_sref_[_top_]]; \
+ const bool is_left = !(_dir_[_top_] & 0x01); \
+ if (0 == (_dir_[_top_] & 0x02)) { \
+ _dir_[_top_++] ^= 0x03; \
+ }
+
+#define DPOP() \
+ assert (_top_ < 65); \
+ --_top_; \
+ const bin_t b = _bin_[_top_]; \
+ const cell_t& dc = destination.cell_[_dref_[_top_]]; \
+ const bool is_left = !(_dir_[_top_] & 0x01); \
+ if (0 == (_dir_[_top_] & 0x02)) { \
+ _dir_[_top_++] ^= 0x03; \
+ }
+
+#define SDPOP() \
+ assert (_top_ < 65); \
+ --_top_; \
+ const bin_t b = _bin_[_top_]; \
+ const cell_t& sc = source.cell_[_sref_[_top_]]; \
+ const cell_t& dc = destination.cell_[_dref_[_top_]]; \
+ const bool is_left = !(_dir_[_top_] & 0x01); \
+ if (0 == (_dir_[_top_] & 0x02)) { \
+ _dir_[_top_++] ^= 0x03; \
+ }
+
+
+/**
+ * Find first additional bin in source
+ *
+ * @param destination
+ * the destination binmap
+ * @param source
+ * the source binmap
+ */
+bin_t binmap_t::find_complement(const binmap_t& destination, const binmap_t& source, const bin_t::uint_t twist)
+{
+ return find_complement(destination, source, bin_t::ALL, twist);
+
+ if (destination.is_empty()) {
+ const cell_t& cell = source.cell_[ROOT_REF];
+ if (!cell.is_left_ref_ && !cell.is_right_ref_ && cell.left_.bitmap_ == BITMAP_FILLED && cell.right_.bitmap_ == BITMAP_FILLED) {
+ return source.root_bin_;
+ }
+ return _find_complement(source.root_bin_, BITMAP_EMPTY, ROOT_REF, source, twist);
+ }
+
+ if (destination.root_bin_.contains(source.root_bin_)) {
+ ref_t dref;
+ bin_t dbin;
+
+ destination.trace(&dref, &dbin, source.root_bin_);
+
+ if (dbin == source.root_bin_) {
+ return binmap_t::_find_complement(dbin, dref, destination, ROOT_REF, source, twist);
+ }
+
+ assert (source.root_bin_ < dbin);
+
+ if (destination.cell_[dref].left_.bitmap_ != BITMAP_FILLED) {
+ if (destination.cell_[dref].left_.bitmap_ == BITMAP_EMPTY) {
+ const cell_t& cell = source.cell_[ROOT_REF];
+ if (!cell.is_left_ref_ && !cell.is_right_ref_ && cell.left_.bitmap_ == BITMAP_FILLED && cell.right_.bitmap_ == BITMAP_FILLED) {
+ return source.root_bin_;
+ }
+ }
+ return binmap_t::_find_complement(source.root_bin_, destination.cell_[dref].left_.bitmap_, ROOT_REF, source, twist);
+ }
+
+ return bin_t::NONE;
+
+ } else {
+ SSTACK();
+
+ /* Initialization */
+ SPUSH(source.root_bin_, ROOT_REF, twist);
+
+ /* Main loop */
+ do {
+ SPOP();
+
+ if (is_left) {
+ if (b.left() == destination.root_bin_) {
+ if (sc.is_left_ref_) {
+ const bin_t res = binmap_t::_find_complement(destination.root_bin_, ROOT_REF, destination, sc.left_.ref_, source, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ } else if (sc.left_.bitmap_ != BITMAP_EMPTY) {
+ const bin_t res = binmap_t::_find_complement(destination.root_bin_, ROOT_REF, destination, sc.left_.bitmap_, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ }
+ continue;
+ }
+
+ if (sc.is_left_ref_) {
+ SPUSH(b.left(), sc.left_.ref_, twist);
+ continue;
+
+ } else if (sc.left_.bitmap_ != BITMAP_EMPTY) {
+ if (0 == (twist & (b.left().base_length() - 1) & ~(destination.root_bin_.base_length() - 1))) {
+ const bin_t res = binmap_t::_find_complement(destination.root_bin_, ROOT_REF, destination, sc.left_.bitmap_, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ return binmap_t::_find_complement(destination.root_bin_.sibling(), BITMAP_EMPTY, sc.left_.bitmap_, twist);
+
+ } else if (sc.left_.bitmap_ != BITMAP_FILLED) {
+ return binmap_t::_find_complement(b.left(), BITMAP_EMPTY, sc.left_.bitmap_, twist);
+
+ } else {
+ bin_t::uint_t s = twist & (b.left().base_length() - 1);
+ /* Sorry for the following hardcode hack: Flow the highest bit of s */
+ s |= s >> 1; s |= s >> 2;
+ s |= s >> 4; s |= s >> 8;
+ s |= s >> 16;
+ s |= (s >> 16) >> 16; // FIXME: hide warning
+ return bin_t(s + 1 + (s >> 1)); /* bin_t(s >> 1).sibling(); */
+ }
+ }
+
+ } else {
+ if (sc.is_right_ref_) {
+ return binmap_t::_find_complement(b.right(), BITMAP_EMPTY, sc.right_.ref_, source, twist);
+ } else if (sc.right_.bitmap_ != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.right(), BITMAP_EMPTY, sc.right_.bitmap_, twist);
+ }
+ continue;
+ }
+ } while (_top_ > 0);
+
+ return bin_t::NONE;
+ }
+}
+
+
+bin_t binmap_t::find_complement(const binmap_t& destination, const binmap_t& source, bin_t range, const bin_t::uint_t twist)
+{
+ ref_t sref = ROOT_REF;
+ bitmap_t sbitmap = BITMAP_EMPTY;
+ bool is_sref = true;
+
+ if (range.contains(source.root_bin_)) {
+ range = source.root_bin_;
+ is_sref = true;
+ sref = ROOT_REF;
+
+ } else if (source.root_bin_.contains(range)) {
+ bin_t sbin;
+ source.trace(&sref, &sbin, range);
+
+ if (range == sbin) {
+ is_sref = true;
+ } else {
+ is_sref = false;
+
+ if (range < sbin) {
+ sbitmap = source.cell_[sref].left_.bitmap_;
+ } else {
+ sbitmap = source.cell_[sref].right_.bitmap_;
+ }
+
+ sbitmap &= BITMAP[ BITMAP_LAYER_BITS & range.toUInt() ];
+
+ if (sbitmap == BITMAP_EMPTY) {
+ return bin_t::NONE;
+ }
+ }
+
+ } else {
+ return bin_t::NONE;
+ }
+
+ assert (is_sref || sbitmap != BITMAP_EMPTY);
+
+ if (destination.is_empty()) {
+ if (is_sref) {
+ const cell_t& cell = source.cell_[sref];
+ if (!cell.is_left_ref_ && !cell.is_right_ref_ && cell.left_.bitmap_ == BITMAP_FILLED && cell.right_.bitmap_ == BITMAP_FILLED) {
+ return range;
+ } else {
+ return _find_complement(range, BITMAP_EMPTY, sref, source, twist);
+ }
+ } else {
+ return _find_complement(range, BITMAP_EMPTY, sbitmap, twist);
+ }
+ }
+
+ if (destination.root_bin_.contains(range)) {
+ ref_t dref;
+ bin_t dbin;
+ destination.trace(&dref, &dbin, range);
+
+ if (range == dbin) {
+ if (is_sref) {
+ return _find_complement(range, dref, destination, sref, source, twist);
+ } else {
+ return _find_complement(range, dref, destination, sbitmap, twist);
+ }
+
+ } else {
+ bitmap_t dbitmap;
+
+ if (range < dbin) {
+ dbitmap = destination.cell_[dref].left_.bitmap_;
+ } else {
+ dbitmap = destination.cell_[dref].right_.bitmap_;
+ }
+
+ if (dbitmap == BITMAP_FILLED) {
+ return bin_t::NONE;
+
+ } else if (is_sref) {
+ if (dbitmap == BITMAP_EMPTY) {
+ const cell_t& cell = source.cell_[sref];
+ if (!cell.is_left_ref_ && !cell.is_right_ref_ && cell.left_.bitmap_ == BITMAP_FILLED && cell.right_.bitmap_ == BITMAP_FILLED) {
+ return range;
+ }
+ }
+
+ return _find_complement(range, dbitmap, sref, source, twist);
+
+ } else {
+ if ((sbitmap & ~dbitmap) != BITMAP_EMPTY) {
+ return _find_complement(range, dbitmap, sbitmap, twist);
+ } else {
+ return bin_t::NONE;
+ }
+ }
+ }
+
+ } else if (!range.contains(destination.root_bin_)) {
+ if (is_sref) {
+ return _find_complement(range, BITMAP_EMPTY, sref, source, twist);
+ } else {
+ return _find_complement(range, BITMAP_EMPTY, sbitmap, twist);
+ }
+
+ } else { // range.contains(destination.m_root_bin)
+ if (is_sref) {
+ SSTACK();
+
+ SPUSH(range, sref, twist);
+
+ do {
+ SPOP();
+
+ if (is_left) {
+ if (b.left() == destination.root_bin_) {
+ if (sc.is_left_ref_) {
+ const bin_t res = binmap_t::_find_complement(destination.root_bin_, ROOT_REF, destination, sc.left_.ref_, source, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ } else if (sc.left_.bitmap_ != BITMAP_EMPTY) {
+ const bin_t res = binmap_t::_find_complement(destination.root_bin_, ROOT_REF, destination, sc.left_.bitmap_, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ }
+ continue;
+ }
+
+ if (sc.is_left_ref_) {
+ SPUSH(b.left(), sc.left_.ref_, twist);
+ continue;
+
+ } else if (sc.left_.bitmap_ != BITMAP_EMPTY) {
+ if (0 == (twist & (b.left().base_length() - 1) & ~(destination.root_bin_.base_length() - 1))) {
+ const bin_t res = binmap_t::_find_complement(destination.root_bin_, ROOT_REF, destination, sc.left_.bitmap_, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ return binmap_t::_find_complement(destination.root_bin_.sibling(), BITMAP_EMPTY, sc.left_.bitmap_, twist);
+
+ } else if (sc.left_.bitmap_ != BITMAP_FILLED) {
+ return binmap_t::_find_complement(b.left(), BITMAP_EMPTY, sc.left_.bitmap_, twist);
+
+ } else {
+ bin_t::uint_t s = twist & (b.left().base_length() - 1);
+ /* Sorry for the following hardcode hack: Flow the highest bit of s */
+ s |= s >> 1; s |= s >> 2;
+ s |= s >> 4; s |= s >> 8;
+ s |= s >> 16;
+ s |= (s >> 16) >> 16; // FIXME: hide warning
+ return bin_t(s + 1 + (s >> 1)); /* bin_t(s >> 1).sibling(); */
+ }
+ }
+
+ } else {
+ if (sc.is_right_ref_) {
+ return binmap_t::_find_complement(b.right(), BITMAP_EMPTY, sc.right_.ref_, source, twist);
+ } else if (sc.right_.bitmap_ != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.right(), BITMAP_EMPTY, sc.right_.bitmap_, twist);
+ }
+ continue;
+ }
+ } while (_top_ > 0);
+
+ return bin_t::NONE;
+
+ } else {
+ if (0 == (twist & (range.base_length() - 1) & ~(destination.root_bin_.base_length() - 1))) {
+ const bin_t res = binmap_t::_find_complement(destination.root_bin_, ROOT_REF, destination, sbitmap, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ return binmap_t::_find_complement(destination.root_bin_.sibling(), BITMAP_EMPTY, sbitmap, twist);
+
+ } else if (sbitmap != BITMAP_FILLED) {
+ return binmap_t::_find_complement(range, BITMAP_EMPTY, sbitmap, twist);
+
+ } else {
+ bin_t::uint_t s = twist & (range.base_length() - 1);
+ /* Sorry for the following hardcode hack: Flow the highest bit of s */
+ s |= s >> 1; s |= s >> 2;
+ s |= s >> 4; s |= s >> 8;
+ s |= s >> 16;
+ s |= (s >> 16) >> 16; // FIXME: hide warning
+ return bin_t(s + 1 + (s >> 1)); /* bin_t(s >> 1).sibling(); */
+ }
+ }
+ }
+}
+
+
+bin_t binmap_t::_find_complement(const bin_t& bin, const ref_t dref, const binmap_t& destination, const ref_t sref, const binmap_t& source, const bin_t::uint_t twist)
+{
+ /* Initialization */
+ SDSTACK();
+ SDPUSH(bin, sref, dref, twist);
+
+ /* Main loop */
+ do {
+ SDPOP();
+
+ if (is_left) {
+ if (sc.is_left_ref_) {
+ if (dc.is_left_ref_) {
+ SDPUSH(b.left(), sc.left_.ref_, dc.left_.ref_, twist);
+ continue;
+
+ } else if (dc.left_.bitmap_ != BITMAP_FILLED) {
+ const bin_t res = binmap_t::_find_complement(b.left(), dc.left_.bitmap_, sc.left_.ref_, source, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ continue;
+ }
+
+ } else if (sc.left_.bitmap_ != BITMAP_EMPTY) {
+ if (dc.is_left_ref_) {
+ const bin_t res = binmap_t::_find_complement(b.left(), dc.left_.ref_, destination, sc.left_.bitmap_, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ continue;
+
+ } else if ((sc.left_.bitmap_ & ~dc.left_.bitmap_) != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.left(), dc.left_.bitmap_, sc.left_.bitmap_, twist);
+ }
+ }
+
+ } else {
+ if (sc.is_right_ref_) {
+ if (dc.is_right_ref_) {
+ SDPUSH(b.right(), sc.right_.ref_, dc.right_.ref_, twist);
+ continue;
+
+ } else if (dc.right_.bitmap_ != BITMAP_FILLED) {
+ const bin_t res = binmap_t::_find_complement(b.right(), dc.right_.bitmap_, sc.right_.ref_, source, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ continue;
+ }
+
+ } else if (sc.right_.bitmap_ != BITMAP_EMPTY) {
+ if (dc.is_right_ref_) {
+ const bin_t res = binmap_t::_find_complement(b.right(), dc.right_.ref_, destination, sc.right_.bitmap_, twist);
+ if (!res.is_none()) {
+ return res;
+ }
+ continue;
+
+ } else if ((sc.right_.bitmap_ & ~dc.right_.bitmap_) != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.right(), dc.right_.bitmap_, sc.right_.bitmap_, twist);
+ }
+ }
+ }
+ } while (_top_ > 0);
+
+ return bin_t::NONE;
+}
+
+
+bin_t binmap_t::_find_complement(const bin_t& bin, const bitmap_t dbitmap, const ref_t sref, const binmap_t& source, const bin_t::uint_t twist)
+{
+ assert (dbitmap != BITMAP_EMPTY || sref != ROOT_REF ||
+ source.cell_[ROOT_REF].is_left_ref_ ||
+ source.cell_[ROOT_REF].is_right_ref_ ||
+ source.cell_[ROOT_REF].left_.bitmap_ != BITMAP_FILLED ||
+ source.cell_[ROOT_REF].right_.bitmap_ != BITMAP_FILLED);
+
+ /* Initialization */
+ SSTACK();
+ SPUSH(bin, sref, twist);
+
+ /* Main loop */
+ do {
+ SPOP();
+
+ if (is_left) {
+ if (sc.is_left_ref_) {
+ SPUSH(b.left(), sc.left_.ref_, twist);
+ continue;
+ } else if ((sc.left_.bitmap_ & ~dbitmap) != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.left(), dbitmap, sc.left_.bitmap_, twist);
+ }
+
+ } else {
+ if (sc.is_right_ref_) {
+ SPUSH(b.right(), sc.right_.ref_, twist);
+ continue;
+ } else if ((sc.right_.bitmap_ & ~dbitmap) != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.right(), dbitmap, sc.right_.bitmap_, twist);
+ }
+ }
+ } while (_top_ > 0);
+
+ return bin_t::NONE;
+}
+
+
+bin_t binmap_t::_find_complement(const bin_t& bin, const ref_t dref, const binmap_t& destination, const bitmap_t sbitmap, const bin_t::uint_t twist)
+{
+ /* Initialization */
+ DSTACK();
+ DPUSH(bin, dref, twist);
+
+ /* Main loop */
+ do {
+ DPOP();
+
+ if (is_left) {
+ if (dc.is_left_ref_) {
+ DPUSH(b.left(), dc.left_.ref_, twist);
+ continue;
+
+ } else if ((sbitmap & ~dc.left_.bitmap_) != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.left(), dc.left_.bitmap_, sbitmap, twist);
+ }
+
+ } else {
+ if (dc.is_right_ref_) {
+ DPUSH(b.right(), dc.right_.ref_, twist);
+ continue;
+
+ } else if ((sbitmap & ~dc.right_.bitmap_) != BITMAP_EMPTY) {
+ return binmap_t::_find_complement(b.right(), dc.right_.bitmap_, sbitmap, twist);
+ }
+ }
+ } while (_top_ > 0);
+
+ return bin_t::NONE;
+}
+
+
+bin_t binmap_t::_find_complement(const bin_t& bin, const bitmap_t dbitmap, const bitmap_t sbitmap, bin_t::uint_t twist)
+{
+ bitmap_t bitmap = sbitmap & ~dbitmap;
+
+ assert (bitmap != BITMAP_EMPTY);
+
+ if (bitmap == BITMAP_FILLED) {
+ return bin;
+ }
+
+ twist &= bin.base_length() - 1;
+
+ if (sizeof(bitmap_t) == 2) {
+ if (twist & 1) {
+ bitmap = ((bitmap & 0x5555) << 1) | ((bitmap & 0xAAAA) >> 1);
+ }
+ if (twist & 2) {
+ bitmap = ((bitmap & 0x3333) << 2) | ((bitmap & 0xCCCC) >> 2);
+ }
+ if (twist & 4) {
+ bitmap = ((bitmap & 0x0f0f) << 4) | ((bitmap & 0xf0f0) >> 4);
+ }
+ if (twist & 8) {
+ bitmap = ((bitmap & 0x00ff) << 8) | ((bitmap & 0xff00) >> 8);
+ }
+
+ // Arno, 2012-03-21: Do workaround (see below) here as well?
+
+ return bin_t(bin.base_left().twisted(twist & ~0x0f).toUInt() + bitmap_to_bin(bitmap)).to_twisted(twist & 0x0f);
+
+ } else {
+ if (twist & 1) {
+ bitmap = ((bitmap & 0x55555555) << 1) | ((bitmap & 0xAAAAAAAA) >> 1);
+ }
+ if (twist & 2) {
+ bitmap = ((bitmap & 0x33333333) << 2) | ((bitmap & 0xCCCCCCCC) >> 2);
+ }
+ if (twist & 4) {
+ bitmap = ((bitmap & 0x0f0f0f0f) << 4) | ((bitmap & 0xf0f0f0f0) >> 4);
+ }
+ if (twist & 8) {
+ bitmap = ((bitmap & 0x00ff00ff) << 8) | ((bitmap & 0xff00ff00) >> 8);
+ }
+ if (twist & 16) {
+ bitmap = ((bitmap & 0x0000ffff) << 16) | ((bitmap & 0xffff0000) >> 16);
+ }
+
+ bin_t diff = bin_t(bin.base_left().twisted(twist & ~0x1f).toUInt() + bitmap_to_bin(bitmap)).to_twisted(twist & 0x1f);
+
+ // Arno, 2012-03-21: Sanity check, if it fails, attempt workaround
+ if (!bin.contains(diff))
+ {
+ // Bug: Proposed bin is outside of specified range. The bug appears
+ // to be that the code assumes that the range parameter (called bin
+ // here) is aligned on a 32-bit boundary. I.e. the width of a
+ // half_t. Hence when the code does range + bitmap_to_bin(x)
+ // to find the base-layer offset of the bit on which the source
+ // and dest bitmaps differ, the result may be too high.
+ //
+ // What I do here is to round the rangestart to 32 bits, and
+ // then add bitmap_to_bin(bitmap), divided by two as that function
+ // returns the bit in a "bin number" format (=bit * 2).
+ //
+ // In other words, the "bin" parameter should tell us at what
+ // base offset of the 32-bit dbitmap and sbitmap is. At the moment
+ // it doesn't always, because "bin" is not rounded to 32-bit.
+ //
+ // see tests/binstest3.cpp
+
+ bin_t::uint_t rangestart = bin.base_left().twisted(twist & ~0x1f).layer_offset();
+ bin_t::uint_t b2b = bitmap_to_bin(bitmap);
+ bin_t::uint_t absoff = ((int)(rangestart/32))*32 + b2b/2;
+
+ diff = bin_t(0,absoff);
+ diff = diff.to_twisted(twist & 0x1f);
+
+ //char binstr[32];
+ //fprintf(stderr,"__fc solution %s\n", diff.str(binstr) );
+ }
+ return diff;
+ }
+}
+
+
+/**
+ * Sets bins
+ *
+ * @param bin
+ * the bin
+ */
+void binmap_t::set(const bin_t& bin)
+{
+ if (bin.is_none()) {
+ return;
+ }
+
+ if (bin.layer_bits() > BITMAP_LAYER_BITS) {
+ _set__high_layer_bitmap(bin, BITMAP_FILLED);
+ } else {
+ _set__low_layer_bitmap(bin, BITMAP_FILLED);
+ }
+}
+
+
+/**
+ * Resets bins
+ *
+ * @param bin
+ * the bin
+ */
+void binmap_t::reset(const bin_t& bin)
+{
+ if (bin.is_none()) {
+ return;
+ }
+
+ if (bin.layer_bits() > BITMAP_LAYER_BITS) {
+ _set__high_layer_bitmap(bin, BITMAP_EMPTY);
+ } else {
+ _set__low_layer_bitmap(bin, BITMAP_EMPTY);
+ }
+}
+
+
+/**
+ * Empty all bins
+ */
+void binmap_t::clear()
+{
+ cell_t& cell = cell_[ROOT_REF];
+
+ if (cell.is_left_ref_) {
+ free_cell(cell.left_.ref_);
+ }
+ if (cell.is_right_ref_) {
+ free_cell(cell.right_.ref_);
+ }
+
+ cell.is_left_ref_ = false;
+ cell.is_right_ref_ = false;
+ cell.left_.bitmap_ = BITMAP_EMPTY;
+ cell.right_.bitmap_ = BITMAP_EMPTY;
+}
+
+
+/**
+ * Fill the binmap. Creates a new filled binmap. Size is given by the source root
+ */
+void binmap_t::fill(const binmap_t& source)
+{
+ root_bin_ = source.root_bin_;
+ /* Extends root if needed */
+ while (!root_bin_.contains(source.root_bin_)) {
+ if (!extend_root()) {
+ return /* ALLOC ERROR */;
+ }
+ }
+ set(source.root_bin_);
+
+ cell_t& cell = cell_[ROOT_REF];
+
+ cell.is_left_ref_ = false;
+ cell.is_right_ref_ = false;
+ cell.left_.bitmap_ = BITMAP_FILLED;
+ cell.right_.bitmap_ = BITMAP_FILLED;
+}
+
+
+
+/**
+ * Get number of allocated cells
+ */
+size_t binmap_t::cells_number() const
+{
+ return allocated_cells_number_;
+}
+
+
+/**
+ * Get total size of the binmap
+ */
+size_t binmap_t::total_size() const
+{
+ return sizeof(*this) + sizeof(cell_[0]) * cells_number_;
+}
+
+
+
+/**
+ * Echo the binmap status to stdout
+ */
+void binmap_t::status() const
+{
+ printf("bitmap:\n");
+ for (int i = 0; i < 16; ++i) {
+ for (int j = 0; j < 64; ++j) {
+ printf("%d", is_filled(bin_t(i * 64 + j)));
+ }
+ printf("\n");
+ }
+
+ printf("size: %u bytes\n", static_cast<unsigned int>(total_size()));
+ printf("cells number: %u (of %u)\n", static_cast<unsigned int>(allocated_cells_number_), static_cast<unsigned int>(cells_number_));
+ printf("root bin: %llu\n", static_cast<unsigned long long>(root_bin_.toUInt()));
+}
+
+
+/** Trace the bin */
+inline void binmap_t::trace(ref_t* ref, bin_t* bin, const bin_t& target) const
+{
+ assert (root_bin_.contains(target));
+
+ ref_t cur_ref = ROOT_REF;
+ bin_t cur_bin = root_bin_;
+
+ while (target != cur_bin) {
+ if (target < cur_bin) {
+ if (cell_[cur_ref].is_left_ref_) {
+ cur_ref = cell_[cur_ref].left_.ref_;
+ cur_bin.to_left();
+ } else {
+ break;
+ }
+ } else {
+ if (cell_[cur_ref].is_right_ref_) {
+ cur_ref = cell_[cur_ref].right_.ref_;
+ cur_bin.to_right();
+ } else {
+ break;
+ }
+ }
+ }
+
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ if (ref) {
+ *ref = cur_ref;
+ }
+ if (bin) {
+ *bin = cur_bin;
+ }
+}
+
+
+/** Trace the bin */
+inline void binmap_t::trace(ref_t* ref, bin_t* bin, ref_t** history, const bin_t& target) const
+{
+ assert (history);
+ assert (root_bin_.contains(target));
+
+ ref_t* href = *history;
+ ref_t cur_ref = ROOT_REF;
+ bin_t cur_bin = root_bin_;
+
+ *href++ = ROOT_REF;
+ while (target != cur_bin) {
+ if (target < cur_bin) {
+ if (cell_[cur_ref].is_left_ref_) {
+ cur_ref = cell_[cur_ref].left_.ref_;
+ cur_bin.to_left();
+ } else {
+ break;
+ }
+ } else {
+ if (cell_[cur_ref].is_right_ref_) {
+ cur_ref = cell_[cur_ref].right_.ref_;
+ cur_bin.to_right();
+ } else {
+ break;
+ }
+ }
+
+ *href++ = cur_ref;
+ }
+
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ if (ref) {
+ *ref = cur_ref;
+ }
+ if (bin) {
+ *bin = cur_bin;
+ }
+
+ *history = href;
+}
+
+
+/**
+ * Copy a binmap to another
+ */
+void binmap_t::copy(binmap_t& destination, const binmap_t& source)
+{
+ destination.root_bin_ = source.root_bin_;
+ binmap_t::copy(destination, ROOT_REF, source, ROOT_REF);
+}
+
+
+/**
+ * Copy a range from one binmap to another binmap
+ */
+void binmap_t::copy(binmap_t& destination, const binmap_t& source, const bin_t& range)
+{
+ ref_t int_ref;
+ bin_t int_bin;
+
+ if (range.contains(destination.root_bin_)) {
+ if (source.root_bin_.contains(range)) {
+ source.trace(&int_ref, &int_bin, range);
+ destination.root_bin_ = range;
+ binmap_t::copy(destination, ROOT_REF, source, int_ref);
+ } else if (range.contains(source.root_bin_)) {
+ destination.root_bin_ = source.root_bin_;
+ binmap_t::copy(destination, ROOT_REF, source, ROOT_REF);
+ } else {
+ destination.reset(range);
+ }
+
+ } else {
+ if (source.root_bin_.contains(range)) {
+ source.trace(&int_ref, &int_bin, range);
+
+ const cell_t& cell = source.cell_[int_ref];
+
+ if (range.layer_bits() <= BITMAP_LAYER_BITS) {
+ if (range < int_bin) {
+ destination._set__low_layer_bitmap(range, cell.left_.bitmap_);
+ } else {
+ destination._set__low_layer_bitmap(range, cell.right_.bitmap_);
+ }
+
+ } else {
+ if (range == int_bin) {
+ if (cell.is_left_ref_ || cell.is_right_ref_ || cell.left_.bitmap_ != cell.right_.bitmap_) {
+ binmap_t::_copy__range(destination, source, int_ref, range);
+ } else {
+ destination._set__high_layer_bitmap(range, cell.left_.bitmap_);
+ }
+ } else if (range < int_bin) {
+ destination._set__high_layer_bitmap(range, cell.left_.bitmap_);
+ } else {
+ destination._set__high_layer_bitmap(range, cell.right_.bitmap_);
+ }
+ }
+
+ } else if (range.contains(source.root_bin_)) {
+ destination.reset(range); // Probably it could be optimized
+
+ const cell_t& cell = source.cell_[ ROOT_REF ];
+
+ if (cell.is_left_ref_ || cell.is_right_ref_ || cell.left_.bitmap_ != cell.right_.bitmap_) {
+ binmap_t::_copy__range(destination, source, ROOT_REF, source.root_bin_);
+ } else {
+ destination._set__high_layer_bitmap(source.root_bin_, cell.left_.bitmap_);
+ }
+
+ } else {
+ destination.reset(range);
+ }
+ }
+}
+
+
+inline void binmap_t::_set__low_layer_bitmap(const bin_t& bin, const bitmap_t _bitmap)
+{
+ assert (bin.layer_bits() <= BITMAP_LAYER_BITS);
+
+ const bitmap_t bin_bitmap = BITMAP[ bin.toUInt() & BITMAP_LAYER_BITS ];
+ const bitmap_t bitmap = _bitmap & bin_bitmap;
+
+ /* Extends root if needed */
+ if (!root_bin_.contains(bin)) {
+ /* Trivial case */
+ if (bitmap == BITMAP_EMPTY) {
+ return;
+ }
+ do {
+ if (!extend_root()) {
+ return /* ALLOC ERROR */;
+ }
+ } while (!root_bin_.contains(bin));
+ }
+
+ /* Get the pre-range */
+ const bin_t pre_bin( (bin.toUInt() & (~(BITMAP_LAYER_BITS + 1))) | BITMAP_LAYER_BITS );
+
+ /* The trace the bin with history */
+ ref_t _href[64];
+ ref_t* href = _href;
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ /* Process first stage -- do not touch existed tree */
+ trace(&cur_ref, &cur_bin, &href, pre_bin);
+
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ /* Checking that we need to do anything */
+ bitmap_t bm = BITMAP_EMPTY;
+ {
+ cell_t& cell = cell_[cur_ref];
+
+ if (bin < cur_bin) {
+ assert (!cell.is_left_ref_);
+ bm = cell.left_.bitmap_;
+ if ((bm & bin_bitmap) == bitmap) {
+ return;
+ }
+ if (cur_bin == pre_bin) {
+ cell.left_.bitmap_ = (cell.left_.bitmap_ & ~bin_bitmap) | bitmap;
+ pack_cells(href - 1);
+ return;
+ }
+ } else {
+ assert (!cell.is_right_ref_);
+ bm = cell.right_.bitmap_;
+ if ((bm & bin_bitmap) == bitmap) {
+ return;
+ }
+ if (cur_bin == pre_bin) {
+ cell.right_.bitmap_ = (cell.right_.bitmap_ & ~bin_bitmap) | bitmap;
+ pack_cells(href - 1);
+ return;
+ }
+ }
+ }
+
+ /* Reserving proper number of cells */
+ if (!reserve_cells( cur_bin.layer() - pre_bin.layer() )) {
+ return /* MEMORY ERROR or OVERFLOW ERROR */;
+ }
+
+ /* Continue to trace */
+ do {
+ const ref_t ref = _alloc_cell();
+
+ cell_[ref].is_left_ref_ = false;
+ cell_[ref].is_right_ref_ = false;
+ cell_[ref].left_.bitmap_ = bm;
+ cell_[ref].right_.bitmap_ = bm;
+
+ if (pre_bin < cur_bin) {
+ cell_[cur_ref].is_left_ref_ = true;
+ cell_[cur_ref].left_.ref_ = ref;
+ cur_bin.to_left();
+ } else {
+ cell_[cur_ref].is_right_ref_ = true;
+ cell_[cur_ref].right_.ref_ = ref;
+ cur_bin.to_right();
+ }
+
+ cur_ref = ref;
+ } while (cur_bin != pre_bin);
+
+ assert (cur_bin == pre_bin);
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ /* Complete setting */
+ if (bin < cur_bin) {
+ cell_[cur_ref].left_.bitmap_ = (cell_[cur_ref].left_.bitmap_ & ~bin_bitmap) | bitmap;
+ } else {
+ cell_[cur_ref].right_.bitmap_ = (cell_[cur_ref].right_.bitmap_ & ~bin_bitmap) | bitmap;
+ }
+}
+
+
+inline void binmap_t::_set__high_layer_bitmap(const bin_t& bin, const bitmap_t bitmap)
+{
+ assert (bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ /* First trivial case */
+ if (bin.contains(root_bin_)) {
+ cell_t& cell = cell_[ROOT_REF];
+ if (cell.is_left_ref_) {
+ free_cell(cell.left_.ref_);
+ }
+ if (cell.is_right_ref_) {
+ free_cell(cell.right_.ref_);
+ }
+
+ root_bin_ = bin;
+ cell.is_left_ref_ = false;
+ cell.is_right_ref_ = false;
+ cell.left_.bitmap_ = bitmap;
+ cell.right_.bitmap_ = bitmap;
+
+ return;
+ }
+
+ /* Get the pre-range */
+ bin_t pre_bin = bin.parent();
+
+ /* Extends root if needed */
+ if (!root_bin_.contains(pre_bin)) {
+ /* Second trivial case */
+ if (bitmap == BITMAP_EMPTY) {
+ return;
+ }
+
+ do {
+ if (!extend_root()) {
+ return /* ALLOC ERROR */;
+ }
+ } while (!root_bin_.contains(pre_bin));
+ }
+
+ /* The trace the bin with history */
+ ref_t _href[64];
+ ref_t* href = _href;
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ /* Process first stage -- do not touch existed tree */
+ trace(&cur_ref, &cur_bin, &href, pre_bin);
+
+ /* Checking that we need to do anything */
+ bitmap_t bm = BITMAP_EMPTY;
+ {
+ cell_t& cell = cell_[cur_ref];
+ if (bin < cur_bin) {
+ if (cell.is_left_ref_) {
+ /* assert (cur_bin == pre_bin); */
+ cell.is_left_ref_ = false;
+ free_cell(cell.left_.ref_);
+ } else {
+ bm = cell.left_.bitmap_;
+ if (bm == bitmap) {
+ return;
+ }
+ }
+ if (cur_bin == pre_bin) {
+ cell.left_.bitmap_ = bitmap;
+ pack_cells(href - 1);
+ return;
+ }
+ } else {
+ if (cell.is_right_ref_) {
+ /* assert (cur_bin == pre_bin); */
+ cell.is_right_ref_ = false;
+ free_cell(cell.right_.ref_);
+ } else {
+ bm = cell.right_.bitmap_;
+ if (bm == bitmap) {
+ return;
+ }
+ }
+ if (cur_bin == pre_bin) {
+ cell.right_.bitmap_ = bitmap;
+ pack_cells(href - 1);
+ return;
+ }
+ }
+ }
+
+ /* Reserving proper number of cells */
+ if (!reserve_cells( cur_bin.layer() - pre_bin.layer() )) {
+ return /* MEMORY ERROR or OVERFLOW ERROR */;
+ }
+
+ /* Continue to trace */
+ do {
+ const ref_t ref = _alloc_cell();
+
+ cell_[ref].is_left_ref_ = false;
+ cell_[ref].is_right_ref_ = false;
+ cell_[ref].left_.bitmap_ = bm;
+ cell_[ref].right_.bitmap_ = bm;
+
+ if (pre_bin < cur_bin) {
+ cell_[cur_ref].is_left_ref_ = true;
+ cell_[cur_ref].left_.ref_ = ref;
+ cur_bin.to_left();
+ } else {
+ cell_[cur_ref].is_right_ref_ = true;
+ cell_[cur_ref].right_.ref_ = ref;
+ cur_bin.to_right();
+ }
+
+ cur_ref = ref;
+ } while (cur_bin != pre_bin);
+
+ assert (cur_bin == pre_bin);
+ assert (cur_bin.layer_bits() > BITMAP_LAYER_BITS);
+
+ /* Complete setting */
+ if (bin < cur_bin) {
+ cell_[cur_ref].left_.bitmap_ = bitmap;
+ } else {
+ cell_[cur_ref].right_.bitmap_ = bitmap;
+ }
+}
+
+
+void binmap_t::_copy__range(binmap_t& destination, const binmap_t& source, const ref_t sref, const bin_t sbin)
+{
+ assert (sbin.layer_bits() > BITMAP_LAYER_BITS);
+
+ assert (sref == ROOT_REF ||
+ source.cell_[ sref ].is_left_ref_ || source.cell_[ sref ].is_right_ref_ ||
+ source.cell_[ sref ].left_.bitmap_ != source.cell_[ sref ].right_.bitmap_
+ );
+
+ /* Extends root if needed */
+ while (!destination.root_bin_.contains(sbin)) {
+ if (!destination.extend_root()) {
+ return /* ALLOC ERROR */;
+ }
+ }
+
+ /* The trace the bin */
+ ref_t cur_ref;
+ bin_t cur_bin;
+
+ /* Process first stage -- do not touch existed tree */
+ destination.trace(&cur_ref, &cur_bin, sbin);
+
+ /* Continue unpacking if needed */
+ if (cur_bin != sbin) {
+ bitmap_t bm = BITMAP_EMPTY;
+
+ if (sbin < cur_bin) {
+ bm = destination.cell_[cur_ref].left_.bitmap_;
+ } else {
+ bm = destination.cell_[cur_ref].right_.bitmap_;
+ }
+
+ /* Reserving proper number of cells */
+ if (!destination.reserve_cells( cur_bin.layer() - sbin.layer() )) {
+ return /* MEMORY ERROR or OVERFLOW ERROR */;
+ }
+
+ /* Continue to trace */
+ do {
+ const ref_t ref = destination._alloc_cell();
+
+ destination.cell_[ref].is_left_ref_ = false;
+ destination.cell_[ref].is_right_ref_ = false;
+ destination.cell_[ref].left_.bitmap_ = bm;
+ destination.cell_[ref].right_.bitmap_ = bm;
+
+ if (sbin < cur_bin) {
+ destination.cell_[cur_ref].is_left_ref_ = true;
+ destination.cell_[cur_ref].left_.ref_ = ref;
+ cur_bin.to_left();
+ } else {
+ destination.cell_[cur_ref].is_right_ref_ = true;
+ destination.cell_[cur_ref].right_.ref_ = ref;
+ cur_bin.to_right();
+ }
+
+ cur_ref = ref;
+ } while (cur_bin != sbin);
+ }
+
+ /* Make copying */
+ copy(destination, cur_ref, source, sref);
+}
+
+
+/**
+ * Clone binmap cells to another binmap
+ */
+void binmap_t::copy(binmap_t& destination, const ref_t dref, const binmap_t& source, const ref_t sref)
+{
+ assert (dref == ROOT_REF ||
+ source.cell_[ sref ].is_left_ref_ || source.cell_[ sref ].is_right_ref_ ||
+ source.cell_[ sref ].left_.bitmap_ != source.cell_[ sref ].right_.bitmap_
+ );
+
+ size_t sref_size = 0;
+ size_t dref_size = 0;
+
+ ref_t sstack[128];
+ ref_t dstack[128];
+ size_t top = 0;
+
+ /* Get size of the source subtree */
+ sstack[top++] = sref;
+ do {
+ assert (top < sizeof(sstack) / sizeof(sstack[0]));
+
+ ++sref_size;
+
+ const cell_t& scell = source.cell_[ sstack[--top] ];
+ if (scell.is_left_ref_) {
+ sstack[top++] = scell.left_.ref_;
+ }
+ if (scell.is_right_ref_) {
+ sstack[top++] = scell.right_.ref_;
+ }
+
+ } while (top > 0);
+
+ /* Get size of the destination subtree */
+ dstack[top++] = dref;
+ do {
+ assert (top < sizeof(dstack) / sizeof(dstack[0]));
+
+ ++dref_size;
+
+ const cell_t& dcell = destination.cell_[ dstack[--top] ];
+ if (dcell.is_left_ref_) {
+ dstack[top++] = dcell.left_.ref_;
+ }
+ if (dcell.is_right_ref_) {
+ dstack[top++] = dcell.right_.ref_;
+ }
+
+ } while (top > 0);
+
+ /* Reserving proper number of cells */
+ if (dref_size < sref_size) {
+ if (!destination.reserve_cells( sref_size - dref_size)) {
+ return /* MEMORY ERROR or OVERFLOW ERROR */;
+ }
+ }
+
+ /* Release the destination subtree */
+ if (destination.cell_[dref].is_left_ref_) {
+ destination.free_cell(destination.cell_[dref].left_.ref_);
+ }
+ if (destination.cell_[dref].is_right_ref_) {
+ destination.free_cell(destination.cell_[dref].right_.ref_);
+ }
+
+ /* Make cloning */
+ sstack[top] = sref;
+ dstack[top] = dref;
+ ++top;
+
+ do {
+ --top;
+ const cell_t& scell = source.cell_[ sstack[top] ];
+ cell_t& dcell = destination.cell_[ dstack[top] ];
+
+ /* Processing left ref */
+ if (scell.is_left_ref_) {
+ dcell.is_left_ref_ = true;
+ dcell.left_.ref_ = destination._alloc_cell();
+
+ sstack[top] = scell.left_.ref_;
+ dstack[top] = dcell.left_.ref_;
+ ++top;
+ } else {
+ dcell.is_left_ref_ = false;
+ dcell.left_.bitmap_ = scell.left_.bitmap_;
+ }
+
+ /* Processing right ref */
+ if (scell.is_right_ref_) {
+ dcell.is_right_ref_ = true;
+ dcell.right_.ref_ = destination._alloc_cell();
+
+ sstack[top] = scell.right_.ref_;
+ dstack[top] = dcell.right_.ref_;
+ ++top;
+ } else {
+ dcell.is_right_ref_ = false;
+ dcell.right_.bitmap_ = scell.right_.bitmap_;
+ }
+ } while (top > 0);
+}
+
+int binmap_t::write_cell(FILE *fp,cell_t c)
+{
+ fprintf_retiffail(fp,"leftb %d\n", c.left_.bitmap_);
+ fprintf_retiffail(fp,"rightb %d\n", c.right_.bitmap_);
+ fprintf_retiffail(fp,"is_left %d\n", c.is_left_ref_ ? 1 : 0 );
+ fprintf_retiffail(fp,"is_right %d\n", c.is_right_ref_ ? 1 : 0 );
+ fprintf_retiffail(fp,"is_free %d\n", c.is_free_ ? 1 : 0 );
+ return 0;
+}
+
+
+int binmap_t::read_cell(FILE *fp,cell_t *c)
+{
+ bitmap_t left,right;
+ int is_left,is_right,is_free;
+ fscanf_retiffail(fp,"leftb %d\n", &left);
+ fscanf_retiffail(fp,"rightb %d\n", &right);
+ fscanf_retiffail(fp,"is_left %d\n", &is_left );
+ fscanf_retiffail(fp,"is_right %d\n", &is_right );
+ fscanf_retiffail(fp,"is_free %d\n", &is_free );
+
+ //fprintf(stderr,"binmapread_cell: l%ld r%ld %d %d %d\n", left, right, is_left, is_right, is_free );
+
+ c->left_.bitmap_ = left;
+ c->right_.bitmap_ = right;
+ c->is_left_ref_ = (bool)is_left;
+ c->is_right_ref_ = (bool)is_right;
+ c->is_free_ = (bool)is_free;
+
+ return 0;
+}
+
+// Arno, 2011-10-20: Persistent storage
+int binmap_t::serialize(FILE *fp)
+{
+ fprintf_retiffail(fp,"root bin %lli\n",root_bin_.toUInt() );
+ fprintf_retiffail(fp,"free top %i\n",free_top_ );
+ fprintf_retiffail(fp,"alloc cells " PRISIZET"\n", allocated_cells_number_);
+ fprintf_retiffail(fp,"cells num " PRISIZET"\n", cells_number_);
+ for (size_t i=0; i<cells_number_; i++)
+ {
+ if (write_cell(fp,cell_[i]) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+
+
+
+int binmap_t::deserialize(FILE *fp)
+{
+ bin_t::uint_t rootbinval;
+ ref_t freetop;
+ size_t alloccells,cells;
+ fscanf_retiffail(fp,"root bin %lli\n", &rootbinval );
+ fscanf_retiffail(fp,"free top %i\n", &freetop );
+ fscanf_retiffail(fp,"alloc cells " PRISIZET"\n", &alloccells);
+ fscanf_retiffail(fp,"cells num " PRISIZET"\n", &cells);
+
+ //fprintf(stderr,"Filling BINMAP %p\n", this );
+ //fprintf(stderr,"Rootbin %lli freetop %li alloc %li num %li\n", rootbinval, freetop, alloccells, cells );
+
+ root_bin_ = bin_t(rootbinval);
+ free_top_ = freetop;
+ allocated_cells_number_ = alloccells;
+ cells_number_ = cells;
+ if (cell_ != NULL) {
+ free(cell_);
+ }
+ cell_ = (cell_t *)new cell_t[cells];
+ size_t i=0;
+ for (i=0; i<cells; i++)
+ {
+ /* Cleans cell */
+ memset(&cell_[i], 0, sizeof(cell_[0]));
+ if (read_cell(fp,&cell_[i]) < 0)
+ return -1;
+ }
+ return 0;
+}