}
-bin64_t iterator::next (bool need_solid) {
- assert(!deep());
+bin64_t iterator::next (bool need_solid, uint8_t min_layer) {
+ assert( (!deep()) || (layer()==min_layer));
while (pos.is_right())
parent();
//parent();
//if (need_solid ? !solid() : deep())
// right();
sibling();
- while (need_solid ? !solid() : deep())
+ while ( (need_solid ? !solid() : deep()) && layer()>min_layer )
left();
return pos;
}
while (
fi.deep() ?
(ti.deep() || *ti!=stop) :
- (ti.deep() ? *fi!=FILLED : ( ((*ti^stop)&~*fi) && (*ti!=seek || *fi!=EMPTY) ) )
+ (ti.deep() ? *fi!=FILLED :
+ ( ((*ti^stop)&~*fi) && (*ti!=seek || *fi!=EMPTY) ) )
)
{
ti.left(); fi.left();
return bin64_t::NONE;
}
-// FIXME unite with remove(); do bitwise()
-void binmap_t::copy_range (binmap_t& origin, bin64_t range) {
+void binmap_t::range_op (binmap_t& mask, bin64_t range, bin_op_t op) {
if (range==bin64_t::ALL)
- range = bin64_t ( height>origin.height ? height : origin.height, 0 );
- iterator zis(this,range,true), zat(&origin,range,true);
+ range = bin64_t ( height>mask.height ? height : mask.height, 0 );
+ iterator zis(this,range,true), zat(&mask,range,true);
while (zis.pos.within(range)) {
while (zis.deep() || zat.deep()) {
zis.left(); zat.left();
}
-
- *zis = *zat;
+
+ switch (op) {
+ case REMOVE_OP:
+ *zis &= ~*zat;
+ break;
+ case AND_OP:
+ *zis &= *zat;
+ break;
+ case COPY_OP:
+ *zis = *zat;
+ break;
+ case OR_OP:
+ *zis |= *zat;
+ }
while (zis.pos.is_right()) {
zis.parent(); zat.parent();
}
+void binmap_t::map16 (uint16_t* target, bin64_t range, iterator& lead) {
+ while (!range.within(lead.pos))
+ lead.parent();
+ while (lead.pos!=range)
+ lead.towards(range);
+ if (!lead.deep()) {
+ *target = *lead;
+ return;
+ }
+ lead.left();
+ lead.left();
+ lead.left();
+ lead.left();
+ uint16_t shift = 1;
+ for(int i=0; i<16; i++) {
+ if (!lead.deep() && *lead==FILLED)
+ *target |= shift;
+ shift<<=1;
+ lead.next(false,range.layer()-4);
+ }
+}
+
+
+void binmap_t::to_coarse_bitmap (void* bits, bin64_t range, uint8_t height) {
+ uint16_t* bits16 = (uint16_t*) bits;
+ iterator iter(this,range,true);
+ int height16 = range.layer()-height-4;
+ int wordwidth = 1 << height16;
+ int offset = range.offset() << height16;
+ for(int i=offset; i<offset+wordwidth; i++)
+ map16(bits16+i,bin64_t(height+4,i),iter);
+}
+
+
binheap::binheap() {
size_ = 32;
heap_ = (bin64_t*) malloc(size_*sizeof(bin64_t));
binheap::~binheap() {
free(heap_);
}
+
#define BINS_H
#include "bin64.h"
+class iterator; // FIXME shame
+
/** A binmap covering 2^64 range. Binmap is a hybrid of a bitmap (aka
bit vector) and a binary tree. The key ability of a binmap is
the aggregation of solid (all-0 or all-1) ranges. */
/** Set value for the bin. */
void set (bin64_t bin, fill_t val=FILLED);
+ typedef enum {
+ OR_OP,
+ AND_OP,
+ REMOVE_OP,
+ COPY_OP
+ } bin_op_t;
+
/** Copy a range from another binmap. */
- void copy_range (binmap_t& origin, bin64_t range);
+ void range_op (binmap_t& mask, bin64_t range, bin_op_t op);
+ void range_copy (binmap_t& mask, bin64_t range)
+ { range_op(mask, range, COPY_OP); }
+ void range_remove (binmap_t& mask, bin64_t range)
+ { range_op(mask, range, REMOVE_OP); }
+ void range_or (binmap_t& mask, bin64_t range)
+ { range_op(mask, range, OR_OP); }
+ void range_and (binmap_t& mask, bin64_t range)
+ { range_op(mask, range, AND_OP); }
/** Find the leftmost bin within the specified range which is
either filled or empty. */
right change places. Twisting is mostly needed for randomization. */
void twist (uint64_t mask);
+ void to_coarse_bitmap (void* bits, bin64_t range, uint8_t height);
+
private:
/** Every 16th uint32 is a flag field denoting whether
static uint32_t split16to32(uint16_t half);
static int join32to16(uint32_t cell);
+
+ void map16 (uint16_t* target, bin64_t range, iterator& lead);
friend class iterator;
#ifdef FRIEND_TEST
void right() {to(1);}
/** Move to the next defined (non-deep, flat) cell.
If solid==true, move to a solid (0xffff/0x0) cell. */
- bin64_t next (bool solid=false);
+ bin64_t next (bool solid=false, uint8_t min_layer=0);
bin64_t bin() { return pos; }
void towards(bin64_t bin) {
bin64_t next = pos.towards(bin);
add.set(bin64_t(1,4));
add.set(bin64_t(0,13));
add.set(bin64_t(5,118));
- data.copy_range(add, bin64_t(3,0));
+ data.range_copy(add, bin64_t(3,0));
EXPECT_TRUE(binmap_t::is_mixed(data.get(bin64_t(3,0))));
EXPECT_EQ(binmap_t::EMPTY,data.get(bin64_t(2,0)));
EXPECT_EQ(binmap_t::FILLED,data.get(bin64_t(2,1)));
}
+TEST(BinsTest,RangeOpTest) {
+ binmap_t a, b;
+ a.set(bin64_t(0,0));
+ a.set(bin64_t(0,2));
+ b.set(bin64_t(0,1));
+ b.set(bin64_t(0,3));
+ a.range_or(b,bin64_t(1,0));
+ EXPECT_TRUE(a.is_filled(bin64_t(1,0)));
+ EXPECT_FALSE(a.is_filled(bin64_t(1,1)));
+
+ binmap_t f, s;
+ f.set(bin64_t(3,0));
+ s.set(bin64_t(0,1));
+ s.set(bin64_t(0,4));
+ f.range_remove(s,bin64_t(2,1));
+
+ EXPECT_TRUE(f.is_filled(bin64_t(2,0)));
+ EXPECT_FALSE(f.is_filled(bin64_t(0,4)));
+ EXPECT_TRUE(f.is_filled(bin64_t(0,5)));
+
+ binmap_t z, x;
+ z.set(bin64_t(1,0));
+ z.set(bin64_t(1,2));
+ x.set(bin64_t(0,1));
+ x.set(bin64_t(0,1));
+}
+
+TEST(BinsTest,CoarseBitmap) {
+ binmap_t b;
+ b.set(bin64_t(4,0));
+ uint32_t i32;
+ b.to_coarse_bitmap(&i32,bin64_t(5,0),0);
+ EXPECT_EQ((1<<16)-1,i32);
+
+ b.set(bin64_t(14,0));
+ i32=0;
+ b.to_coarse_bitmap(&i32,bin64_t(15,0),10);
+ EXPECT_EQ((1<<16)-1,i32);
+
+ binmap_t rough;
+ rough.set(bin64_t(1,0));
+ rough.set(bin64_t(0,2));
+ i32=0;
+ rough.to_coarse_bitmap(&i32,bin64_t(6,0),1);
+ EXPECT_EQ(1,i32);
+}
+
/*TEST(BinsTest,AddSub) {
binmap_t b;
b|=15;