authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-19 11:49:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-19 11:49:33-07:00
loga0d16829215f56fe42548f1014cba0f2df5a1609
treeb37c997e1b59a14cc8144df791029492b64ca79a
parent4e6a04929d22015c85780f08fe46d6378ae82b66

std.hash.RapidHash: remove

Its design keeps evolving. See https://github.com/Nicoshev/rapidhash/releases It's great to see the design improving, but over time, this will lead to code rot; versions that aren't widely used but would still have to live in the standard library forever and be maintained. Better to be maintained as an external dependency that applications can opt into. Then, in a few years, if a version proves to be stable and widely adopted, it could be considered for inclusion in the standard library.

3 files changed, 0 insertions(+), 133 deletions(-)

lib/std/hash.zig-2
......@@ -32,8 +32,6 @@ pub const CityHash64 = cityhash.CityHash64;
3232const wyhash = @import("hash/wyhash.zig");
3333pub const Wyhash = wyhash.Wyhash;
3434
35pub const RapidHash = @import("hash/RapidHash.zig");
36
3735const xxhash = @import("hash/xxhash.zig");
3836pub const XxHash3 = xxhash.XxHash3;
3937pub const XxHash64 = xxhash.XxHash64;
lib/std/hash/RapidHash.zig deleted-125
......@@ -1,125 +0,0 @@
1const std = @import("std");
2
3const readInt = std.mem.readInt;
4const assert = std.debug.assert;
5const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
7
8const RAPID_SEED: u64 = 0xbdd89aa982704029;
9const RAPID_SECRET: [3]u64 = .{ 0x2d358dccaa6c78a5, 0x8bb84b93962eacc9, 0x4b33a62ed433d4a3 };
10
11pub fn hash(seed: u64, input: []const u8) u64 {
12 const sc = RAPID_SECRET;
13 const len = input.len;
14 var a: u64 = 0;
15 var b: u64 = 0;
16 var k = input;
17 var is: [3]u64 = .{ seed, 0, 0 };
18
19 is[0] ^= mix(seed ^ sc[0], sc[1]) ^ len;
20
21 if (len <= 16) {
22 if (len >= 4) {
23 const d: usize = ((len & 24) >> @intCast(len >> 3));
24 const e = len - 4;
25 a = (r32(k) << 32) | r32(k[e..]);
26 b = ((r32(k[d..]) << 32) | r32(k[(e - d)..]));
27 } else if (len > 0)
28 a = (@as(u64, k[0]) << 56) | (@as(u64, k[len >> 1]) << 32) | @as(u64, k[len - 1]);
29 } else {
30 var remain = len;
31 if (len > 48) {
32 is[1] = is[0];
33 is[2] = is[0];
34 while (remain >= 96) {
35 inline for (0..6) |i| {
36 const m1 = r64(k[8 * i * 2 ..]);
37 const m2 = r64(k[8 * (i * 2 + 1) ..]);
38 is[i % 3] = mix(m1 ^ sc[i % 3], m2 ^ is[i % 3]);
39 }
40 k = k[96..];
41 remain -= 96;
42 }
43 if (remain >= 48) {
44 inline for (0..3) |i| {
45 const m1 = r64(k[8 * i * 2 ..]);
46 const m2 = r64(k[8 * (i * 2 + 1) ..]);
47 is[i] = mix(m1 ^ sc[i], m2 ^ is[i]);
48 }
49 k = k[48..];
50 remain -= 48;
51 }
52
53 is[0] ^= is[1] ^ is[2];
54 }
55
56 if (remain > 16) {
57 is[0] = mix(r64(k) ^ sc[2], r64(k[8..]) ^ is[0] ^ sc[1]);
58 if (remain > 32) {
59 is[0] = mix(r64(k[16..]) ^ sc[2], r64(k[24..]) ^ is[0]);
60 }
61 }
62
63 a = r64(input[len - 16 ..]);
64 b = r64(input[len - 8 ..]);
65 }
66
67 a ^= sc[1];
68 b ^= is[0];
69 mum(&a, &b);
70 return mix(a ^ sc[0] ^ len, b ^ sc[1]);
71}
72
73test "RapidHash.hash" {
74 const bytes: []const u8 = "abcdefgh" ** 128;
75
76 const sizes: [13]u64 = .{ 0, 1, 2, 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
77
78 const outcomes: [13]u64 = .{
79 0x5a6ef77074ebc84b,
80 0xc11328477bc0f5d1,
81 0x5644ac035e40d569,
82 0x347080fbf5fcd81,
83 0x56b66b8dc802bcc,
84 0xb6bf9055973aac7c,
85 0xed56d62eead1e402,
86 0xc19072d767da8ffb,
87 0x89bb40a9928a4f0d,
88 0xe0af7c5e7b6e29fd,
89 0x9a3ed35fbedfa11a,
90 0x4c684b2119ca19fb,
91 0x4b575f5bf25600d6,
92 };
93
94 var success: bool = true;
95 for (sizes, outcomes) |s, e| {
96 const r = hash(RAPID_SEED, bytes[0..s]);
97
98 expectEqual(e, r) catch |err| {
99 std.debug.print("Failed on {d}: {!}\n", .{ s, err });
100 success = false;
101 };
102 }
103 try expect(success);
104}
105
106inline fn mum(a: *u64, b: *u64) void {
107 const r = @as(u128, a.*) * b.*;
108 a.* = @truncate(r);
109 b.* = @truncate(r >> 64);
110}
111
112inline fn mix(a: u64, b: u64) u64 {
113 var copy_a = a;
114 var copy_b = b;
115 mum(&copy_a, &copy_b);
116 return copy_a ^ copy_b;
117}
118
119inline fn r64(p: []const u8) u64 {
120 return readInt(u64, p[0..8], .little);
121}
122
123inline fn r32(p: []const u8) u64 {
124 return readInt(u32, p[0..4], .little);
125}
lib/std/hash/benchmark.zig-6
......@@ -59,12 +59,6 @@ const hashes = [_]Hash{
5959 .ty = hash.crc.Crc32,
6060 .name = "crc32",
6161 },
62 Hash{
63 .ty = hash.RapidHash,
64 .name = "rapidhash",
65 .has_iterative_api = false,
66 .init_u64 = 0,
67 },
6862 Hash{
6963 .ty = hash.CityHash32,
7064 .name = "cityhash-32",