slain-num 0.3.0

SLAIN's own numeric crate: dense matrices, least squares, polynomials, FFT, convolution, statistics and 1-D/N-D minimisation, with AVX2 kernels.
Documentation
#[cfg(target_arch = "x86_64")]
#[inline]
fn fast() -> bool {
    slain_rt::cpu::avx2()
}

#[must_use]
pub fn dot(a: &[f64], b: &[f64]) -> f64 {
    let n = a.len().min(b.len());
    #[cfg(target_arch = "x86_64")]
    if fast() {
        return unsafe { x86::dot(&a[..n], &b[..n]) };
    }
    a[..n].iter().zip(&b[..n]).map(|(x, y)| x * y).sum()
}

#[must_use]
pub fn sum(a: &[f64]) -> f64 {
    #[cfg(target_arch = "x86_64")]
    if fast() {
        return unsafe { x86::sum(a) };
    }
    a.iter().sum()
}

#[must_use]
pub fn sq_diff_u16(a: &[u16], b: &[u16]) -> u64 {
    let n = a.len().min(b.len());
    #[cfg(target_arch = "x86_64")]
    if fast() {
        return unsafe { x86::sq_diff_u16(&a[..n], &b[..n]) };
    }
    a[..n].iter().zip(&b[..n]).map(|(&x, &y)| (i64::from(x) - i64::from(y)).pow(2) as u64).sum()
}

#[cfg(target_arch = "x86_64")]
mod x86 {
    use core::arch::x86_64::*;

    #[inline(always)]
    unsafe fn hsum(v: __m256d) -> f64 {
        let s = _mm_add_pd(_mm256_castpd256_pd128(v), _mm256_extractf128_pd::<1>(v));
        _mm_cvtsd_f64(_mm_add_sd(s, _mm_unpackhi_pd(s, s)))
    }

    #[target_feature(enable = "avx2,fma")]
    pub(super) unsafe fn dot(a: &[f64], b: &[f64]) -> f64 {
        let n = a.len();
        let (mut s0, mut s1) = (_mm256_setzero_pd(), _mm256_setzero_pd());
        let mut i = 0;
        while i + 8 <= n {
            s0 = _mm256_fmadd_pd(_mm256_loadu_pd(a.as_ptr().add(i)), _mm256_loadu_pd(b.as_ptr().add(i)), s0);
            s1 = _mm256_fmadd_pd(_mm256_loadu_pd(a.as_ptr().add(i + 4)), _mm256_loadu_pd(b.as_ptr().add(i + 4)), s1);
            i += 8;
        }
        if i + 4 <= n {
            s0 = _mm256_fmadd_pd(_mm256_loadu_pd(a.as_ptr().add(i)), _mm256_loadu_pd(b.as_ptr().add(i)), s0);
            i += 4;
        }
        let mut s = hsum(_mm256_add_pd(s0, s1));
        while i < n {
            s += a[i] * b[i];
            i += 1;
        }
        s
    }

    #[target_feature(enable = "avx2")]
    pub(super) unsafe fn sum(a: &[f64]) -> f64 {
        let n = a.len();
        let mut s = _mm256_setzero_pd();
        let mut i = 0;
        while i + 4 <= n {
            s = _mm256_add_pd(s, _mm256_loadu_pd(a.as_ptr().add(i)));
            i += 4;
        }
        let mut t = hsum(s);
        while i < n {
            t += a[i];
            i += 1;
        }
        t
    }

    #[target_feature(enable = "avx2")]
    pub(super) unsafe fn sq_diff_u16(a: &[u16], b: &[u16]) -> u64 {
        let n = a.len();
        let zero = _mm256_setzero_si256();
        let mut acc = zero;
        let mut i = 0;
        while i + 16 <= n {
            let pa = _mm256_loadu_si256(a.as_ptr().add(i).cast());
            let pb = _mm256_loadu_si256(b.as_ptr().add(i).cast());
            let lo = _mm256_sub_epi32(_mm256_unpacklo_epi16(pa, zero), _mm256_unpacklo_epi16(pb, zero));
            let hi = _mm256_sub_epi32(_mm256_unpackhi_epi16(pa, zero), _mm256_unpackhi_epi16(pb, zero));
            let odd = |v: __m256i| _mm256_srli_epi64::<32>(v);
            acc = _mm256_add_epi64(acc, _mm256_add_epi64(_mm256_mul_epi32(lo, lo), _mm256_mul_epi32(odd(lo), odd(lo))));
            acc = _mm256_add_epi64(acc, _mm256_add_epi64(_mm256_mul_epi32(hi, hi), _mm256_mul_epi32(odd(hi), odd(hi))));
            i += 16;
        }
        let mut lanes = [0u64; 4];
        _mm256_storeu_si256(lanes.as_mut_ptr().cast(), acc);
        let mut total: u64 = lanes.iter().sum();
        while i < n {
            total += (i64::from(a[i]) - i64::from(b[i])).pow(2) as u64;
            i += 1;
        }
        total
    }
}