mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
wyhash: stateless is faster for both iterative hashing and small keys.
This commit is contained in:
parent
4b5172d287
commit
3faf5d3857
@ -33,16 +33,11 @@ fn mix1(a: u64, b: u64, seed: u64) u64 {
|
||||
|
||||
pub const Wyhash = struct {
|
||||
seed: u64,
|
||||
|
||||
buf: [32]u8,
|
||||
buf_len: usize,
|
||||
msg_len: usize,
|
||||
|
||||
pub fn init(seed: u64) Wyhash {
|
||||
return Wyhash{
|
||||
.seed = seed,
|
||||
.buf = undefined,
|
||||
.buf_len = 0,
|
||||
.msg_len = 0,
|
||||
};
|
||||
}
|
||||
@ -61,34 +56,12 @@ pub const Wyhash = struct {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update(self: *Wyhash, b: []const u8) void {
|
||||
var off: usize = 0;
|
||||
fn partial(self: *Wyhash, b: []const u8) void {
|
||||
const rem_key = b;
|
||||
const rem_len = b.len;
|
||||
|
||||
// Partial from previous.
|
||||
if (self.buf_len != 0 and self.buf_len + b.len > 32) {
|
||||
off += 32 - self.buf_len;
|
||||
mem.copy(u8, self.buf[self.buf_len..], b[0..off]);
|
||||
self.round(self.buf[0..]);
|
||||
self.buf_len = 0;
|
||||
}
|
||||
|
||||
// Full middle blocks.
|
||||
while (off + 32 <= b.len) : (off += 32) {
|
||||
@inlineCall(self.round, b[off .. off + 32]);
|
||||
}
|
||||
|
||||
// Remainder for next pass.
|
||||
mem.copy(u8, self.buf[self.buf_len..], b[off..]);
|
||||
self.buf_len += @intCast(u8, b[off..].len);
|
||||
self.msg_len += b.len;
|
||||
}
|
||||
|
||||
pub fn final(self: *Wyhash) u64 {
|
||||
const seed = self.seed;
|
||||
const rem_len = @intCast(u5, self.buf_len);
|
||||
const rem_key = self.buf[0..self.buf_len];
|
||||
|
||||
self.seed = switch (rem_len) {
|
||||
var seed = self.seed;
|
||||
seed = switch (@intCast(u5, rem_len)) {
|
||||
0 => seed,
|
||||
1 => mix0(read_bytes(1, rem_key), primes[4], seed),
|
||||
2 => mix0(read_bytes(2, rem_key), primes[4], seed),
|
||||
@ -122,7 +95,22 @@ pub const Wyhash = struct {
|
||||
30 => mix0(read_8bytes_swapped(rem_key), read_8bytes_swapped(rem_key[8..]), seed) ^ mix1(read_8bytes_swapped(rem_key[16..]), (read_bytes(4, rem_key[24..]) << 16) | read_bytes(2, rem_key[28..]), seed),
|
||||
31 => mix0(read_8bytes_swapped(rem_key), read_8bytes_swapped(rem_key[8..]), seed) ^ mix1(read_8bytes_swapped(rem_key[16..]), (read_bytes(4, rem_key[24..]) << 24) | (read_bytes(2, rem_key[28..]) << 8) | read_bytes(1, rem_key[30..]), seed),
|
||||
};
|
||||
self.seed = seed;
|
||||
}
|
||||
|
||||
pub fn update(self: *Wyhash, b: []const u8) void {
|
||||
var off: usize = 0;
|
||||
|
||||
// Full middle blocks.
|
||||
while (off + 32 <= b.len) : (off += 32) {
|
||||
@inlineCall(self.round, b[off .. off + 32]);
|
||||
}
|
||||
|
||||
self.partial(b[off..]);
|
||||
self.msg_len += b.len;
|
||||
}
|
||||
|
||||
pub fn final(self: *Wyhash) u64 {
|
||||
return mum(self.seed ^ self.msg_len, primes[4]);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user