// run

// 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"
}
