vector math experiments
This commit is contained in:
97
vecs.zig
Normal file
97
vecs.zig
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user