diff options
Diffstat (limited to 'gcc/testsuite/go.test/test/hashmap.go')
-rwxr-xr-x | gcc/testsuite/go.test/test/hashmap.go | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/gcc/testsuite/go.test/test/hashmap.go b/gcc/testsuite/go.test/test/hashmap.go new file mode 100755 index 000000000..096ece0a5 --- /dev/null +++ b/gcc/testsuite/go.test/test/hashmap.go @@ -0,0 +1,181 @@ +// $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. + +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 +} + + +type Array [1024]Entry + +type HashMap struct { + map_ *Array + 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(Array) + 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) 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 *Array = 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) + _, _, _ = x1, x2, x3 + + // this doesn't work I think... + //hmap.Lookup(x1, true) + //hmap.Lookup(x2, true) + //hmap.Lookup(x3, true) + + //print "done\n" +} |