Skip to content

Instantly share code, notes, and snippets.

@Validark
Created October 15, 2024 21:46
Show Gist options
  • Save Validark/540fd2ca78f3ce4aa54830fb3cc925bb to your computer and use it in GitHub Desktop.
Save Validark/540fd2ca78f3ce4aa54830fb3cc925bb to your computer and use it in GitHub Desktop.
clmul interlace two bitstrings
const std = @import("std");
const builtin = @import("builtin");
const assert = std.debug.assert;
const has_native_carryless_multiply = switch (builtin.cpu.arch) {
.x86_64 => std.Target.x86.featureSetHas(builtin.cpu.features, .pclmul),
.aarch64 => std.Target.aarch64.featureSetHas(builtin.cpu.features, .aes),
.riscv64 => std.Target.riscv.featureSetHas(builtin.cpu.features, .zbc),
//.sparc64 => std.Target.sparc.featureSetHas(builtin.cpu.features, .vis3),
else => false,
};
fn carryless_square(x: u64) u64 {
return switch (builtin.cpu.arch) {
.x86_64 => carryless_multiply_x86(x, x),
.aarch64 => carryless_multiply_aarch64(x, x),
.riscv64 => carryless_multiply_riscv64(x, x),
else => unreachable,
};
}
export fn interlace_via_clmul(a: u64, b: u64) u64 {
return ((carryless_square(a) << 1) +% carryless_square(b));
}
fn carryless_multiply_x86(a: u64, b: u64) u64 {
return struct {
extern fn @"llvm.x86.pclmulqdq"(@Vector(2, u64), @Vector(2, u64), i8) @Vector(2, u64);
}.@"llvm.x86.pclmulqdq"(.{ a, 0 }, .{ b, 0 }, 0)[0];
}
fn carryless_multiply_aarch64(a: u64, b: u64) u64 {
return @as([2]u64, @bitCast(struct {
extern fn @"llvm.aarch64.neon.pmull64"(u64, u64) @Vector(16, u8);
}.@"llvm.aarch64.neon.pmull64"(a, b)))[0];
}
fn carryless_multiply_riscv64(a: u64, b: u64) u64 {
return struct {
extern fn @"llvm.riscv.clmul"(u64, u64) u64;
}.@"llvm.riscv.clmul"(a, b);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment