Skip to main content

SIMD Vectors

Zynx provides a built-in vector<T, N> type for SIMD (Single Instruction, Multiple Data) operations. This type is intended for data-parallel workloads and maps directly to hardware vector registers using the backend C compiler's vector extensions (for example, __attribute__((vector_size)) in GCC and Clang).

Use SIMD vectors when you need predictable, low-level control over packed numeric data and are comfortable with the target platform's vector semantics.

Declaration

A vector is declared with an element type T and a constant size N:

let v: vector<i32, 4>;

The size N must be a positive compile-time constant. The element type T must be a numeric type that the backend can map to a hardware SIMD lane.

Initialization and Assignment

Vectors can be initialized from standard Zynx arrays of the same size. This allows for straightforward data loading from regular aggregates:

let data: i32[4] = [1, 2, 3, 4];
let v: vector<i32, 4> = data;

You can also use array-like literals directly when initializing a vector, as long as the literal length matches the vector size:

let v2: vector<i32, 2> = [10, 20];

Operations

Vectors support a subset of arithmetic and bitwise operators. These operations are performed element-wise by the hardware and lowered to the platform's SIMD instruction set.

let a: vector<i32, 4> = [1, 1, 1, 1];
let b: vector<i32, 4> = [2, 2, 2, 2];

let c = a + b; // [3, 3, 3, 3]
let d = c * 2; // [6, 6, 6, 6]
let e = d >> 1; // [3, 3, 3, 3]

Supported Operators

  • Arithmetic: +, -, *, /, %
  • Bitwise: &, |, ^, <<, >>, ~
  • Compound assignment: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=

Notes:

  • Operations are applied lane-wise across all elements.
  • Vector operations do not use Zynx's default checked arithmetic (overflow checks); they follow the native SIMD behavior of the target, typically wrapping on overflow.

Element Access

You can access individual elements of a vector using standard subscript syntax:

let v: vector<i32, 4> = [10, 20, 30, 40];
let first = v[0]; // 10
// let x = v[4]; // Panics: index out of bounds

Safety

  • Zynx performs runtime bounds checking on vector subscripts.
  • Accessing an index >= N triggers a panic, preserving memory safety.

Safety and Hardening

  • Type validation: The compiler ensures that vector<T, N> is only instantiated with supported numeric element types (T) and positive integer constants (N).
  • Initialization safety:
    • Assigning from a fixed-size array or literal requires the same length; mismatches are diagnosed at compile time.
    • Assigning from a dynamic array (for example, v = my_array) performs a runtime size check in non-release builds to ensure the array length exactly matches the vector size.
  • Arithmetic: Vector arithmetic is performed using native SIMD instructions. Overflow checks are disabled for vectors to follow standard hardware semantics.
  • Literals: Vectors can be initialized directly with array-like literals:
    let v: vector<i32, 2> = [1, 2];
    The compiler validates the literal size at compile time.