83 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			V
		
	
	
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
 | 
						|
// Use of this source code is governed by an MIT license
 | 
						|
// that can be found in the LICENSE file.
 | 
						|
 | 
						|
module builtin
 | 
						|
 | 
						|
/*
 | 
						|
	This is work in progress.
 | 
						|
	A very early test version of the hashmap with a fixed size.
 | 
						|
	Only works with string keys and int values for now.
 | 
						|
	
 | 
						|
	I added this to improve performance of the V compiler,
 | 
						|
	which uses lots of O(log n) map get's. Turned out with N < 10 000
 | 
						|
	the performance gains are basically non-existent.
 | 
						|
*/
 | 
						|
 | 
						|
struct hashmap {
 | 
						|
	cap          int
 | 
						|
	keys         []string
 | 
						|
	table        []hashmapentry
 | 
						|
	elm_size int
 | 
						|
pub:
 | 
						|
	nr_collisions int
 | 
						|
}
 | 
						|
 | 
						|
struct hashmapentry {
 | 
						|
        key string
 | 
						|
        val int
 | 
						|
        next &hashmapentry  // linked list for collisions
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	min_cap = 2 << 10
 | 
						|
	max_cap = 2 << 20
 | 
						|
)
 | 
						|
 | 
						|
fn new_hashmap(planned_nr_items int) hashmap {
 | 
						|
	mut cap := planned_nr_items * 5
 | 
						|
	if cap < min_cap {
 | 
						|
		cap = min_cap
 | 
						|
	}	
 | 
						|
	if cap > max_cap {
 | 
						|
		cap = max_cap
 | 
						|
	}	
 | 
						|
	return hashmap{
 | 
						|
		cap: cap
 | 
						|
		elm_size: 4
 | 
						|
		table: make(cap, cap, sizeof(hashmapentry))
 | 
						|
	}	
 | 
						|
}	
 | 
						|
 | 
						|
fn (m mut hashmap) set(key string, val int) {
 | 
						|
	mut hash := int(b_fabs( key.hash() ))
 | 
						|
	idx := hash % m.cap
 | 
						|
	if m.table[idx].key.len != 0 {
 | 
						|
		//println('\nset() idx=$idx key="$key" hash="$hash" val=$val')
 | 
						|
		m.nr_collisions++
 | 
						|
		//println('collision:' + m.table[idx].key)
 | 
						|
		mut e := &m.table[idx]
 | 
						|
		for e.next != 0 {
 | 
						|
			e = e.next
 | 
						|
		}	
 | 
						|
		e.next = &hashmapentry{key, val, 0}
 | 
						|
	} else {
 | 
						|
		m.table[idx] = hashmapentry{key, val, 0}
 | 
						|
	}
 | 
						|
}	
 | 
						|
 | 
						|
fn (m mut hashmap) get(key string) int {
 | 
						|
	hash := int(b_fabs( key.hash() ))
 | 
						|
	idx := hash % m.cap
 | 
						|
	mut e := &m.table[idx]
 | 
						|
	for e.next != 0 { // todo unsafe {
 | 
						|
		if e.key == key {
 | 
						|
			return e.val
 | 
						|
		}	
 | 
						|
		e = e.next
 | 
						|
	}	
 | 
						|
	return e.val
 | 
						|
}
 | 
						|
 | 
						|
[inline] fn b_fabs(v int) f64 { return if v < 0 { -v } else { v } }
 |