tiny.simd.ShardMul
Defined in shardmul.
API (12)
Actions
Public operations.
Types and contracts
Public types and contracts.
Fields and members
Public fields and members.
Source
Source: lib/simd/src/shardmul.zig:19
zig
pub const ShardMul = struct { table: [bucket_count]u32, rounds: [4]hash_mod.WeakTwoMul, const Self = @This(); pub const FeistelPair = struct { left: u32, right: u32, }; pub fn init(data: ShardMulData) Self { return .{ .table = data.table, .rounds = .{ hash_mod.WeakTwoMul.initKey(data.keys[0]), hash_mod.WeakTwoMul.initKey(data.keys[1]), hash_mod.WeakTwoMul.initKey(data.keys[2]), hash_mod.WeakTwoMul.initKey(data.keys[3]), }, }; } pub fn isEmpty(self: Self) bool { if (self.table[0] == 0) return true; for (self.table) |entry| { if (entry == 0) @panic("ShardMul table contains a zero multiplier"); } return false; } pub fn feistel(self: Self, input: u64) FeistelPair { var left: u32 = @truncate(input); var right: u32 = @truncate(input >> 32); left ^= self.rounds[0].hash(right); right ^= self.rounds[1].hash(left); left ^= self.rounds[2].hash(right); right ^= self.rounds[3].hash(left); return .{ .left = left, .right = right }; } pub fn bucketIndex(left: u32) u32 { return left >> 28; } pub fn lookupMul(self: Self, bucket: u32) u32 { std.debug.assert(bucket < bucket_count); return self.table[bucket]; } pub fn hash(self: Self, input: u64) u32 { std.debug.assert(!self.isEmpty()); const pair = self.feistel(input); return mulAndXorScalar(pair.left, pair.right, self.lookupMul(bucketIndex(pair.left))); } pub fn oneVec(self: Self, comptime D64: type, input: D64.Vector) D64.rebind(u32).Vector { requireTag(D64, u64); std.debug.assert(!self.isEmpty()); const D32 = D64.rebind(u32); var left: D32.Vector = undefined; var right: D32.Vector = undefined; inline for (0..D64.lane_count) |lane| { left[lane] = @truncate(input[lane]); right[lane] = @truncate(input[lane] >> 32); } return self.resultFromFeistel(D32, self.feistelVector(D32, left, right)); } pub fn twoVec( self: Self, comptime D32: type, first: D32.repartition(u64).Vector, second: D32.repartition(u64).Vector, ) D32.Vector { requireTag(D32, u32); if (D32.lane_count < 2) @compileError("ShardMul twoVec requires at least two u32 lanes"); std.debug.assert(!self.isEmpty()); const D64 = D32.repartition(u64); var left: D32.Vector = undefined; var right: D32.Vector = undefined; inline for (0..D64.lane_count) |lane| { left[lane] = @truncate(first[lane]); right[lane] = @truncate(first[lane] >> 32); left[D64.lane_count + lane] = @truncate(second[lane]); right[D64.lane_count + lane] = @truncate(second[lane] >> 32); } return self.resultFromFeistel(D32, self.feistelVector(D32, left, right)); } pub fn mulAndXor( comptime D32: type, left: D32.Vector, right: D32.Vector, muls: D32.Vector, ) D32.Vector { requireTag(D32, u32); const D16 = D32.repartition(u16); const products = multiply.mulHigh( D16, @as(D16.Vector, @bitCast(right)), @as(D16.Vector, @bitCast(muls)), ); const mixed: D32.Vector = @bitCast(products); return left ^ (mixed & @as(D32.Vector, @splat(0x0fff_ffff))); } fn feistelVector( self: Self, comptime D32: type, initial_left: D32.Vector, initial_right: D32.Vector, ) VectorPair(D32) { var left = initial_left; var right = initial_right; left ^= self.rounds[0].oneVec(D32, right); right ^= self.rounds[1].oneVec(D32, left); left ^= self.rounds[2].oneVec(D32, right); right ^= self.rounds[3].oneVec(D32, left); return .{ .left = left, .right = right }; } fn resultFromFeistel(self: Self, comptime D32: type, pair: VectorPair(D32)) D32.Vector { const buckets = shift.shiftRight(D32, 28, pair.left); const muls = table.lookup16(D32, &self.table, buckets); return mulAndXor(D32, pair.left, pair.right, muls); }};Source: lib/simd/src/root.zig:622
zig
pub const ShardMul = shardmul.ShardMul;Complete caller list for ShardMul.init
8 direct callers.
tiny.simd.ShardMulPlan.build[method] atlib/simd/src/shardmul.zig:225tiny.simd.ShardMulPlan.inspect[function] atlib/simd/src/shardmul.zig:164tiny.simd.shardmul.makeShardMul[function] atlib/simd/src/shardmul.zig:328lib.simd.src.shardmul.test_Highway_ShardMul_builder_produces_collision-free_outputs_and_excludes_extras[function] — test source atlib/simd/src/shardmul.zig:503in nearest public ownertiny.simd.shardmullib.simd.src.shardmul.test_Highway_ShardMul_builder_remains_collision-free_for_clustered_keys[function] — test source atlib/simd/src/shardmul.zig:534in nearest public ownertiny.simd.shardmullib.simd.src.shardmul.test_Highway_ShardMul_plans_enforce_scratch_and_input_distributions[function] — test source atlib/simd/src/shardmul.zig:554in nearest public ownertiny.simd.shardmullib.simd.src.shardmul.test_Highway_ShardMul_scalar_and_vector_queries_agree[function] — test source atlib/simd/src/shardmul.zig:409in nearest public ownertiny.simd.shardmullib.simd.src.shardmul.test_Highway_ShardMul_single-worker_builder_oracle_matches_exactly[function] — test source atlib/simd/src/shardmul.zig:448in nearest public ownertiny.simd.shardmul
Complete caller list for ShardMul.isEmpty
7 direct callers.
tiny.simd.ShardMul.hash[method] atlib/simd/src/shardmul.zig:69tiny.simd.ShardMul.oneVec[method] atlib/simd/src/shardmul.zig:75tiny.simd.ShardMul.twoVec[method] atlib/simd/src/shardmul.zig:88lib.simd.src.shardmul.test_Highway_ShardMul_builder_produces_collision-free_outputs_and_excludes_extras[function] — test source atlib/simd/src/shardmul.zig:503in nearest public ownertiny.simd.shardmullib.simd.src.shardmul.test_Highway_ShardMul_builder_remains_collision-free_for_clustered_keys[function] — test source atlib/simd/src/shardmul.zig:534in nearest public ownertiny.simd.shardmullib.simd.src.shardmul.test_Highway_ShardMul_plans_enforce_scratch_and_input_distributions[function] — test source atlib/simd/src/shardmul.zig:554in nearest public ownertiny.simd.shardmullib.simd.src.shardmul.test_Highway_ShardMul_scalar_and_vector_queries_agree[function] — test source atlib/simd/src/shardmul.zig:409in nearest public ownertiny.simd.shardmul
Audit
| Definitions | 11 |
|---|---|
| Public names | 22 |
| Members | 4 |
| Version | 26.7.0 |
| Revision | daab053ee433 |