summaryrefslogtreecommitdiff
path: root/src/comptime_map.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/comptime_map.zig')
-rw-r--r--src/comptime_map.zig24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/comptime_map.zig b/src/comptime_map.zig
index d41f6f8..3d61bd6 100644
--- a/src/comptime_map.zig
+++ b/src/comptime_map.zig
@@ -38,7 +38,7 @@ pub fn ComptimeHashMap(comptime K: type, comptime V: type, comptime ctx: type, c
38 var key: K = kv.@"0"; 38 var key: K = kv.@"0";
39 var value: V = kv.@"1"; 39 var value: V = kv.@"1";
40 40
41 const start_index = @as(usize, ctx.hash(undefined, key)) & (size - 1); 41 const start_index = reduceMulHi(ctx.hash(undefined, key), size);
42 42
43 var roll_over = 0; 43 var roll_over = 0;
44 var distance_from_start_index = 0; 44 var distance_from_start_index = 0;
@@ -88,7 +88,7 @@ pub fn ComptimeHashMap(comptime K: type, comptime V: type, comptime ctx: type, c
88 } 88 }
89 89
90 pub fn get(key: K) ?*const V { 90 pub fn get(key: K) ?*const V {
91 const start_index = @as(usize, ctx.hash(undefined, key)) & (size - 1); 91 const start_index = reduceMulHi(ctx.hash(undefined, key), size);
92 { 92 {
93 var roll_over: usize = 0; 93 var roll_over: usize = 0;
94 while (roll_over <= max_distance_from_start_index) : (roll_over += 1) { 94 while (roll_over <= max_distance_from_start_index) : (roll_over += 1) {
@@ -104,6 +104,11 @@ pub fn ComptimeHashMap(comptime K: type, comptime V: type, comptime ctx: type, c
104 }; 104 };
105} 105}
106 106
107fn reduceMulHi(h: u64, m: u64) u64 {
108 // floor((h * m) / 2^64)
109 return @as(u64, @truncate((@as(u128, h) * @as(u128, m)) >> 64));
110}
111
107test "basic usage" { 112test "basic usage" {
108 const map = ComptimeStringHashMap(usize, .{ 113 const map = ComptimeStringHashMap(usize, .{
109 .{ "foo", 1 }, 114 .{ "foo", 1 },
@@ -157,6 +162,20 @@ test "array pair comptime hash map" {
157 try testing.expect(map.has(.{ 2, 4 })); 162 try testing.expect(map.has(.{ 2, 4 }));
158} 163}
159 164
165test "Next version tripwire" {
166 // Check for the bug on each version bump, if it goes away,
167 // well, that's useful information.
168 const v = @import("builtin").zig_version;
169 if (v.major == 0 and v.minor <= 15) return;
170 const map = AutoComptimeHashMap([2]u21, u21, .{
171 .{ .{ 2, 3 }, 5 },
172 .{ .{ 42, 56 }, 12 },
173 .{ .{ 2, 4 }, 6 },
174 });
175 try testing.expect(map.has(.{ 2, 3 })); // Still buggy :/
176 try testing.expect(map.has(.{ 23, 42 })); // No bug! :D
177}
178
160const std = @import("std"); 179const std = @import("std");
161const hash_map = std.hash_map; 180const hash_map = std.hash_map;
162const testing = std.testing; 181const testing = std.testing;
@@ -183,4 +202,3 @@ const math = std.math;
183// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 202// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
184// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 203// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
185// SOFTWARE. 204// SOFTWARE.
186