ggblas 0.1.2

Matrix multiplicatiosn in simple pure rust multithreadded blas-like interface. Exploits intrinsics on available targets.
Documentation
use super::f16::CpuF16;
use core::arch::wasm32::*;
use half::f16;

const STEP: usize = 16;
const EPR: usize = 4;
const ARR: usize = STEP / EPR;

pub struct CurrentCpuF16 {}

impl CpuF16<ARR> for CurrentCpuF16 {
    type Unit = v128;
    type Array = [v128; ARR];

    const STEP: usize = STEP;
    const EPR: usize = EPR;

    fn n() -> usize {
        ARR
    }

    unsafe fn zero() -> Self::Unit {
        f32x4_splat(0.0f32)
    }

    unsafe fn zero_array() -> Self::Array {
        [Self::zero(); ARR]
    }

    unsafe fn from_f32(v: f32) -> Self::Unit {
        f32x4_splat(v)
    }

    unsafe fn load(mem_addr: *const f16) -> Self::Unit {
        let mut tmp = [0.0f32; 4];
        for i in 0..4 {
            tmp[i] = (*mem_addr.add(i)).to_f32();
        }
        v128_load(tmp.as_ptr() as *const v128)
    }

    unsafe fn vec_fma(a: Self::Unit, b: Self::Unit, c: Self::Unit) -> Self::Unit {
        f32x4_add(f32x4_mul(b, c), a)
    }

    unsafe fn vec_store(mem_addr: *mut f16, a: Self::Unit) {
        let mut tmp = [0.0f32; 4];
        v128_store(tmp.as_mut_ptr() as *mut v128, a);
        for i in 0..4 {
            *mem_addr.add(i) = f16::from_f32(tmp[i]);
        }
    }

    unsafe fn vec_reduce(mut x: Self::Array, y: *mut f32) {
        let mut offset = ARR >> 1;
        for i in 0..offset {
            x[i] = f32x4_add(x[i], x[offset + i]);
        }
        offset >>= 1;
        for i in 0..offset {
            x[i] = f32x4_add(x[i], x[offset + i]);
        }
        offset >>= 1;
        for i in 0..offset {
            x[i] = f32x4_add(x[i], x[offset + i]);
        }
        *y = f32x4_extract_lane::<0>(x[0])
            + f32x4_extract_lane::<1>(x[0])
            + f32x4_extract_lane::<2>(x[0])
            + f32x4_extract_lane::<3>(x[0]);
    }
}