conspire 0.7.2

The Rust interface to conspire.
Documentation
use crate::math::Scalar;
use std::arch::x86_64::{
    _mm256_fmadd_pd, _mm256_fnmadd_pd, _mm256_loadu_pd, _mm256_set1_pd, _mm256_storeu_pd,
};

#[target_feature(enable = "avx2", enable = "fma")]
pub(super) unsafe fn axpy(target: &mut [Scalar], column: &[Scalar], w: Scalar) {
    let len = target.len();
    let spread = _mm256_set1_pd(w);
    let mut r = 0;
    unsafe {
        while r + 4 <= len {
            let entry = target.as_mut_ptr().add(r);
            _mm256_storeu_pd(
                entry,
                _mm256_fnmadd_pd(
                    _mm256_loadu_pd(column.as_ptr().add(r)),
                    spread,
                    _mm256_loadu_pd(entry),
                ),
            );
            r += 4;
        }
    }
    (r..len).for_each(|i| target[i] -= column[i] * w);
}

#[target_feature(enable = "avx2", enable = "fma")]
pub(super) unsafe fn rank_one_quad(
    temp_0: &mut [Scalar],
    temp_1: &mut [Scalar],
    temp_2: &mut [Scalar],
    temp_3: &mut [Scalar],
    column: &[Scalar],
    u: [Scalar; 4],
) {
    let len = column.len();
    let u_0 = _mm256_set1_pd(u[0]);
    let u_1 = _mm256_set1_pd(u[1]);
    let u_2 = _mm256_set1_pd(u[2]);
    let u_3 = _mm256_set1_pd(u[3]);
    let mut r = 0;
    unsafe {
        while r + 4 <= len {
            let value = _mm256_loadu_pd(column.as_ptr().add(r));
            _mm256_storeu_pd(
                temp_0.as_mut_ptr().add(r),
                _mm256_fmadd_pd(value, u_0, _mm256_loadu_pd(temp_0.as_ptr().add(r))),
            );
            _mm256_storeu_pd(
                temp_1.as_mut_ptr().add(r),
                _mm256_fmadd_pd(value, u_1, _mm256_loadu_pd(temp_1.as_ptr().add(r))),
            );
            _mm256_storeu_pd(
                temp_2.as_mut_ptr().add(r),
                _mm256_fmadd_pd(value, u_2, _mm256_loadu_pd(temp_2.as_ptr().add(r))),
            );
            _mm256_storeu_pd(
                temp_3.as_mut_ptr().add(r),
                _mm256_fmadd_pd(value, u_3, _mm256_loadu_pd(temp_3.as_ptr().add(r))),
            );
            r += 4;
        }
    }
    (r..len).for_each(|i| {
        temp_0[i] += column[i] * u[0];
        temp_1[i] += column[i] * u[1];
        temp_2[i] += column[i] * u[2];
        temp_3[i] += column[i] * u[3];
    });
}

#[allow(clippy::too_many_arguments)]
#[target_feature(enable = "avx2", enable = "fma")]
pub(super) unsafe fn rank_two_quad(
    temp_0: &mut [Scalar],
    temp_1: &mut [Scalar],
    temp_2: &mut [Scalar],
    temp_3: &mut [Scalar],
    column: &[Scalar],
    other: &[Scalar],
    u: [Scalar; 4],
    w: [Scalar; 4],
) {
    let len = column.len();
    let u_0 = _mm256_set1_pd(u[0]);
    let u_1 = _mm256_set1_pd(u[1]);
    let u_2 = _mm256_set1_pd(u[2]);
    let u_3 = _mm256_set1_pd(u[3]);
    let w_0 = _mm256_set1_pd(w[0]);
    let w_1 = _mm256_set1_pd(w[1]);
    let w_2 = _mm256_set1_pd(w[2]);
    let w_3 = _mm256_set1_pd(w[3]);
    let mut r = 0;
    unsafe {
        while r + 4 <= len {
            let value = _mm256_loadu_pd(column.as_ptr().add(r));
            let second = _mm256_loadu_pd(other.as_ptr().add(r));
            _mm256_storeu_pd(
                temp_0.as_mut_ptr().add(r),
                _mm256_fmadd_pd(
                    second,
                    w_0,
                    _mm256_fmadd_pd(value, u_0, _mm256_loadu_pd(temp_0.as_ptr().add(r))),
                ),
            );
            _mm256_storeu_pd(
                temp_1.as_mut_ptr().add(r),
                _mm256_fmadd_pd(
                    second,
                    w_1,
                    _mm256_fmadd_pd(value, u_1, _mm256_loadu_pd(temp_1.as_ptr().add(r))),
                ),
            );
            _mm256_storeu_pd(
                temp_2.as_mut_ptr().add(r),
                _mm256_fmadd_pd(
                    second,
                    w_2,
                    _mm256_fmadd_pd(value, u_2, _mm256_loadu_pd(temp_2.as_ptr().add(r))),
                ),
            );
            _mm256_storeu_pd(
                temp_3.as_mut_ptr().add(r),
                _mm256_fmadd_pd(
                    second,
                    w_3,
                    _mm256_fmadd_pd(value, u_3, _mm256_loadu_pd(temp_3.as_ptr().add(r))),
                ),
            );
            r += 4;
        }
    }
    (r..len).for_each(|i| {
        temp_0[i] += column[i] * u[0] + other[i] * w[0];
        temp_1[i] += column[i] * u[1] + other[i] * w[1];
        temp_2[i] += column[i] * u[2] + other[i] * w[2];
        temp_3[i] += column[i] * u[3] + other[i] * w[3];
    });
}