|
68 | 68 |
|
69 | 69 | is |
70 | 70 |
|
| 71 | + # element at this index was deleted, this index should be treated as occupied when looking up elements |
| 72 | + # to not cause unexpected gaps that could lead to lost elements |
| 73 | + # for insertions it is treated the same as an empty index |
| 74 | + del is |
| 75 | + |
71 | 76 | # number of entries currently in this map |
72 | 77 | # |
73 | 78 | load := mut 0 |
|
86 | 91 |
|
87 | 92 | # the contents |
88 | 93 | # |
89 | | - contents := mut (LM.env.new_array (option (tuple HK V)) allocated_size.get.as_i64 nil) |
| 94 | + contents := mut (LM.env.new_array (choice nil del (tuple HK V)) allocated_size.get.as_i64 nil) |
90 | 95 |
|
91 | 96 |
|
92 | 97 | # calculate the index of k within contents array in case of no conflict |
|
101 | 106 | # return the next alternative position to check |
102 | 107 | # |
103 | 108 | collision (at i64) => |
104 | | - (at + 1) % allocated_size.get.as_i64 # NYI: dumb collision function, check literature and improve! |
| 109 | + (at + 904644503766293287) % allocated_size.get.as_i64 |
105 | 110 |
|
106 | 111 |
|
107 | 112 | # increase internal allocation if upper_load_factor is reached |
|
127 | 132 | => |
128 | 133 | allocated_size <- new_alloc_size |
129 | 134 | old_contents := contents.get.as_array |
130 | | - contents <- LM.env.new_array (option (tuple HK V)) allocated_size.get.as_i64 nil |
131 | | - for tup in (old_contents.filter o->o??) do |
132 | | - ok, ov := tup.get |
133 | | - store (idx ok) ok ov false |
| 135 | + contents <- LM.env.new_array (choice nil del (tuple HK V)) allocated_size.get.as_i64 nil |
| 136 | + for elem in old_contents do |
| 137 | + match elem |
| 138 | + t tuple HK V => |
| 139 | + ok, ov := t |
| 140 | + store (idx ok) ok ov false false |
| 141 | + * => # noting to add |
134 | 142 |
|
135 | 143 |
|
136 | 144 | # store key value pair at given index |
137 | 145 | # updates value for existing key, does conflict resolution |
138 | 146 | # |
139 | | - store (at i64, k HK, v V, update_size bool) => |
| 147 | + store (at i64, k HK, v V, update_size bool, is_update bool) => |
| 148 | + |
140 | 149 | match contents.get[at] |
141 | 150 | nil => |
142 | | - contents.get[at] := (k, v) # insert new key value pair |
143 | | - if update_size then load <- load.get + 1 |
| 151 | + if is_update |
| 152 | + store (idx k) k v update_size false |
| 153 | + else |
| 154 | + contents.get[at] := (k, v) # insert new key value pair |
| 155 | + if update_size then load <- load.get + 1 |
| 156 | + |
144 | 157 | t tuple => |
145 | 158 | ek, _ := t |
146 | 159 | if ek = k # no conflict, but remapping of k |
147 | 160 | contents.get[at] := (k, v) |
148 | 161 | else # conflict |
149 | | - store (collision at) k v update_size |
| 162 | + store (collision at) k v update_size is_update |
| 163 | + del => |
| 164 | + if is_update |
| 165 | + store (collision at) k v update_size is_update |
| 166 | + else |
| 167 | + contents.get[at] := (k, v) # insert new key value pair |
| 168 | + if update_size then load <- load.get + 1 |
150 | 169 |
|
151 | 170 |
|
152 | 171 | # number of entries in this map |
|
160 | 179 | # |
161 | 180 | public redef put(k HK, v V) unit => |
162 | 181 |
|
163 | | - store (idx k) k v true |
| 182 | + store (idx k) k v true true |
164 | 183 |
|
165 | 184 | increase_if_necessary |
166 | 185 |
|
|
169 | 188 | # |
170 | 189 | public redef get(k HK) option V => |
171 | 190 |
|
172 | | - retrieve (at i64) option V => |
| 191 | + retrieve (at i64, stop_at_start bool) option V => |
173 | 192 | match contents.get[at] |
174 | 193 | nil => nil |
175 | 194 | t tuple => |
176 | 195 | ek, v := t |
177 | 196 | if ek = k |
178 | 197 | v |
179 | 198 | else |
180 | | - retrieve (collision at) |
| 199 | + retrieve (collision at) true |
| 200 | + del => |
| 201 | + (at = start_idx && stop_at_start) ? nil : retrieve (collision at) true |
181 | 202 |
|
182 | | - retrieve (idx k) |
| 203 | + start_idx := idx k |
| 204 | + retrieve start_idx false |
183 | 205 |
|
184 | 206 |
|
185 | 207 | # remove key from map, returns the removed value |
186 | 208 | # |
187 | 209 | public redef remove(k HK) option V => |
188 | 210 |
|
189 | 211 |
|
190 | | - del(del_idx i64) option V => |
| 212 | + delete(del_idx i64, stop_at_start bool) option V => |
191 | 213 | match contents.get[del_idx] |
192 | 214 | nil => nil |
193 | 215 | t tuple => |
194 | 216 | ek, v := t |
195 | 217 | if ek = k |
196 | 218 | contents.get[del_idx] := nil |
197 | 219 | load <- load.get - 1 |
198 | | - fill_hole del_idx (collision del_idx) |
| 220 | + contents.get[del_idx] := del |
199 | 221 | v |
200 | 222 | else |
201 | | - del (collision del_idx) |
| 223 | + delete (collision del_idx) true |
| 224 | + del => |
| 225 | + (stop_at_start && del_idx = del_start_idx) ? nil : delete (collision del_idx) true |
202 | 226 |
|
| 227 | + del_start_idx := idx k |
203 | 228 |
|
204 | | - # move elements if they should be in the position of the removed element |
205 | | - # recursively filles new holes |
206 | | - # |
207 | | - fill_hole(cur_idx, next_idx i64) => |
208 | | - match contents.get[next_idx] |
209 | | - nil => # done |
210 | | - t tuple => |
211 | | - ek, _ := t |
212 | | - |
213 | | - if ( |
214 | | - # not having passed array end: move elements saved at a larger index |
215 | | - (next_idx >= cur_idx && idx ek <= cur_idx) || |
216 | | - |
217 | | - # element index is larger then array index (collision moved it beyond end): |
218 | | - # - always move to left |
219 | | - # - move to right (beyond beginning into the end) if it can normally be saved at that index |
220 | | - (idx ek > next_idx && (cur_idx < next_idx || idx ek <= cur_idx)) || |
221 | | - |
222 | | - # having passed array end: move elements saved at a larger index only if they get moved left (i.e. not beyond the beginning into the end) |
223 | | - (cur_idx < cur_idx && next_idx < cur_idx && idx ek <= cur_idx)) |
224 | | - then |
225 | | - contents.get[cur_idx] := t |
226 | | - contents.get[next_idx] := nil |
227 | | - fill_hole next_idx (collision next_idx) |
228 | | - else |
229 | | - fill_hole cur_idx (collision next_idx) |
230 | | - |
231 | | - return_val := del (idx k) |
| 229 | + return_val := delete del_start_idx false |
232 | 230 |
|
233 | 231 | decrease_if_necessary |
234 | 232 |
|
|
239 | 237 | # |
240 | 238 | public redef items Sequence (tuple HK V) => |
241 | 239 | contents.get.as_array |
242 | | - .filter o->o?? |
243 | | - .map (o -> o.or_else (panic "filter failed")) |
| 240 | + .filter (o -> o ? tuple => true | * => false) |
| 241 | + .map (x -> x ? t tuple => t | * => panic "filter failed" ) |
244 | 242 |
|
245 | 243 |
|
246 | 244 | # create an immutable map from this |
|
0 commit comments