From ab47042eac5f32f747d259987fdf9fcaa7f4cb10 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Sun, 15 Apr 2018 16:28:54 +0300 Subject: [PATCH 1/5] initial 64bit support --- source/roaring/roaring.d | 224 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 2 deletions(-) diff --git a/source/roaring/roaring.d b/source/roaring/roaring.d index c07c03a..88556e8 100644 --- a/source/roaring/roaring.d +++ b/source/roaring/roaring.d @@ -5,11 +5,13 @@ import roaring.c; Bitmap bitmapOf(const uint[] args ...) { + pragma(inline, true); return Bitmap.fromArray(args); } Bitmap bitmapOf(const uint[] bits) { + pragma(inline, true); return Bitmap.fromArray(bits); } @@ -31,6 +33,26 @@ unittest assert((r1 == r2) && (r1 == r3)); } +Bitmap64 bitmap64Of(const ulong[] args...) +{ + pragma(inline, true); + return bitmap64Of(args); +} + +Bitmap64 bitmap64Of(const ulong[] args) +{ + auto b = new Bitmap64; + foreach (arg; args) b.add(arg); + return b; +} + +unittest +{ + const b = bitmap64Of(1, 2, 3); + assert(b.length == 3); + assert(bitmap64Of(1, 2^^40) == bitmap64Of([1, 2^^40])); +} + Bitmap readBitmap(const char[] buf) { return Bitmap.read(buf); @@ -170,7 +192,7 @@ class Bitmap } @nogc @property @safe - void copyOnWrite(bool enable) pure + void copyOnWrite(bool enable) { this.bitmap.copy_on_write = enable; } @@ -487,7 +509,6 @@ class Bitmap override bool opEquals(Object b) const { - import std.stdio : writeln; if (this is b) return true; if (b is null) return false; if (typeid(this) == typeid(b)) { @@ -544,6 +565,205 @@ class Bitmap private roaring_bitmap_t* bitmap; } +@nogc @safe +private uint indexOf(const ulong x) pure +{ + pragma(inline, true); + return cast(uint)(x >> 32); +} + +@nogc @safe +private uint lowOf(const ulong x) pure +{ + pragma(inline, true); + return cast(uint)x; +} + +@nogc @safe +private ulong valueOf(const uint index, const uint low) pure +{ + pragma(inline, true); + return (cast(ulong)index << 32) + low; +} + +unittest +{ + import std.stdio : writeln; + ulong x = cast(ulong)uint.max + 2; + writeln("x = ", x); + writeln("index(x) = ", indexOf(x)); + writeln("lowOf(x) = ", lowOf(x)); + writeln("valueOf(x) = ", valueOf(indexOf(x), lowOf(x))); + // assert(indexOf(x) == 1); + // assert(lowOf(x) == 1); + assert(valueOf(indexOf(x), lowOf(x)) == x); +} + + +class Bitmap64 +{ + @nogc @property @safe + ulong length() const pure + { + ulong result = 0; + foreach (bmp; this.bitmaps.byValue) { + result += bmp.length; + } + return result; + } + + /** + * Return the largest value (if not empty) + * + */ + @nogc @property @safe + ulong maximum() const pure + { + ulong result = 0; + foreach (index, bmp; this.bitmaps) { + const m = valueOf(index, bmp.maximum); + if (m > result) result = m; + } + return result; + } + + /** + * Return the smallest value (if not empty) + * + */ + @nogc @property @safe + ulong minimum() const pure + { + ulong result = ulong.max; + foreach (index, bmp; this.bitmaps) { + const m = valueOf(index, bmp.minimum); + if (m < result) result = m; + } + return result; + } + + unittest + { + const r2 = bitmap64Of(100, ulong.max); + assert(r2.minimum == 100); + assert(r2.maximum == ulong.max); + } + + @nogc @property @safe + void copyOnWrite(bool enable) + { + if (enable == this.copyOnWrite_) return; + this.copyOnWrite_ = enable; + foreach (bmp; this.bitmaps.byValue) { + bmp.bitmap.copy_on_write = enable; + } + } + + @nogc @property @safe + bool copyOnWrite() const + { + return this.copyOnWrite_; + } + + void add(const ulong x) + { + ensureBitmap(indexOf(x)).add(lowOf(x)); + } + + bool contains(const ulong x) const + { + const index = indexOf(x); + if (index !in this.bitmaps) { + return false; + } + return lowOf(x) in this.bitmaps[index]; + } + + @nogc @safe + bool optimize() + { + auto result = false; + foreach (bmp; this.bitmaps.byValue) { + result |= bmp.optimize; + } + return result; + } + + unittest + { + auto r1 = bitmap64Of(5, 1, 2, 3, 5, 6); + r1.copyOnWrite = true; + //check optimization + auto size1 = r1.sizeInBytes; + r1.optimize; + assert(r1.sizeInBytes < size1); + } + + @nogc @property @safe + size_t sizeInBytes() const pure + { + size_t result = 0; + foreach (bmp; this.bitmaps.byValue) { + result += bmp.sizeInBytes; + } + return result; + } + + unittest + { + assert(bitmap64Of(5).sizeInBytes == bitmapOf(5).sizeInBytes); + assert(bitmap64Of(5, 2^^40).sizeInBytes > bitmapOf(5).sizeInBytes); + } + + @safe + bool opBinaryRight(const string op)(const long x) const + if (op == "in") + { + static if (op == "in") { + const index = indexOf(x); + if (index !in this.bitmaps) { + return false; + } + return lowOf(x) in this.bitmaps[index]; + } + else static assert(0, "Operator " ~ op ~ " not implemented."); + } + + override bool opEquals(Object b) const + { + if (this is b) return true; + if (b is null) return false; + if (typeid(this) == typeid(b)) { + const cb = cast(Bitmap64)b; + return this.bitmaps == cb.bitmaps; + } + return false; + } + + private Bitmap ensureBitmap(const uint index) + { + if (index !in this.bitmaps) { + auto bmp = new Bitmap; + bmp.copyOnWrite = this.copyOnWrite; + this.bitmaps[index] = bmp; + return bmp; + } + return this.bitmaps[index]; + } + + private Bitmap[uint] bitmaps; + private bool copyOnWrite_ = false; +} + +unittest +{ + auto b = new Bitmap64; + b.add(2^^40); + assert(2^^40 in b); + b.add(5); + assert(b.length == 2); +} + unittest { import std.stdio : writefln, writeln; From b155a4e261c7b23b764758b899e706d023f5e338 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Sun, 15 Apr 2018 19:36:03 +0300 Subject: [PATCH 2/5] gdc fix --- source/roaring/roaring.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/roaring/roaring.d b/source/roaring/roaring.d index 88556e8..d4400e9 100644 --- a/source/roaring/roaring.d +++ b/source/roaring/roaring.d @@ -602,7 +602,7 @@ unittest class Bitmap64 { - @nogc @property @safe + @nogc @property ulong length() const pure { ulong result = 0; From f2b7dae38741807362b6c5c66bc824e0f57c3289 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Sun, 15 Apr 2018 20:09:27 +0300 Subject: [PATCH 3/5] gdc fix --- source/roaring/roaring.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/roaring/roaring.d b/source/roaring/roaring.d index d4400e9..a8cadb9 100644 --- a/source/roaring/roaring.d +++ b/source/roaring/roaring.d @@ -649,7 +649,7 @@ class Bitmap64 assert(r2.maximum == ulong.max); } - @nogc @property @safe + @nogc @property void copyOnWrite(bool enable) { if (enable == this.copyOnWrite_) return; @@ -679,7 +679,7 @@ class Bitmap64 return lowOf(x) in this.bitmaps[index]; } - @nogc @safe + @nogc bool optimize() { auto result = false; @@ -699,7 +699,7 @@ class Bitmap64 assert(r1.sizeInBytes < size1); } - @nogc @property @safe + @nogc @property size_t sizeInBytes() const pure { size_t result = 0; From afd2d71c0074f2c696fb9b3d46cb5ed1a135464d Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Sun, 15 Apr 2018 20:14:11 +0300 Subject: [PATCH 4/5] Trivial cleanup --- source/roaring/roaring.d | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/source/roaring/roaring.d b/source/roaring/roaring.d index a8cadb9..14f6def 100644 --- a/source/roaring/roaring.d +++ b/source/roaring/roaring.d @@ -588,14 +588,9 @@ private ulong valueOf(const uint index, const uint low) pure unittest { - import std.stdio : writeln; ulong x = cast(ulong)uint.max + 2; - writeln("x = ", x); - writeln("index(x) = ", indexOf(x)); - writeln("lowOf(x) = ", lowOf(x)); - writeln("valueOf(x) = ", valueOf(indexOf(x), lowOf(x))); - // assert(indexOf(x) == 1); - // assert(lowOf(x) == 1); + assert(indexOf(x) == 1); + assert(lowOf(x) == 1); assert(valueOf(indexOf(x), lowOf(x)) == x); } From 33715c7bd0eb92a4aaad89895f79e718290c9485 Mon Sep 17 00:00:00 2001 From: Yuce Tekol Date: Tue, 17 Apr 2018 19:42:02 +0300 Subject: [PATCH 5/5] opDollar is length --- source/roaring/roaring.d | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/source/roaring/roaring.d b/source/roaring/roaring.d index 14f6def..b2ddf51 100644 --- a/source/roaring/roaring.d +++ b/source/roaring/roaring.d @@ -476,11 +476,7 @@ class Bitmap return r; } - @nogc @property @safe - uint opDollar() const pure - { - return length; - } + alias opDollar = length; unittest {