Construction & Operators

magetypes provides natural Rust syntax for SIMD operations.

Construction

From Array

#![allow(unused)]
fn main() {
let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let v = f32x8::from_array(token, data);
}

From Slice

#![allow(unused)]
fn main() {
let slice = &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
let v = f32x8::from_slice(token, slice);
}

Splat (Broadcast)

#![allow(unused)]
fn main() {
let v = f32x8::splat(token, 3.14159);  // All lanes = π
}

Zero

#![allow(unused)]
fn main() {
let v = f32x8::zero(token);  // All lanes = 0
}

Load from Memory

#![allow(unused)]
fn main() {
// Unaligned load
let v = f32x8::load(token, ptr);

// From reference
let v = f32x8::from_array(token, *array_ref);
}

Extraction

To Array

#![allow(unused)]
fn main() {
let arr: [f32; 8] = v.to_array();
}

Store to Memory

#![allow(unused)]
fn main() {
v.store(ptr);          // Unaligned store
v.store_aligned(ptr);  // Aligned store (UB if misaligned)
}

Extract Single Lane

#![allow(unused)]
fn main() {
let first = v.extract::<0>();
let third = v.extract::<2>();
}

Arithmetic Operators

All standard operators work:

#![allow(unused)]
fn main() {
let a = f32x8::splat(token, 2.0);
let b = f32x8::splat(token, 3.0);

let sum = a + b;        // [5.0; 8]
let diff = a - b;       // [-1.0; 8]
let prod = a * b;       // [6.0; 8]
let quot = a / b;       // [0.666...; 8]
let neg = -a;           // [-2.0; 8]
}

Compound Assignment

#![allow(unused)]
fn main() {
let mut v = f32x8::splat(token, 1.0);
v += f32x8::splat(token, 2.0);  // v = [3.0; 8]
v *= f32x8::splat(token, 2.0);  // v = [6.0; 8]
}

Fused Multiply-Add

FMA is faster and more precise than separate multiply and add:

#![allow(unused)]
fn main() {
// a * b + c (single instruction on AVX2/NEON)
let result = a.mul_add(b, c);

// a * b - c
let result = a.mul_sub(b, c);

// -(a * b) + c  (negated multiply-add)
let result = a.neg_mul_add(b, c);
}

Comparisons

Comparisons return mask types:

#![allow(unused)]
fn main() {
let a = f32x8::from_array(token, [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);
let b = f32x8::splat(token, 4.0);

let lt = a.simd_lt(b);   // [true, true, true, false, false, false, false, false]
let eq = a.simd_eq(b);   // [false, false, false, true, false, false, false, false]
let ge = a.simd_ge(b);   // [false, false, false, true, true, true, true, true]
}

Blend with Mask

#![allow(unused)]
fn main() {
let mask = a.simd_lt(b);
let result = mask.blend(true_values, false_values);
}

Min/Max

#![allow(unused)]
fn main() {
let min = a.min(b);  // Element-wise minimum
let max = a.max(b);  // Element-wise maximum

// With scalar
let clamped = v.max(f32x8::splat(token, 0.0))
               .min(f32x8::splat(token, 1.0));
}

Absolute Value

#![allow(unused)]
fn main() {
let abs = v.abs();  // |v| for each lane
}

Reductions

Horizontal operations across lanes:

#![allow(unused)]
fn main() {
let sum = v.reduce_add();      // Sum of all lanes
let max = v.reduce_max();      // Maximum lane
let min = v.reduce_min();      // Minimum lane
}

Integer Operations

For integer types (i32x8, u8x16, etc.):

#![allow(unused)]
fn main() {
let a = i32x8::splat(token, 10);
let b = i32x8::splat(token, 3);

// Arithmetic
let sum = a + b;
let diff = a - b;
let prod = a * b;

// Bitwise
let and = a & b;
let or = a | b;
let xor = a ^ b;
let not = !a;

// Shifts
let shl = a << 2;           // Shift left by constant
let shr = a >> 1;           // Shift right by constant
let shr_arith = a.shr_arithmetic(1);  // Sign-extending shift
}

Example: Dot Product

#![allow(unused)]
fn main() {
use archmage::{Desktop64, SimdToken, arcane};
use magetypes::simd::f32x8;

#[arcane]
fn dot_product(token: Desktop64, a: &[f32; 8], b: &[f32; 8]) -> f32 {
    let va = f32x8::from_array(token, *a);
    let vb = f32x8::from_array(token, *b);
    (va * vb).reduce_add()
}
}

Example: Vector Normalization

#![allow(unused)]
fn main() {
#[arcane]
fn normalize(token: Desktop64, v: &mut [f32; 8]) {
    let vec = f32x8::from_array(token, *v);
    let len_sq = (vec * vec).reduce_add();
    let len = len_sq.sqrt();

    if len > 0.0 {
        let inv_len = f32x8::splat(token, 1.0 / len);
        let normalized = vec * inv_len;
        *v = normalized.to_array();
    }
}
}