Advertisement
Guest User

Untitled

a guest
Oct 20th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.25 KB | None | 0 0
  1. module main
  2.  
  3. import math
  4.  
  5. [inline]
  6. fn hm_next_power_of_two(_x i64) i64 {
  7. if _x == 0 {
  8. return 1
  9. }
  10.  
  11. mut x := _x
  12. x--
  13. x |= x >> 1
  14. x |= x >> 2
  15. x |= x >> 4
  16. x |= x >> 8
  17. x |= x >> 16
  18. x |= x >> 32
  19.  
  20. return x + 1
  21. }
  22.  
  23. [inline]
  24. fn hm_math_max(num_a, num_b int) int {
  25. if num_a > num_b {
  26. return num_a
  27. }
  28.  
  29. return num_b
  30. }
  31.  
  32. [inline]
  33. fn hm_get_pot_array_size(expected int, factor f32) int {
  34. return hm_math_max(2, int(hm_next_power_of_two(i64(math.ceil(f32(expected) / factor)))))
  35. }
  36.  
  37.  
  38. [inline]
  39. fn hm_phi_mix(x int) int {
  40. h := x * 0x9e3779b9
  41. return h ^ (h >> 16)
  42. }
  43.  
  44. struct IntHashMap {
  45. mut:
  46. fill_factor f32
  47. threshold int
  48. size int
  49. mask u32
  50.  
  51. keys []int
  52. values []voidptr
  53. used []bool
  54. }
  55.  
  56. fn new_int_hash_map(size int, fill_factor f32) &IntHashMap {
  57. mut hash_map := &IntHashMap{}
  58. capacity := hm_get_pot_array_size(size, fill_factor)
  59. hash_map.mask = u32(capacity - 1)
  60. hash_map.fill_factor = fill_factor
  61.  
  62. hash_map.keys = [0].repeat(capacity)
  63. hash_map.values = [voidptr(NULL)].repeat(capacity)
  64. hash_map.used = [false].repeat(capacity)
  65. hash_map.threshold = int(f32(capacity) * f32(fill_factor))
  66.  
  67. return hash_map
  68. }
  69.  
  70. fn (hash_map IntHashMap) get(key int) voidptr {
  71. idx := hash_map._read_index(key)
  72.  
  73. if idx != -1 {
  74. return C.array__get(hash_map.values, idx)
  75. } else {
  76. return NULL
  77. }
  78. }
  79.  
  80. [inline]
  81. fn (hash_map IntHashMap) has(key int) bool {
  82. return hash_map._read_index(key) != -1
  83. }
  84.  
  85.  
  86. fn (hash_map mut IntHashMap) put(key int, value voidptr) {
  87. mut idx := hash_map._put_index(key)
  88. if idx < 0 {
  89. println('no space, rehashing')
  90. hash_map._rehash(hash_map.keys.len * 2)
  91. idx = hash_map._put_index(key)
  92. }
  93.  
  94. //prev := hash_map.values[idx]
  95. if !hash_map.used[idx] {
  96. hash_map.keys[idx] = key
  97. hash_map.values[idx] = value
  98. hash_map.used[idx] = true
  99. hash_map.size++
  100.  
  101. if hash_map.size >= hash_map.threshold {
  102. println('hit hashmap threshold, rehashing')
  103. hash_map._rehash(hash_map.keys.len * 2)
  104. }
  105. } else {
  106. hash_map.values[idx] = value
  107. }
  108.  
  109. //return prev
  110. }
  111.  
  112. [inline]
  113. fn (hash_map IntHashMap) size() int {
  114. return hash_map.size
  115. }
  116.  
  117. fn (hash_map mut IntHashMap) remove(key int) voidptr {
  118. idx := hash_map._read_index(key)
  119.  
  120. if idx == -1 {
  121. return NULL
  122. }
  123.  
  124. res := C.array__get(hash_map.values, idx)
  125. hash_map.size--
  126. hash_map._shift_keys(idx)
  127. return res
  128. }
  129.  
  130. [inline]
  131. fn (hash_map IntHashMap) _start_index(key int) int {
  132. return int(u32(hm_phi_mix(key)) & hash_map.mask)
  133. }
  134.  
  135. [inline]
  136. fn (hash_map IntHashMap) _next_index(key int) int {
  137. return int(u32(key + 1) & hash_map.mask)
  138. }
  139.  
  140. [inline]
  141. fn (hash_map IntHashMap) _read_index(key int) int {
  142. mut idx := hash_map._start_index(key)
  143.  
  144. if !hash_map.used[idx] {
  145. return -1
  146. }
  147.  
  148. if hash_map.keys[idx] == key && hash_map.used[idx] {
  149. return idx
  150. }
  151.  
  152. start_idx := idx
  153. for {
  154. idx = hash_map._next_index(idx)
  155.  
  156. if idx == start_idx || !hash_map.used[idx] {
  157. return -1
  158. }
  159.  
  160. if hash_map.keys[idx] == key && hash_map.used[idx] {
  161. return idx
  162. }
  163. }
  164.  
  165. return -1
  166. }
  167.  
  168. [inline]
  169. fn (hash_map IntHashMap) _put_index(key int) int {
  170. read_idx := hash_map._read_index(key)
  171. if read_idx >= 0 {
  172. return read_idx
  173. }
  174.  
  175. start_idx := hash_map._start_index(key)
  176. mut idx := start_idx
  177.  
  178. for {
  179. if !hash_map.used[idx] {
  180. break
  181. }
  182.  
  183. idx = hash_map._next_index(key)
  184. if idx == start_idx {
  185. return -1
  186. }
  187. }
  188.  
  189. return idx
  190. }
  191.  
  192. fn (hash_map mut IntHashMap) _rehash(new_capacity int) {
  193. hash_map.threshold = int(f32(new_capacity) * f32(hash_map.fill_factor))
  194. hash_map.mask = u32(new_capacity - 1)
  195.  
  196. old_capacity := hash_map.keys.len
  197. old_keys := hash_map.keys
  198. old_values := hash_map.values
  199. old_used := hash_map.used
  200. println('rehash $old_capacity -> $new_capacity')
  201.  
  202. hash_map.keys = [0].repeat(new_capacity)
  203. hash_map.values = [voidptr(NULL)].repeat(new_capacity)
  204. hash_map.used = [false].repeat(new_capacity)
  205. hash_map.size = 0
  206.  
  207. for i := old_capacity; i > 0; i-- {
  208. if old_used[i] {
  209. hash_map.put(old_keys[i], old_values[i])
  210. }
  211. }
  212. }
  213.  
  214. fn (hash_map mut IntHashMap) _shift_keys(_pos int) int {
  215. mut last := 0
  216. mut k := 0
  217. mut pos := _pos
  218.  
  219. for {
  220. last = pos
  221. pos = hash_map._next_index(pos)
  222.  
  223. for {
  224. k = hash_map.keys[pos]
  225. if !hash_map.used[pos] {
  226. hash_map.keys[last] = 0
  227. hash_map.values[last] = voidptr(NULL)
  228. hash_map.used[last] = false
  229.  
  230. return last
  231. }
  232.  
  233. slot := hash_map._start_index(k)
  234.  
  235. if last <= pos {
  236. if last >= slot || slot > pos {
  237. break
  238. }
  239. } else {
  240. if last >= slot && slot > pos {
  241. break
  242. }
  243. }
  244.  
  245. pos = hash_map._next_index(pos)
  246. }
  247.  
  248. hash_map.keys[last] = k
  249. hash_map.values[last] = hash_map.values[pos]
  250. hash_map.used[last] = hash_map.used[pos]
  251. }
  252.  
  253. panic('should not happen!')
  254. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement