Last active
July 30, 2024 03:25
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! | |
//! 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