booyah
This commit is contained in:
		
							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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user