Skip to content

Commit

Permalink
lib/std/collections: add Bitmap
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Curto <[email protected]>
  • Loading branch information
pierrec committed Sep 6, 2023
1 parent e3412da commit dc0c5a4
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 0 deletions.
73 changes: 73 additions & 0 deletions lib/std/collections/bitmap.c3
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* @require Type.kindof == UNSIGNED_INT
**/
module std::collections::bitmap(<Type>);
import std::collections::list;

def BitmapList = List(<Type>);

struct Bitmap
{
BitmapList data;
}

fn void Bitmap.init(&self, usz initial_capacity = 1, Allocator* using = mem::heap())
{
self.data.init(initial_capacity, using);
}

fn void Bitmap.tinit(&self)
{
self.init(.using = mem::temp());
}

fn usz Bitmap.cardinality(&self)
{
usz n;
foreach (x : self.data)
{
n += x.popcount();
}
return n;
}

fn void Bitmap.set(&self, usz i)
{
usz q = i / Type.sizeof;
usz r = i % Type.sizeof;
if (q >= self.data.len())
{
self.data.reserve(q + 1);
self.data.size = q + 1;
}
self.data.set(q, self.data[q] | (1 << r));
}

fn void Bitmap.unset(&self, usz i)
{
usz q = i / Type.sizeof;
usz r = i % Type.sizeof;
if (q >= self.data.len()) return;
self.data.set(q, self.data[q] &~ (1 << r));
}

fn bool Bitmap.get(&self, usz i) @operator([]) @inline
{
usz q = i / Type.sizeof;
usz r = i % Type.sizeof;
if (q >= self.data.len()) return false;
return self.data[q] & (1 << r) != 0;
}

fn usz Bitmap.len(&self) @operator(len)
{
usz n = self.data.len();
if (n > 0) n -= self.data[n - 1].ctz();
return n;
}

fn void Bitmap.set_bool(&self, usz i, bool value) @operator([]=) @inline
{
if (value) return self.set(i);
self.unset(i);
}
46 changes: 46 additions & 0 deletions test/unit/stdlib/collections/bitmap.c3
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module list_test @test;
import std::collections::bitmap;
import std::collections::list;
import std::io;

def Bitmap = Bitmap(<char>);
def List = List(<usz>);

fn void! set_get()
{
Bitmap bm;
bm.tinit();
assert(bm.len() == 0);

assert(!bm.get(0));
bm.set(0);
assert(bm.get(0));
assert(bm.cardinality() == 1);

assert(!bm.get(2000));
bm[2000] = true;
assert(bm.get(2000));
assert(bm.cardinality() == 2);

List found;
found.tinit();
foreach (i, x : bm)
{
switch (i)
{
case 0:
case 2000:
assert(x);
found.push(i);
default:
assert(!x);
}
}
assert(found.array_view() == usz[]{0, 2000});

bm.unset(0);
assert(!bm.get(0));
bm[2000] = false;
assert(!bm.get(2000));
assert(bm.cardinality() == 0);
}

0 comments on commit dc0c5a4

Please sign in to comment.