# Vectors

> SIMD with ordinary operators.

```zig
const std = @import("std");
const expect = std.testing.expect;

test "element-wise arithmetic" {
    const a: @Vector(4, i32) = .{ 1, 2, 3, 4 };
    const b: @Vector(4, i32) = .{ 10, 20, 30, 40 };
    const sum = a + b; // one operation across all lanes
    try expect(sum[0] == 11);
    try expect(sum[3] == 44);
}

test "reduce across lanes" {
    const v: @Vector(4, i32) = .{ 1, 2, 3, 4 };
    try expect(@reduce(.Add, v) == 10);
    try expect(@reduce(.Max, v) == 4);
}

test "splat fills every lane" {
    const v: @Vector(4, i32) = @splat(7);
    try expect(@reduce(.Add, v) == 28);
}

test "comparisons produce a vector of bools" {
    const a: @Vector(4, i32) = .{ 1, 5, 3, 7 };
    const b: @Vector(4, i32) = .{ 4, 4, 4, 4 };
    const mask = a > b; // @Vector(4, bool)
    try expect(@reduce(.Or, mask));
    try expect(!@reduce(.And, mask));

    // Select lane-wise between two vectors.
    const picked = @select(i32, mask, a, b);
    try expect(picked[0] == 4 and picked[1] == 5);
}

test "vectors and arrays convert" {
    const arr = [_]i32{ 1, 2, 3, 4 };
    const v: @Vector(4, i32) = arr;
    const back: [4]i32 = v;
    try expect(back[2] == 3);
}
```

*Runnable: compiled to WebAssembly and executed by CI against Zig master. (`02-language.vectors`)*

`@Vector(N, T)` is a SIMD vector of `N` lanes. Arithmetic operators work
element-wise across all lanes at once, compiling to real vector instructions
where the target has them:

```zig
const sum = a + b;   // one operation, four lanes
```

## The supporting builtins

| Builtin | Does |
| --- | --- |
| `@splat(x)` | fill every lane with `x` |
| `@reduce(.Add, v)` | collapse lanes to one value |
| `@select(T, mask, a, b)` | pick lane-wise between two vectors |
| `@shuffle` | rearrange lanes |

Comparisons produce a `@Vector(N, bool)` mask rather than a single `bool`, which
is why `@reduce(.Or, mask)` or `@select` is how you act on the result.

## Vectors and arrays interconvert

```zig
const v: @Vector(4, i32) = arr;   // array -> vector
const back: [4]i32 = v;           // vector -> array
```

Same data, different type. Keep values in vector form through a computation and
convert at the edges.

## When to bother

Zig will often auto-vectorise a plain loop. Explicit vectors are for when you
need the guarantee, or when the operation does not map onto a simple loop. If
the target lacks SIMD, the code still works. The compiler lowers it to scalar
operations.

Two how-to recipes put these builtins to work:
[a SIMD dot product](https://www.ziglang.in/learn/how-to/simd-sum/) for arithmetic and
[SIMD byte scanning](https://www.ziglang.in/learn/how-to/simd-scan/) for searching.
