Vectors
Zig provides vector types for SIMD. These are not to be conflated with vectors
in a mathematical sense, or vectors like C++'s std::vector (for this, see
"Arraylist" in chapter 2). Vectors may be created using the
@Type
built-in we used
earlier, and
std.meta.Vector
provides a shorthand for this.
Vectors can only have child types of booleans, integers, floats and pointers.
Operations between vectors with the same child type and length can take place.
These operations are performed on each of the values in the
vector.std.meta.eql
is used here to check for equality between two vectors (also useful for other
types like structs).
const meta = @import("std").meta;
test "vector add" {
const x: @Vector(4, f32) = .{ 1, -10, 20, -1 };
const y: @Vector(4, f32) = .{ 2, 10, 0, 1 };
const z = x + y;
try expect(meta.eql(z, @Vector(4, f32){ 3, 0, 20, 0 }));
}
Vectors are indexable.
test "vector indexing" {
const x: @Vector(4, u8) = .{ 255, 0, 255, 0 };
try expect(x[0] == 255);
}
The built-in function
@splat
may be used to
construct a vector where all of the values are the same. Here we use it to
multiply a vector by a scalar.
test "vector * scalar" {
const x: @Vector(3, f32) = .{ 12.5, 37.5, 2.5 };
const y = x * @as(@Vector(3, f32), @splat(2));
try expect(meta.eql(y, @Vector(3, f32){ 25, 75, 5 }));
}
Vectors do not have a len
field like arrays, but may still be looped over.
test "vector looping" {
const x = @Vector(4, u8){ 255, 0, 255, 0 };
var sum = blk: {
var tmp: u10 = 0;
var i: u8 = 0;
while (i < 4) : (i += 1) tmp += x[i];
break :blk tmp;
};
try expect(sum == 510);
}
Vectors coerce to their respective arrays.
const arr: [4]f32 = @Vector(4, f32){ 1, 2, 3, 4 };
It is worth noting that using explicit vectors may result in slower software if you do not make the right decisions - the compiler's auto-vectorisation is fairly smart as-is.