vector math experiments

This commit is contained in:
David Allemang
2024-03-27 17:40:39 -04:00
parent 2f70c43c00
commit d4196644df
2 changed files with 126 additions and 0 deletions

97
vecs.zig Normal file
View File

@@ -0,0 +1,97 @@
const std = @import("std");
const mat4f = mat(4, 4, f32);
const vec4f = mat(4, 1, f32);
const mat4i = mat(4, 4, i32);
const vec4i = mat(4, 1, i32);
const mat4u = mat(4, 4, u32);
const vec4u = mat(4, 1, u32);
pub fn mat(comptime R_: usize, comptime C_: usize, comptime T_: type) type {
return struct {
pub const Rows = R_;
pub const Cols = C_;
pub const T = T_;
data: [Cols][Rows]T,
pub fn mul(l: @This(), r: anytype) MatMulReturnType(@This(), @TypeOf(r)) {
return matmul(l, r);
}
};
}
fn MatMulReturnType(comptime L: type, comptime R: type) type {
if (L.Cols != R.Rows) @compileError("invalid dimensions");
const x: L.T = std.mem.zeroes(L.T);
const y: R.T = std.mem.zeroes(R.T);
const T = @TypeOf(x + y);
return mat(L.Rows, R.Cols, T);
}
pub fn matmul(lhs: anytype, rhs: anytype) MatMulReturnType(@TypeOf(lhs), @TypeOf(rhs)) {
@setFloatMode(.optimized);
const L = @TypeOf(lhs);
const R = @TypeOf(rhs);
const Ret = MatMulReturnType(L, R);
var res = std.mem.zeroes(Ret);
if (L.Cols != R.Rows) @compileError("invalid dimensions");
inline for (0..R.Cols) |col| {
inline for (0..L.Rows) |row| {
inline for (0..L.Cols) |k| {
res.data[col][row] += lhs.data[k][row] * rhs.data[col][k];
}
}
}
return res;
}
export fn c_matmul_f_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void {
const l: *const mat4f = @alignCast(@ptrCast(lhs));
const r: *const vec4f = @alignCast(@ptrCast(rhs));
const o: *vec4f = @alignCast(@ptrCast(out));
o.* = matmul(l.*, r.*);
}
export fn c_matmul_i_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void {
const l: *const mat4i = @alignCast(@ptrCast(lhs));
const r: *const vec4i = @alignCast(@ptrCast(rhs));
const o: *vec4i = @alignCast(@ptrCast(out));
o.* = matmul(l.*, r.*);
}
export fn c_matmul_u_4x4_1x4(lhs: *const anyopaque, rhs: *const anyopaque, out: *anyopaque) void {
const l: *const mat4u = @alignCast(@ptrCast(lhs));
const r: *const vec4u = @alignCast(@ptrCast(rhs));
const o: *vec4u = @alignCast(@ptrCast(out));
o.* = matmul(l.*, r.*);
}
test "matmul" {
// note, column major; it's transposed.
const m: mat4u = .{ .data = .{
.{ 85, 84, 87, 37 },
.{ 33, 54, 49, 83 },
.{ 96, 97, 3, 13 },
.{ 69, 12, 45, 77 },
} };
const u: vec4u = .{ .data = .{.{ 37, 69, 94, 87 }} };
const actual: vec4u = matmul(m, u);
const expect: vec4u = .{ .data = .{.{ 20449, 16996, 10797, 15017 }} };
try std.testing.expectEqualDeep(expect, actual);
}