binheap
authorvictor <victor@e16421f0-f15b-0410-abcd-98678b794739>
Sun, 25 Oct 2009 08:26:26 +0000 (08:26 +0000)
committervictor <victor@e16421f0-f15b-0410-abcd-98678b794739>
Sun, 25 Oct 2009 08:26:26 +0000 (08:26 +0000)
git-svn-id: https://ttuki.vtt.fi/svn/p2p-next/TUD/p2tp/trunk@471 e16421f0-f15b-0410-abcd-98678b794739

bins.cpp
bins.h
tests/binstest2.cpp

index f546982..6686655 100644 (file)
--- a/bins.cpp
+++ b/bins.cpp
@@ -314,4 +314,61 @@ void    bins::remove (bins& b) {
         }
         zis.sibling(); zat.sibling();
     }
-}
\ No newline at end of file
+}
+
+
+binheap::binheap() {
+    size_ = 32;
+    heap_ = (bin64_t*) malloc(size_*sizeof(bin64_t));
+    filled_ = 0;
+}
+
+bool bincomp (const bin64_t& a, const bin64_t& b) {
+    register uint64_t ab = a.base_offset(), bb = b.base_offset();
+    if (ab==bb)
+        return a.tail_bit() < b.tail_bit();
+    else
+        return ab > bb;
+}
+
+bool bincomp_rev (const bin64_t& a, const bin64_t& b) {
+    register uint64_t ab = a.base_offset(), bb = b.base_offset();
+    if (ab==bb)
+        return a.tail_bit() > b.tail_bit();
+    else
+        return ab < bb;
+}
+
+bin64_t binheap::pop() {
+    if (!filled_)
+        return bin64_t::NONE;
+    bin64_t ret = heap_[0];
+    std::pop_heap(heap_, heap_+filled_--,bincomp);
+    while (filled_ && heap_[0].within(ret))
+        std::pop_heap(heap_, heap_+filled_--,bincomp);
+    return ret;
+}
+
+void    binheap::extend() {
+    std::sort(heap_,heap_+filled_,bincomp_rev);
+    int solid = 0;
+    for(int i=1; i<filled_; i++)
+        if (!heap_[i].within(heap_[solid]))
+            heap_[++solid] = heap_[i];
+    filled_ = solid+1;
+    if (2*filled_>size_) {
+        size_ <<= 1;
+        heap_ = (bin64_t*) realloc(heap_,size_*sizeof(bin64_t));
+    }
+}
+
+void    binheap::push(bin64_t val) {
+    if (filled_==size_)
+        extend();
+    heap_[filled_++] = val;
+    std::push_heap(heap_, heap_+filled_,bincomp);
+}
+
+binheap::~binheap() {
+    free(heap_);
+}
diff --git a/bins.h b/bins.h
index e1d9130..dba5b8c 100644 (file)
--- a/bins.h
+++ b/bins.h
@@ -128,4 +128,19 @@ public:
     uint16_t& operator* () { return host->halves[half]; }
 };
 
+
+class binheap {
+    bin64_t     *heap_;
+    uint32_t    filled_;
+    uint32_t    size_;
+public:
+    binheap();
+    bin64_t pop();
+    void    push(bin64_t);
+    bool    empty() const { return !filled_; }
+    void    extend();
+    ~binheap();
+};
+
+
 #endif
index a3fadfb..e75b0cf 100755 (executable)
@@ -212,6 +212,28 @@ TEST(BinsTest,Remove) {
     
 }
 
+TEST(BinheapTest,Eat) {
+    
+    binheap b;
+    b.push(bin64_t(0,1));
+    b.push(bin64_t(0,3));
+    b.push(bin64_t(2,0));
+    b.push(bin64_t(2,4));
+    
+    EXPECT_EQ(bin64_t(2,0),b.pop());
+    EXPECT_EQ(bin64_t(2,4),b.pop());
+    EXPECT_EQ(bin64_t::none(),b.pop());
+    
+    for (int i=0; i<64; i++) {
+        b.push(bin64_t(0,i));
+    }
+    b.push(bin64_t(5,0));
+    EXPECT_EQ(bin64_t(5,0),b.pop());
+    for (int i=32; i<64; i++)
+        EXPECT_EQ(bin64_t(0,i),b.pop());
+        
+}
+
 /*TEST(BinsTest,AddSub) {
        bins b;
        b|=15;