booyah
parent
a121f47873
commit
d27d5348f9
50
pmap.go
50
pmap.go
|
@ -50,11 +50,20 @@ func (p pmap) Get(k Key) (Value, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p pmap) Set(k Key, v Value) Map {
|
func (p pmap) Set(k Key, v Value) Map {
|
||||||
|
h := hash(k) // TODO: p.hash
|
||||||
|
root, added := insert(p.root, 0, h, k, v, hash)
|
||||||
|
p.root = root
|
||||||
|
if added {
|
||||||
|
p.len++
|
||||||
|
}
|
||||||
|
//pretty.Println(p)
|
||||||
|
return p
|
||||||
|
|
||||||
//p.root = leaf{k, v}
|
//p.root = leaf{k, v}
|
||||||
//p.len = 1
|
//p.len = 1
|
||||||
//return p
|
//return p
|
||||||
|
|
||||||
h := hash(k) // TODO: p.hash
|
h = hash(k) // TODO: p.hash
|
||||||
n, _ := p.root.(*node)
|
n, _ := p.root.(*node)
|
||||||
if n == nil {
|
if n == nil {
|
||||||
n = &node{}
|
n = &node{}
|
||||||
|
@ -116,9 +125,13 @@ func lookup(root interface{}, shift, hash uint32, key Key) (Value, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func singleton(key Key, val Value, hash, shift uint32) *node {
|
func singleton(key Key, val Value, hash, shift uint32) *node {
|
||||||
|
return newnode(leaf{key, val}, hash, shift)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newnode(child interface{}, hash, shift uint32) *node {
|
||||||
n := &node{}
|
n := &node{}
|
||||||
idx := hash >> shift & mask
|
idx := hash >> shift & mask
|
||||||
n.child[idx] = leaf{key, val}
|
n.child[idx] = child
|
||||||
n.bitmap = 1 << idx
|
n.bitmap = 1 << idx
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
@ -129,8 +142,9 @@ func insert(n interface{}, shift, hash uint32, key Key, val Value, hashFn hashFu
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return leaf{key, val}, true
|
return leaf{key, val}, true
|
||||||
}
|
}
|
||||||
var insert func(n interface{}, shift uint32) interface{}
|
var _insert func(n interface{}, shift uint32) interface{}
|
||||||
insert = func(n interface{}, shift uint32) interface{} {
|
_insert = func(n interface{}, shift uint32) interface{} {
|
||||||
|
//fmt.Printf("insert %v %x %#v\n", shift, hash, n)
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
//case nil:
|
//case nil:
|
||||||
// added = true
|
// added = true
|
||||||
|
@ -145,26 +159,34 @@ func insert(n interface{}, shift, hash uint32, key Key, val Value, hashFn hashFu
|
||||||
added = true
|
added = true
|
||||||
return collision{hash, []leaf{{key, val}, n}}
|
return collision{hash, []leaf{{key, val}, n}}
|
||||||
} else {
|
} else {
|
||||||
|
if h>>shift == hash>>shift {
|
||||||
|
panic("pmap: infinite loop in insert")
|
||||||
|
}
|
||||||
|
// not a collision, so we must still have some hash bits left
|
||||||
// split the trie
|
// split the trie
|
||||||
m := singleton(key, val, hash, shift)
|
m := newnode(n, h, shift)
|
||||||
return insert(m, shift+log2deg)
|
return _insert(m, shift)
|
||||||
}
|
}
|
||||||
case *node:
|
case *node:
|
||||||
c := n.getNode(shift, hash, key)
|
c := n.getNode(shift, hash, key)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
// new node
|
// new node
|
||||||
// TODO
|
c = leaf{key, val}
|
||||||
added = true
|
added = true
|
||||||
return singleton(key, val, shift, hash)
|
|
||||||
} else {
|
} else {
|
||||||
// if it's a leaf and the hashes match, form a collision
|
c = _insert(c, shift+log2deg)
|
||||||
// if we run out of hash, form a leaf
|
|
||||||
//
|
|
||||||
return insert(c, shift+log2deg)
|
|
||||||
}
|
}
|
||||||
|
idx := hash >> shift & mask
|
||||||
|
x := &node{child: n.child, bitmap: n.bitmap}
|
||||||
|
x.child[idx] = c
|
||||||
|
x.bitmap |= 1 << idx
|
||||||
|
return x
|
||||||
case *collision:
|
case *collision:
|
||||||
if n.hash != hash {
|
if n.hash != hash {
|
||||||
panic("hash mismatch") // TODO: can this happen? do we even need collision.hash?
|
// not a collision, so we must still have some hash bits left
|
||||||
|
// split the trie
|
||||||
|
m := newnode(n, n.hash, shift)
|
||||||
|
return _insert(m, shift)
|
||||||
}
|
}
|
||||||
for i := range n.leaf {
|
for i := range n.leaf {
|
||||||
if key == n.leaf[i].k {
|
if key == n.leaf[i].k {
|
||||||
|
@ -184,6 +206,6 @@ func insert(n interface{}, shift, hash uint32, key Key, val Value, hashFn hashFu
|
||||||
panic("pmap: unhandled case in insert")
|
panic("pmap: unhandled case in insert")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newNode = insert(n, shift)
|
newNode = _insert(n, shift)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import "testing"
|
||||||
|
|
||||||
func TestPmap(t *testing.T) {
|
func TestPmap(t *testing.T) {
|
||||||
p := New()
|
p := New()
|
||||||
const numElems = 5
|
const numElems = 100
|
||||||
for i := range make([]int, numElems) {
|
for i := range make([]int, numElems) {
|
||||||
p = p.Set(i, i)
|
p = p.Set(i, i)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue