import "std/simd.zc";
Zen C provides native SIMD (Single Instruction, Multiple Data) vector types that compile to GCC/Clang vector extensions.
Use the @vector(N) attribute on a single-field struct to define a vector of N elements:
@vector(4)
struct f32x4 {
v: f32;
}
This compiles to typedef float __attribute__((vector_size(4 * sizeof(float)))) f32x4; in C.
The standard library provides comprehensive 128-bit (SSE/NEON) and 256-bit (AVX/AVX2) vector types.
| Type | Element | Lanes | Bytes |
|---|---|---|---|
f32x4 |
f32 |
4 | 16 |
f64x2 |
f64 |
2 | 16 |
i32x4 |
i32 |
4 | 16 |
u32x4 |
u32 |
4 | 16 |
i64x2 |
i64 |
2 | 16 |
u64x2 |
u64 |
2 | 16 |
i16x8 |
i16 |
8 | 16 |
u16x8 |
u16 |
8 | 16 |
i8x16 |
i8 |
16 | 16 |
u8x16 |
u8 |
16 | 16 |
| Type | Element | Lanes | Bytes |
|---|---|---|---|
f32x8 |
f32 |
8 | 32 |
f64x4 |
f64 |
4 | 32 |
i32x8 |
i32 |
8 | 32 |
u32x8 |
u32 |
8 | 32 |
i64x4 |
i64 |
4 | 32 |
u64x4 |
u64 |
4 | 32 |
i16x16 |
i16 |
16 | 32 |
u16x16 |
u16 |
16 | 32 |
i8x32 |
i8 |
32 | 32 |
u8x32 |
u8 |
32 | 32 |
let a = f32x4{v: 1.0}; // {1.0, 1.0, 1.0, 1.0}
let b = i32x4{v: 42}; // {42, 42, 42, 42}
let a = f32x4{1.0, 2.0, 3.0, 4.0};
let b = i32x4{10, 20, 30, 40};
All operations work element-wise on every lane simultaneously.
let a = f32x4{1.0, 2.0, 3.0, 4.0};
let b = f32x4{v: 2.0};
let c = a + b; // {3.0, 4.0, 5.0, 6.0}
let d = a * b; // {2.0, 4.0, 6.0, 8.0}
let e = b - a; // {1.0, 0.0, -1.0, -2.0}
let f = b / a; // {2.0, 1.0, 0.667, 0.5}
let x = i32x4{v: 0xFF};
let y = i32x4{v: 0xF0};
let z = x & y; // {0xF0, 0xF0, 0xF0, 0xF0}
let w = x | y; // {0xFF, 0xFF, 0xFF, 0xFF}
let v = x ^ y; // {0x0F, 0x0F, 0x0F, 0x0F}
let c = a + b;
let first: f32 = c[0]; // Access individual lanes
let second: f32 = c[1];
You can define your own vector types for any element type and lane count:
@vector(2)
struct f64x2 {
v: f64;
}
@vector(32)
struct u8x32 {
v: u8;
}