use core::arch::aarch64::*;
use core::mem::MaybeUninit;
use core::ptr;
pub(super) const ROWS: usize = 32;
macro_rules! leaf {
($name:ident, $t:ty, $n:literal, $ld:ident, $st:ident, $dup:ident, $fmsn:ident, $mul:ident) => {
#[inline(never)]
pub(super) unsafe fn $name<const V: usize, const K: usize>(
a: *mut $t,
n: usize,
ld: usize,
len: usize,
) -> bool {
unsafe {
let mut l = [[MaybeUninit::uninit(); V]; K];
for (j, col) in l.iter_mut().enumerate().take(n) {
let src = a.add(j * ld);
if j * ld + K <= len {
for (v, x) in col.iter_mut().enumerate() {
*x = MaybeUninit::new($ld(src.add($n * v)));
}
} else {
let mut t = [0.0 as $t; K];
ptr::copy_nonoverlapping(src, t.as_mut_ptr(), n);
for (v, x) in col.iter_mut().enumerate() {
*x = MaybeUninit::new($ld(t.as_ptr().add($n * v)));
}
}
}
let l = &mut *(&mut l[..n] as *mut [[MaybeUninit<_>; V]] as *mut [[_; V]]);
let sections = if V % 4 == 0 {
4
} else if V % 2 == 0 {
2
} else {
1
};
for j in 0..n {
let mut y = l[j];
let diagonal = l.as_mut_ptr().cast::<$t>().add(j * K + j);
let mut d = *diagonal;
macro_rules! update {
($from:expr) => {
for p in 0..j {
let s = *l.as_ptr().cast::<$t>().add(p * K + j);
d = (-s).mul_add(s, d);
for v in $from..V {
y[v] = $fmsn(y[v], l[p][v], s);
}
}
};
}
match j * sections / K {
0 => update!(0),
1 => update!(V / sections),
2 => update!(2 * V / sections),
_ => update!(3 * V / sections),
}
if d.is_nan() || d <= 0.0 {
return false;
}
let d = d.sqrt();
let r = $dup(1.0 / d);
for y in &mut y {
*y = $mul(*y, r);
}
l[j] = y;
*diagonal = d;
}
let whole = n / $n;
for (j, col) in l.iter().enumerate() {
let dst = a.add(j * ld);
for (v, x) in col.iter().enumerate() {
let mut x = *x;
if $n * v + $n <= j {
x = $dup(0.0);
} else if $n * v < j {
let mut t = [0.0 as $t; $n];
$st(t.as_mut_ptr(), x);
t[..j - $n * v].fill(0.0);
x = $ld(t.as_ptr());
}
if v < whole {
$st(dst.add($n * v), x);
} else if v == whole && n > $n * whole {
let mut t = [0.0 as $t; $n];
$st(t.as_mut_ptr(), x);
for (i, t) in t.iter().enumerate().take(n - $n * whole) {
*dst.add($n * whole + i) = *t;
}
}
}
}
true
}
}
};
}
leaf!(
leaf_f64,
f64,
2,
vld1q_f64,
vst1q_f64,
vdupq_n_f64,
vfmsq_n_f64,
vmulq_f64
);
leaf!(
leaf_f32,
f32,
4,
vld1q_f32,
vst1q_f32,
vdupq_n_f32,
vfmsq_n_f32,
vmulq_f32
);