Skip to content

Instantly share code, notes, and snippets.

@travisstaloch
Last active July 30, 2024 03:25
Show Gist options
  • Save travisstaloch/6ffee43044678d898b9c5bfa79c98e61 to your computer and use it in GitHub Desktop.
Save travisstaloch/6ffee43044678d898b9c5bfa79c98e61 to your computer and use it in GitHub Desktop.
A nice way to represent vectors in zig. Mixin methods allow all types to share code. extern structs mean they can bitcast to/from arrays and simd vectors.
//!
//! updated. now without usingnamespace. see previous revisions for a version with usingnamespace.
//!
pub fn VecMethods(comptime Self: type) type {
return struct {
const info = @typeInfo(Self);
pub const len = info.Struct.fields.len - 1;
pub const Arr = [len]info.Struct.fields[0].type;
pub const Simd = @Vector(len, info.Struct.fields[0].type);
pub fn arr(m: *const @This()) Arr {
const self: *const Self = @alignCast(@fieldParentPtr("m", m));
return @bitCast(self.*);
}
pub fn initArr(a: Arr) Self {
return @bitCast(a);
}
pub fn simd(m: *const @This()) Simd {
const self: *const Self = @alignCast(@fieldParentPtr("m", m));
return @bitCast(self.*);
}
pub fn initSimd(v: Simd) Self {
return @bitCast(v);
}
pub fn add(m: *const @This(), b: Self) Self {
const self: *const Self = @alignCast(@fieldParentPtr("m", m));
return initSimd(self.m.simd() + b.m.simd());
}
// TODO add more useful shared methods
};
}
pub fn Vec2(comptime T: type) type {
return extern struct {
x: T,
y: T,
m: M,
pub const M = VecMethods(@This());
};
}
pub fn Vec3(comptime T: type) type {
return extern struct {
x: T,
y: T,
z: T,
m: M,
pub const M = VecMethods(@This());
};
}
const std = @import("std");
test {
inline for ([_]type{ u8, u32, usize, f32, f64 }) |Child| {
{
const cx2 = Vec2(Child).M;
const x = cx2.initArr(.{ 1, 1 });
const y = cx2.initArr(.{ 1, 2 });
try std.testing.expectEqual(cx2.initArr(.{ 2, 3 }), x.m.add(y));
try std.testing.expectEqual(cx2.initArr(.{ 2, 3 }).m.arr(), x.m.add(y).m.arr());
}
{
const cx3 = Vec3(Child).M;
const x = cx3.initArr(.{ 1, 1, 1 });
const y = cx3.initArr(.{ 1, 2, 3 });
try std.testing.expectEqual(cx3.initArr(.{ 2, 3, 4 }), x.m.add(y));
try std.testing.expectEqual(cx3.initArr(.{ 2, 3, 4 }).m.arr(), x.m.add(y).m.arr());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment