Vector math
Fixed-size arrays support element-wise arithmetic:
float[3] can be used directly as a 3D vector.
Element-wise arithmetic
Both operands must have the same size; element types must match exactly (use explicit conversions and float literals for float arrays).
void main() {
float[3] a = [1.0, 2.0, 3.0];
float[3] b = [4.0, 5.0, 6.0];
float[3] c = a + b; // [5.0, 7.0, 9.0]
float[3] d = a * 2.0; // [2.0, 4.0, 6.0], scalar broadcasts
float[3] e = 10.0 - b; // [6.0, 5.0, 4.0], scalar on either side
println(c[0]); // prints 5
println(d[2]); // prints 6
println(e[0]); // prints 6
}Supported element-wise ops: + - * / % (and
%%), bitwise & | ^ << >> for
integer elements, and == != (which return
bool: == is true when all elements are equal,
!= when any differ). Unary - negates each
element. Unlike scalar arithmetic, integer element-wise ops wrap on
overflow instead of aborting.
void main() {
float[3] a = [1.0, 2.0, 3.0];
float[3] b = [1.0, 2.0, 3.0];
println(a == b); // prints true
println(a == [1.0, 2.0, 4.0]); // prints false
}Sizes must match; mismatched sizes are a compile error. Only arrays
of known (constant) size support element-wise ops; generic sizes
(T[N] with symbolic N) are rejected with a
clear error.
Vector codegen
Element-wise ops compile directly to SIMD vector instructions on the LLVM backend, in every build mode; larger arrays use a loop over vector chunks with a scalar tail. The C backend emits a scalar loop for the C compiler to vectorize.
Vector operations
Arrays of any size double as vectors: dot() returns the
dot product, length() the Euclidean length in the element
type, lengthSquared() the squared length, and
normalized() a unit-length copy (the receiver is left
unchanged). normalized() is only meaningful for
floating-point elements. The free function cross() returns
the cross product of two 3-element arrays.
void main() {
float[3] a = [1.0, 2.0, 3.0];
float[3] b = [4.0, 5.0, 6.0];
println(a.dot(b)); // prints 32
println(a.length()); // prints 3.7416575
float[3] n = a.normalized();
println(n[0]); // prints 0.26726124
float[3] c = cross(a, b);
println(c[0]); // prints -3
println(c[1]); // prints 6
println(c[2]); // prints -3
}Swizzles
Arrays of up to 4 numeric elements support GLSL-style swizzles: 1–4
characters from xyzw, rgba, or
stpq (one set per swizzle), mapping to indices 0–3
(x/r/s → 0,
y/g/t → 1,
z/b/p → 2,
w/a/q → 3). A single character
returns the element; multiple characters return a new array.
Out-of-bounds swizzles are compile errors.
Swizzles are writable: assigning to a single character writes the element, and assigning an array to multiple characters writes each element in order.
Swizzle write restrictions
Only direct assignment writes back (indexing or re-swizzling a multi-character swizzle is a compile error).
void main() {
float[3] v = [1.0, 2.0, 3.0];
v.x = 10.0;
println(v[0]); // prints 10
v.yz = [20.0, 30.0];
println(v[1]); // prints 20
println(v[2]); // prints 30
}void main() {
float[3] v = [1.0, 2.0, 3.0];
println(v.x); // prints 1, same as v[0]
println(v.z); // prints 3
float[2] xy = v.xy; // [1.0, 2.0]
float[3] zyx = v.zyx; // [3.0, 2.0, 1.0]
float[2] rg = v.rg; // [1.0, 2.0], rgba set works too
println(xy[0]); // prints 1
println(zyx[0]); // prints 3
println(rg[1]); // prints 2
float[4] w = [1.0, 2.0, 3.0, 4.0];
println(w.w); // prints 4
float[2] ra = w.ra; // [1.0, 4.0]
println(ra[1]); // prints 4
}See Arrays for array basics.