| ... | ... | @@ -137,18 +137,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 137 | 137 | |
| 138 | 138 | fn optimizedCapacity(expected_count: usize) usize { |
| 139 | 139 | // ensure that the hash map will be at most 60% full if |
| 140 | | // new_capacity items are put into the hash map |
| 140 | // expected_count items are put into it |
| 141 | 141 | var optimized_capacity = expected_count * 5 / 3; |
| 142 | 142 | // round capacity to the next power of two |
| 143 | | const is_power_of_two = optimized_capacity & (optimized_capacity-1) == 0; |
| 144 | | if (!is_power_of_two) { |
| 145 | | const pow = math.log2_int_ceil(usize, optimized_capacity); |
| 146 | | optimized_capacity = math.pow(usize, 2, pow); |
| 147 | | } |
| 148 | | return optimized_capacity; |
| 143 | const pow = math.log2_int_ceil(usize, optimized_capacity); |
| 144 | return math.pow(usize, 2, pow); |
| 149 | 145 | } |
| 150 | 146 | |
| 151 | | /// Increase capacity so that the hash map will be at most |
| 147 | /// Increases capacity so that the hash map will be at most |
| 152 | 148 | /// 60% full when expected_count items are put into it |
| 153 | 149 | pub fn ensureCapacity(self: *Self, expected_count: usize) !void { |
| 154 | 150 | const optimized_capacity = optimizedCapacity(expected_count); |
| ... | ... | @@ -168,6 +164,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 |
| 168 | 164 | |
| 169 | 165 | const old_entries = self.entries; |
| 170 | 166 | try self.initCapacity(new_capacity); |
| 167 | self.incrementModificationCount(); |
| 171 | 168 | if (old_entries.len > 0) { |
| 172 | 169 | // dump all of the old elements into the new table |
| 173 | 170 | for (old_entries) |*old_entry| { |
| ... | ... | @@ -467,6 +464,24 @@ test "iterator hash map" { |
| 467 | 464 | testing.expect(entry.value == values[0]); |
| 468 | 465 | } |
| 469 | 466 | |
| 467 | test "ensure capacity" { |
| 468 | var direct_allocator = std.heap.DirectAllocator.init(); |
| 469 | defer direct_allocator.deinit(); |
| 470 | |
| 471 | var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator); |
| 472 | defer map.deinit(); |
| 473 | |
| 474 | try map.ensureCapacity(20); |
| 475 | const initialCapacity = map.entries.len; |
| 476 | testing.expect(initialCapacity >= 20); |
| 477 | var i : i32 = 0; |
| 478 | while (i < 20) : (i += 1) { |
| 479 | testing.expect(map.putAssumeCapacity(i, i+10) == null); |
| 480 | } |
| 481 | // shouldn't resize from putAssumeCapacity |
| 482 | testing.expect(initialCapacity == map.entries.len); |
| 483 | } |
| 484 | |
| 470 | 485 | pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) { |
| 471 | 486 | return struct { |
| 472 | 487 | fn hash(key: K) u32 { |