mirror of
https://github.com/golang/go
synced 2024-11-21 18:04:40 -07:00
- added another test case
SVN=112273
This commit is contained in:
parent
fcf5b15cfe
commit
0908af75cd
186
tests/hashmap.go
Executable file
186
tests/hashmap.go
Executable file
@ -0,0 +1,186 @@
|
||||
// $G $F.go && $L $F.$A && ./$A.out
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// To compile: go hashmap.go && gcc -o g.out main.go.c gort0.c && g.out
|
||||
|
||||
package main
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helper functions
|
||||
|
||||
func ASSERT(p bool) {
|
||||
if !p {
|
||||
// panic 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Implementation of the HashMap
|
||||
|
||||
type KeyType interface {
|
||||
Hash() uint32;
|
||||
Match(other *KeyType) bool
|
||||
}
|
||||
|
||||
|
||||
type ValueType interface {
|
||||
// empty interface
|
||||
}
|
||||
|
||||
|
||||
type Entry struct {
|
||||
key *KeyType;
|
||||
value *ValueType;
|
||||
}
|
||||
|
||||
|
||||
// Using the Array type below doesn't seem to work
|
||||
//type Array array [1024] Entry;
|
||||
|
||||
type HashMap struct {
|
||||
map_ *[1024] Entry;
|
||||
log2_capacity_ uint32;
|
||||
occupancy_ uint32;
|
||||
}
|
||||
|
||||
|
||||
func (m *HashMap) capacity() uint32 {
|
||||
return 1 << m.log2_capacity_;
|
||||
}
|
||||
|
||||
|
||||
func (m *HashMap) Clear() {
|
||||
// Mark all entries as empty.
|
||||
var i uint32 = m.capacity() - 1;
|
||||
for i > 0 {
|
||||
m.map_[i].key = nil;
|
||||
i = i - 1;
|
||||
}
|
||||
m.occupancy_ = 0;
|
||||
}
|
||||
|
||||
|
||||
func (m *HashMap) Initialize (initial_log2_capacity uint32) {
|
||||
m.log2_capacity_ = initial_log2_capacity;
|
||||
m.map_ = new([1024] Entry);
|
||||
m.Clear();
|
||||
}
|
||||
|
||||
|
||||
func (m *HashMap) Probe (key *KeyType) *Entry {
|
||||
ASSERT(key != nil);
|
||||
|
||||
var i uint32 = key.Hash() % m.capacity();
|
||||
ASSERT(0 <= i && i < m.capacity());
|
||||
|
||||
ASSERT(m.occupancy_ < m.capacity()); // guarantees loop termination
|
||||
for m.map_[i].key != nil && !m.map_[i].key.Match(key) {
|
||||
i++;
|
||||
if i >= m.capacity() {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return &m.map_[i];
|
||||
}
|
||||
|
||||
|
||||
func (m *HashMap) Resize();
|
||||
|
||||
|
||||
func (m *HashMap) Lookup (key *KeyType, insert bool) *Entry {
|
||||
// Find a matching entry.
|
||||
var p *Entry = m.Probe(key);
|
||||
if p.key != nil {
|
||||
return p;
|
||||
}
|
||||
|
||||
// No entry found; insert one if necessary.
|
||||
if insert {
|
||||
p.key = key;
|
||||
p.value = nil;
|
||||
m.occupancy_++;
|
||||
|
||||
// Grow the map if we reached >= 80% occupancy.
|
||||
if m.occupancy_ + m.occupancy_/4 >= m.capacity() {
|
||||
m.Resize();
|
||||
p = m.Probe(key);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// No entry found and none inserted.
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
func (m *HashMap) Resize() {
|
||||
var hmap *[1024] Entry = m.map_;
|
||||
var n uint32 = m.occupancy_;
|
||||
|
||||
// Allocate a new map of twice the current size.
|
||||
m.Initialize(m.log2_capacity_ << 1);
|
||||
|
||||
// Rehash all current entries.
|
||||
var i uint32 = 0;
|
||||
for n > 0 {
|
||||
if hmap[i].key != nil {
|
||||
m.Lookup(hmap[i].key, true).value = hmap[i].value;
|
||||
n = n - 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Test code
|
||||
|
||||
type Number struct {
|
||||
x uint32;
|
||||
}
|
||||
|
||||
|
||||
func (n *Number) Hash() uint32 {
|
||||
return n.x * 23;
|
||||
}
|
||||
|
||||
|
||||
func (n *Number) Match(other *KeyType) bool {
|
||||
// var y *Number = other;
|
||||
// return n.x == y.x;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
func MakeNumber (x uint32) *Number {
|
||||
var n *Number = new(Number);
|
||||
n.x = x;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
func (n int) int { return n + 1; }(1);
|
||||
|
||||
print "HashMap - gri 2/8/2008\n";
|
||||
|
||||
var hmap *HashMap = new(HashMap);
|
||||
hmap.Initialize(0);
|
||||
|
||||
var x1 *Number = MakeNumber(1001);
|
||||
var x2 *Number = MakeNumber(2002);
|
||||
var x3 *Number = MakeNumber(3003);
|
||||
|
||||
// this doesn't work I think...
|
||||
//hmap.Lookup(x1, true);
|
||||
//hmap.Lookup(x2, true);
|
||||
//hmap.Lookup(x3, true);
|
||||
|
||||
print "done\n";
|
||||
}
|
Loading…
Reference in New Issue
Block a user