std1.0.0-beta-7 SafeC docs

Source simd/simd.sc

View in the repository

// SafeC Standard Library — std::simd (portable core implementation)
#pragma once
#include <std/simd/simd.h>

namespace std {

// ── Load ───────────────────────────────────────────────────────────────────
// One unaligned vector load/store each: dereferencing a vec pointer into an
// element array only assumes the element's alignment.
f32x4 simd_load_f32x4(const &float p) {
    unsafe { return *(const f32x4*)p; }
}

f32x8 simd_load_f32x8(const &float p) {
    unsafe { return *(const f32x8*)p; }
}

f64x2 simd_load_f64x2(const &double p) {
    unsafe { return *(const f64x2*)p; }
}

f64x4 simd_load_f64x4(const &double p) {
    unsafe { return *(const f64x4*)p; }
}

i32x4 simd_load_i32x4(const &int p) {
    unsafe { return *(const i32x4*)p; }
}

i32x8 simd_load_i32x8(const &int p) {
    unsafe { return *(const i32x8*)p; }
}

u32x4 simd_load_u32x4(const &unsigned int p) {
    unsafe { return *(const u32x4*)p; }
}

u32x8 simd_load_u32x8(const &unsigned int p) {
    unsafe { return *(const u32x8*)p; }
}

i8x16 simd_load_i8x16(const &signed char p) {
    unsafe { return *(const i8x16*)p; }
}

u8x16 simd_load_u8x16(const &unsigned char p) {
    unsafe { return *(const u8x16*)p; }
}

// ── Store ──────────────────────────────────────────────────────────────────
void simd_store_f32x4(f32x4 v, &float p) {
    unsafe { *(f32x4*)p = v; }
}

void simd_store_f32x8(f32x8 v, &float p) {
    unsafe { *(f32x8*)p = v; }
}

void simd_store_f64x2(f64x2 v, &double p) {
    unsafe { *(f64x2*)p = v; }
}

void simd_store_f64x4(f64x4 v, &double p) {
    unsafe { *(f64x4*)p = v; }
}

void simd_store_i32x4(i32x4 v, &int p) {
    unsafe { *(i32x4*)p = v; }
}

void simd_store_i32x8(i32x8 v, &int p) {
    unsafe { *(i32x8*)p = v; }
}

void simd_store_u32x4(u32x4 v, &unsigned int p) {
    unsafe { *(u32x4*)p = v; }
}

void simd_store_u32x8(u32x8 v, &unsigned int p) {
    unsafe { *(u32x8*)p = v; }
}

void simd_store_i8x16(i8x16 v, &signed char p) {
    unsafe { *(i8x16*)p = v; }
}

void simd_store_u8x16(u8x16 v, &unsigned char p) {
    unsafe { *(u8x16*)p = v; }
}

// ── Broadcast (splat) ──────────────────────────────────────────────────────
f32x4 simd_splat_f32x4(float x) {
    f32x4 v;
    v[0] = x;
        v[1] = x;
        v[2] = x;
        v[3] = x;
    return v;
}

f32x8 simd_splat_f32x8(float x) {
    f32x8 v;
    v[0] = x;
        v[1] = x;
        v[2] = x;
        v[3] = x;
        v[4] = x;
        v[5] = x;
        v[6] = x;
        v[7] = x;
    return v;
}

f64x2 simd_splat_f64x2(double x) {
    f64x2 v;
    v[0] = x;
        v[1] = x;
    return v;
}

f64x4 simd_splat_f64x4(double x) {
    f64x4 v;
    v[0] = x;
        v[1] = x;
        v[2] = x;
        v[3] = x;
    return v;
}

i32x4 simd_splat_i32x4(int x) {
    i32x4 v;
    v[0] = x;
        v[1] = x;
        v[2] = x;
        v[3] = x;
    return v;
}

i32x8 simd_splat_i32x8(int x) {
    i32x8 v;
    v[0] = x;
        v[1] = x;
        v[2] = x;
        v[3] = x;
        v[4] = x;
        v[5] = x;
        v[6] = x;
        v[7] = x;
    return v;
}

u32x4 simd_splat_u32x4(unsigned int x) {
    u32x4 v;
    v[0] = x;
        v[1] = x;
        v[2] = x;
        v[3] = x;
    return v;
}

// ── Fused multiply-add: a*b + c ───────────────────────────────────────────
f32x4 simd_fma_f32x4(f32x4 a, f32x4 b, f32x4 c) {
    return __builtin_fmuladd(a, b, c);
}

f32x8 simd_fma_f32x8(f32x8 a, f32x8 b, f32x8 c) {
    return __builtin_fmuladd(a, b, c);
}

f64x2 simd_fma_f64x2(f64x2 a, f64x2 b, f64x2 c) {
    return __builtin_fmuladd(a, b, c);
}

f64x4 simd_fma_f64x4(f64x4 a, f64x4 b, f64x4 c) {
    return __builtin_fmuladd(a, b, c);
}

// ── Elementwise min/max (per-lane; LLVM's SLP vectorizer commonly
// re-fuses this unrolled form back into a single vector min/max
// instruction at -O2+, same as it does for the load/store loops above) ──
f32x4 simd_min_f32x4(f32x4 a, f32x4 b) {
    f32x4 r;
    r[0] = a[0] < b[0] ? a[0] : b[0];
    r[1] = a[1] < b[1] ? a[1] : b[1];
    r[2] = a[2] < b[2] ? a[2] : b[2];
    r[3] = a[3] < b[3] ? a[3] : b[3];
    return r;
}

f32x4 simd_max_f32x4(f32x4 a, f32x4 b) {
    f32x4 r;
    r[0] = a[0] > b[0] ? a[0] : b[0];
    r[1] = a[1] > b[1] ? a[1] : b[1];
    r[2] = a[2] > b[2] ? a[2] : b[2];
    r[3] = a[3] > b[3] ? a[3] : b[3];
    return r;
}

f32x8 simd_min_f32x8(f32x8 a, f32x8 b) {
    f32x8 r;
    r[0] = a[0] < b[0] ? a[0] : b[0];
    r[1] = a[1] < b[1] ? a[1] : b[1];
    r[2] = a[2] < b[2] ? a[2] : b[2];
    r[3] = a[3] < b[3] ? a[3] : b[3];
    r[4] = a[4] < b[4] ? a[4] : b[4];
    r[5] = a[5] < b[5] ? a[5] : b[5];
    r[6] = a[6] < b[6] ? a[6] : b[6];
    r[7] = a[7] < b[7] ? a[7] : b[7];
    return r;
}

f32x8 simd_max_f32x8(f32x8 a, f32x8 b) {
    f32x8 r;
    r[0] = a[0] > b[0] ? a[0] : b[0];
    r[1] = a[1] > b[1] ? a[1] : b[1];
    r[2] = a[2] > b[2] ? a[2] : b[2];
    r[3] = a[3] > b[3] ? a[3] : b[3];
    r[4] = a[4] > b[4] ? a[4] : b[4];
    r[5] = a[5] > b[5] ? a[5] : b[5];
    r[6] = a[6] > b[6] ? a[6] : b[6];
    r[7] = a[7] > b[7] ? a[7] : b[7];
    return r;
}

i32x4 simd_min_i32x4(i32x4 a, i32x4 b) {
    i32x4 r;
    r[0] = a[0] < b[0] ? a[0] : b[0];
    r[1] = a[1] < b[1] ? a[1] : b[1];
    r[2] = a[2] < b[2] ? a[2] : b[2];
    r[3] = a[3] < b[3] ? a[3] : b[3];
    return r;
}

i32x4 simd_max_i32x4(i32x4 a, i32x4 b) {
    i32x4 r;
    r[0] = a[0] > b[0] ? a[0] : b[0];
    r[1] = a[1] > b[1] ? a[1] : b[1];
    r[2] = a[2] > b[2] ? a[2] : b[2];
    r[3] = a[3] > b[3] ? a[3] : b[3];
    return r;
}

// ── Horizontal reductions ──────────────────────────────────────────────────
float simd_hsum_f32x4(f32x4 v) {
    return v[0] + v[1] + v[2] + v[3];
}

float simd_hmin_f32x4(f32x4 v) {
    float acc = v[0];
    if (v[1] < acc) { acc = v[1]; }
    if (v[2] < acc) { acc = v[2]; }
    if (v[3] < acc) { acc = v[3]; }
    return acc;
}

float simd_hmax_f32x4(f32x4 v) {
    float acc = v[0];
    if (v[1] > acc) { acc = v[1]; }
    if (v[2] > acc) { acc = v[2]; }
    if (v[3] > acc) { acc = v[3]; }
    return acc;
}

float simd_hsum_f32x8(f32x8 v) {
    return v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6] + v[7];
}

double simd_hsum_f64x2(f64x2 v) {
    return v[0] + v[1];
}

double simd_hsum_f64x4(f64x4 v) {
    return v[0] + v[1] + v[2] + v[3];
}

int simd_hsum_i32x4(i32x4 v) {
    return v[0] + v[1] + v[2] + v[3];
}

int simd_hsum_i32x8(i32x8 v) {
    return v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6] + v[7];
}

unsigned int simd_hsum_u32x4(u32x4 v) {
    return v[0] + v[1] + v[2] + v[3];
}

} // namespace std