feature. See also
. The project being documented here (as the example) is the Zig library itself.
blake3.hashVec
fn hashVec(
comptime Vec: type,
comptime n: comptime_int,
inputs: [n][*]const u8,
blocks: usize,
key: [8]u32,
counter: u64,
increment_counter: bool,
flags: Flags,
flags_start: Flags,
flags_end: Flags,
out: *[n * Blake3.digest_length]u8,
) void
File
Code
fn hashVec(
comptime Vec: type,
comptime n: comptime_int,
inputs: [n][*]const u8,
blocks: usize,
key: [8]u32,
counter: u64,
increment_counter: bool,
flags: Flags,
flags_start: Flags,
flags_end: Flags,
out: *[n * Blake3.digest_length]u8,
) void {
var h_vecs: [8]Vec = undefined;
for (0..8) |i| {
h_vecs[i] = @splat(key[i]);
}
const counter_low_vec = if (increment_counter) blk: {
var result: Vec = undefined;
inline for (0..n) |i| {
result[i] = counterLow(counter + i);
}
break :blk result;
} else @as(Vec, @splat(counterLow(counter)));
const counter_high_vec = if (increment_counter) blk: {
var result: Vec = undefined;
inline for (0..n) |i| {
result[i] = counterHigh(counter + i);
}
break :blk result;
} else @as(Vec, @splat(counterHigh(counter)));
var block_flags = flags.with(flags_start);
for (0..blocks) |block| {
if (block + 1 == blocks) {
block_flags = block_flags.with(flags_end);
}
const block_len_vec: Vec = @splat(Blake3.block_length);
const block_flags_vec: Vec = @splat(@as(u32, block_flags.toInt()));
var msg_vecs: [16]Vec = undefined;
transposeMsg(Vec, n, inputs, block * Blake3.block_length, &msg_vecs);
var v: [16]Vec = .{
h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3],
h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7],
@splat(iv[0]), @splat(iv[1]), @splat(iv[2]), @splat(iv[3]),
counter_low_vec, counter_high_vec, block_len_vec, block_flags_vec,
};
inline for (0..7) |r| {
roundFnVec(Vec, &v, &msg_vecs, r);
}
inline for (0..8) |i| {
h_vecs[i] = v[i] ^ v[i + 8];
}
block_flags = flags;
}
switch (n) {
4 => {
var out_vecs = [4]Vec{ h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3] };
transposeNxN(Vec, 4, &out_vecs);
inline for (0..4) |i| {
mem.writeInt(u32, out[0 * 16 + i * 4 ..][0..4], out_vecs[0][i], .little);
}
inline for (0..4) |i| {
mem.writeInt(u32, out[2 * 16 + i * 4 ..][0..4], out_vecs[1][i], .little);
}
inline for (0..4) |i| {
mem.writeInt(u32, out[4 * 16 + i * 4 ..][0..4], out_vecs[2][i], .little);
}
inline for (0..4) |i| {
mem.writeInt(u32, out[6 * 16 + i * 4 ..][0..4], out_vecs[3][i], .little);
}
out_vecs = [4]Vec{ h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7] };
transposeNxN(Vec, 4, &out_vecs);
inline for (0..4) |i| {
mem.writeInt(u32, out[1 * 16 + i * 4 ..][0..4], out_vecs[0][i], .little);
}
inline for (0..4) |i| {
mem.writeInt(u32, out[3 * 16 + i * 4 ..][0..4], out_vecs[1][i], .little);
}
inline for (0..4) |i| {
mem.writeInt(u32, out[5 * 16 + i * 4 ..][0..4], out_vecs[2][i], .little);
}
inline for (0..4) |i| {
mem.writeInt(u32, out[7 * 16 + i * 4 ..][0..4], out_vecs[3][i], .little);
}
},
8 => {
var out_vecs = [8]Vec{ h_vecs[0], h_vecs[1], h_vecs[2], h_vecs[3], h_vecs[4], h_vecs[5], h_vecs[6], h_vecs[7] };
transposeNxN(Vec, 8, &out_vecs);
inline for (0..8) |i| {
mem.writeInt(u32, out[0 * 32 + i * 4 ..][0..4], out_vecs[0][i], .little);
}
inline for (0..8) |i| {
mem.writeInt(u32, out[1 * 32 + i * 4 ..][0..4], out_vecs[1][i], .little);
}
inline for (0..8) |i| {
mem.writeInt(u32, out[2 * 32 + i * 4 ..][0..4], out_vecs[2][i], .little);
}
inline for (0..8) |i| {
mem.writeInt(u32, out[3 * 32 + i * 4 ..][0..4], out_vecs[3][i], .little);
}
inline for (0..8) |i| {
mem.writeInt(u32, out[4 * 32 + i * 4 ..][0..4], out_vecs[4][i], .little);
}
inline for (0..8) |i| {
mem.writeInt(u32, out[5 * 32 + i * 4 ..][0..4], out_vecs[5][i], .little);
}
inline for (0..8) |i| {
mem.writeInt(u32, out[6 * 32 + i * 4 ..][0..4], out_vecs[6][i], .little);
}
inline for (0..8) |i| {
mem.writeInt(u32, out[7 * 32 + i * 4 ..][0..4], out_vecs[7][i], .little);
}
},
16 => {
inline for (0..16) |lane| {
const hash_offset = lane * Blake3.digest_length;
inline for (0..8) |word_idx| {
const word = h_vecs[word_idx][lane];
out[hash_offset + word_idx * 4 + 0] = @truncate(word);
out[hash_offset + word_idx * 4 + 1] = @truncate(word >> 8);
out[hash_offset + word_idx * 4 + 2] = @truncate(word >> 16);
out[hash_offset + word_idx * 4 + 3] = @truncate(word >> 24);
}
}
},
else => @compileError("Unsupported SIMD width"),
}
}