-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Builtin vector properties #4961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I would totally love to have vectors expose their elements as semantic fields, makes code a lot more readable. I think the idea with user-defined vector fields is the way to go here as a color does not expose Maybe const Generic = @Vector(3, u32);
const Vector3 = @Vector(.{ "x", "y", "z" }, f32); |
I agree that this could makes code slightly cleaner, even ignoring aesthetics. First, despite the name, SIMD vectors aren't extremely good at doing vector math when multiple channels are stored in a single vector. This effect is discussed more on Nathan Reed's Blog and in This talk by Andreas Fredriksson, but the short version is this:
The better approach is to use SIMD to accelerate cases where, within a single vector, all channels have the same meaning. So instead of storing
Here, channel access is still important to extract the data for an individual if you need to do specialized processing, but the channels no longer need names since they all have the same meaning. Because of this, I don't feel that storing channels with separate meanings in a single SIMD vector is an important use case for the language. Secondly, even when writing code that does have mixed-meaning, often the best path is to organize your vector code so that you never have to convert from vector->scalar->vector. This means that functions that convert vector->scalar (e.g. dot product) can usually be written better as a function that converts a vector to another vector with the scalar value across all four channels. Here's an example godbolt with dot product. I worry that making more ergonomic vector->scalar conversions will encourage more mixing of scalar and vector code, which is counter-productive if the goal of Finally, I think this feature would introduce some unnecessary complexity to the language. With this, instead of one unique vector type of 4 f32 values, a program could have a large number. Whether or not these should implicitly cast between each other is pretty analagous to the distinct types discussion (#1595), which is still quite controversial. The alternative, which I vastly prefer, is to wrap the vector in a struct that gives the correct operations. After all,
I think my opinions here come from this distinction: To me,
|
It's readonly. Also
|
Easily remedied:
I too can quote
But that's besides the point. |
|
You could alternatively do this:
Here's a godbolt showing that it generates the correct instructions. This allows you to do |
Here's another example showing that the compiler is smart enough to track the value through the |
Oh, I too can invent tricks :) const std = @import("std");
const warn = std.debug.warn;
const Vec2 = struct {
v: @Vector(2, f32),
pub fn @"x+="(self: *@This(), delta: f32) void {
self.v[0] += delta;
}
pub fn @"y+="(self: *@This(), delta: f32) void {
self.v[1] += delta;
}
};
pub fn main() !void {
var v: Vec2 = undefined;
v.@"x+="(1.0);
v.@"y+="(1.0);
warn("v = {}\n", .{v});
} |
Now people are just being silly. As @SpexGuy explained, a |
"Geniuses" should learn to add "IMHO" to each phrase. |
What is going on here? Please let us keep the conversion technical and remember that we are all working towards the same goal. |
With typedef, #5132: // fields split by `,` must have length equal to the base array length
// base type must be an array or vector of a primitive type
const Color = typedefprimitive([4]u8, .NamedArray{.fields="r,g,b,a"});
const Pos3d = typedefprimitive([@Vector(3,f64), .NamedArray{.fields="x,y,z"});
test "" {
const color : Color = @as(Color,.{0,1,2,3});
assert(color[0] == color.r); // syntax sugar applied at comptime
assert(color[1] == color.g);
assert(color[2] == color.b);
assert(color[3] == color.a);
const arr : [4]u8 = @as([4]u8, color); // equivalent at runtime
} This would rely on typedef primitives ( (Normal typedefs ( With respect to coercion, I think named arrays should behave like typedef distincts. The named array auto coerces down to the base type, but going from the base to the named array requires a cast with const arr : [4]u8 = color; // ok. auto coerce
const color2 : Color = arr; // compile error |
Or even user-defined:
The text was updated successfully, but these errors were encountered: