Skip to content

Commit

Permalink
Merge pull request #310 from moonbitlang/hongbo/builtin_popcnt
Browse files Browse the repository at this point in the history
tweak hamt
  • Loading branch information
bobzhang authored Apr 23, 2024
2 parents 8396d8b + def1233 commit 431458b
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 70 deletions.
2 changes: 1 addition & 1 deletion immutable_hashmap/HAMT.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn add_with_hash[K : Eq, V](
hash.lsr(segment_length),
value,
)
Map::Branch(SparseArray::make(idx, child))
Map::Branch(singleton(idx, child))
}
}

Expand Down
3 changes: 1 addition & 2 deletions immutable_hashmap/bitset.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ test "Bitset::has" {
///
/// Get the index of the bit in the bitset.
fn index_of(self : Bitset, idx : Int) -> Int {
let items_below_idx = self.0.land((1).lsl(idx) - 1)
items_below_idx.popcnt()
self.0.land((1).lsl(idx) - 1).popcnt()
}

test "Bitset::index_of" {
Expand Down
47 changes: 19 additions & 28 deletions immutable_hashmap/bucket.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -69,39 +69,30 @@ fn remove[K : Eq, V](self : Bucket[K, V], key : K) -> Option[Bucket[K, V]] {

/// Get the size of a bucket
fn size[K, V](self : Bucket[K, V]) -> Int {
match self {
Just_One(_) => 1
More(_, _, rest) => rest.size() + 1
}
loop self, 1 {
Just_One(_), acc => acc
More(_,_, rest), acc => continue rest, acc + 1
}
}

test "Bucket" {
let b : Bucket[_] = Just_One(0, 0)
@assertion.assert_eq(b.find(0), Some(0))?
@assertion.assert_eq(b.find(1), None)?
@assertion.assert_eq(b.size(), 1)?
let b = b.add(1, 1)
@assertion.assert_eq(b.find(0), Some(0))?
@assertion.assert_eq(b.find(1), Some(1))?
@assertion.assert_eq(b.size(), 2)?
let b = b.add(0, 2)
@assertion.assert_eq(b.find(0), Some(2))?
@assertion.assert_eq(b.find(1), Some(1))?
@assertion.assert_eq(b.size(), 2)?
match b.remove(0) {
None => @assertion.assert_true(false)?
Some(b1) => {
@assertion.assert_eq(b1.find(0), None)?
@assertion.assert_eq(b1.find(1), Some(1))?
}
let b0 : Bucket[_] = Just_One(0, 0)
inspect((b0.find(0),b0.find(1),b0.size()), ~content="(Some(0), None, 1)")?
let b1 = b0.add(1, 1)
inspect((b1.find(0),b1.find(1),b1.size()), ~content="(Some(0), Some(1), 2)")?
let b2 = b1.add(0, 2)
inspect((b2.find(0),b2.find(1),b2.size()), ~content="(Some(2), Some(1), 2)")?
let b3 = b2.remove(0)
{
let b1 = b3.unwrap()
inspect((b1.find(0),b1.find(1)), ~content="(None, Some(1))")?
}
match b.remove(1) {
None => @assertion.assert_true(false)?
Some(b1) => {
@assertion.assert_eq(b1.find(0), Some(2))?
@assertion.assert_eq(b1.find(1), None)?
}
let b4 = b2.remove(1)
{
let b1 = b4.unwrap() // b4 ? --> return Option instead of Result
inspect((b1.find(0),b1.find(1)), ~content="(Some(2), None)")?
}

}

/// Iterate through elements of a bucket
Expand Down
5 changes: 3 additions & 2 deletions immutable_hashmap/moon.pkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"moonbitlang/core/tuple",
"moonbitlang/core/array",
"moonbitlang/core/int",
"moonbitlang/core/coverage"
"moonbitlang/core/coverage",
"moonbitlang/core/option"
]
}
}
50 changes: 13 additions & 37 deletions immutable_hashmap/sparse_array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ priv struct SparseArray[X] {
data : Array[X]
}

fn SparseArray::make[X](idx : Int, value : X) -> SparseArray[X] {
fn SparseArray::singleton[X](idx : Int, value : X) -> SparseArray[X] {
{ elem_info: empty_bitset.add(idx), data: [value] }
}

Expand All @@ -40,20 +40,16 @@ fn op_get[X](self : SparseArray[X], idx : Int) -> Option[X] {
///
/// Add a new element into the sparse array.
/// [idx] must be absent from [self]
/// TODO: use blit intrinsic instead
fn add[X](self : SparseArray[X], idx : Int, value : X) -> SparseArray[X] {
let new_len = self.data.length() + 1
let pos_of_new_item = self.elem_info.index_of(idx)
let new_data = Array::make(new_len, value)
let mut i = 0
while i < pos_of_new_item {
for i = 0; i < pos_of_new_item; i = i + 1 {
new_data[i] = self.data[i]
i = i + 1
}
new_data[i] = value
i = i + 1
while i < new_len {
for i = pos_of_new_item + 1 ; i < new_len ; i = i + 1{
new_data[i] = self.data[i - 1]
i = i + 1
}
{ elem_info: self.elem_info.add(idx), data: new_data }
}
Expand All @@ -72,34 +68,14 @@ fn replace[X](self : SparseArray[X], idx : Int, value : X) -> SparseArray[X] {
}

test "SparseArray" {
let arr = SparseArray::make(1, 1)
@assertion.assert_false(arr.has(0))?
@assertion.assert_eq(arr[0], None)?
@assertion.assert_true(arr.has(1))?
@assertion.assert_eq(arr[1], Some(1))?
@assertion.assert_false(arr.has(2))?
@assertion.assert_eq(arr[2], None)?
let arr = arr.add(2, 2)
@assertion.assert_false(arr.has(0))?
@assertion.assert_eq(arr[0], None)?
@assertion.assert_true(arr.has(1))?
@assertion.assert_eq(arr[1], Some(1))?
@assertion.assert_true(arr.has(2))?
@assertion.assert_eq(arr[2], Some(2))?
let arr = arr.add(0, 0)
@assertion.assert_true(arr.has(0))?
@assertion.assert_eq(arr[0], Some(0))?
@assertion.assert_true(arr.has(1))?
@assertion.assert_eq(arr[1], Some(1))?
@assertion.assert_true(arr.has(2))?
@assertion.assert_eq(arr[2], Some(2))?
let arr = arr.replace(1, 42)
@assertion.assert_true(arr.has(0))?
@assertion.assert_eq(arr[0], Some(0))?
@assertion.assert_true(arr.has(1))?
@assertion.assert_eq(arr[1], Some(42))?
@assertion.assert_true(arr.has(2))?
@assertion.assert_eq(arr[2], Some(2))?
let arr0 = singleton(1, 1)
inspect((arr0.has(0),arr0[0],arr0.has(1),arr0[1],arr0.has(2),arr0[2]), ~content="(false, None, true, Some(1), false, None)")?
let arr1 = arr0.add(2, 2)
inspect((arr1.has(0),arr1[0],arr1.has(1),arr1[1],arr1.has(2),arr1[2]), ~content="(false, None, true, Some(1), true, Some(2))")?
let arr2 = arr1.add(0, 0)
inspect((arr2.has(0),arr2[0],arr2.has(1),arr2[1],arr2.has(2),arr2[2]), ~content="(true, Some(0), true, Some(1), true, Some(2))")?
let arr3 = arr2.replace(1, 42)
inspect((arr3.has(0),arr3[0],arr3.has(1),arr3[1],arr3.has(2),arr3[2]), ~content="(true, Some(0), true, Some(42), true, Some(2))")?
}

/// `size(self: SparseArray[X]) -> Int`
Expand All @@ -119,7 +95,7 @@ fn iter[X](self : SparseArray[X], f : (X) -> Unit) -> Unit {
}

test "SparseArray::iter" {
let arr = SparseArray::make(0, 0).add(1, 1).add(3, 3).add(31, 31)
let arr = singleton(0, 0).add(1, 1).add(3, 3).add(31, 31)
let buf = Buffer::make(0)
let mut is_first = true
arr.iter(
Expand Down

0 comments on commit 431458b

Please sign in to comment.