use crate::hptt::micro_kernel::{MicroKernel, ScalarKernel};
#[inline]
pub unsafe fn macro_kernel_f64(
src: *const f64,
lda: isize,
block_a: usize,
dst: *mut f64,
ldb: isize,
block_b: usize,
) {
const MICRO: usize = <ScalarKernel as MicroKernel<f64>>::MICRO;
let full_a = block_a / MICRO;
let rem_a = block_a % MICRO;
let full_b = block_b / MICRO;
let rem_b = block_b % MICRO;
for jb in 0..full_b {
let j = (jb * MICRO) as isize;
for ia in 0..full_a {
let i = (ia * MICRO) as isize;
ScalarKernel::transpose_micro(
src.offset(i + j * lda),
lda,
dst.offset(j + i * ldb),
ldb,
);
}
if rem_a > 0 {
let i = (full_a * MICRO) as isize;
for jj in 0..MICRO as isize {
for ii in 0..rem_a as isize {
*dst.offset((j + jj) + (i + ii) * ldb) = *src.offset((i + ii) + (j + jj) * lda);
}
}
}
}
if rem_b > 0 {
let j = (full_b * MICRO) as isize;
for ia in 0..full_a {
let i = (ia * MICRO) as isize;
for jj in 0..rem_b as isize {
for ii in 0..MICRO as isize {
*dst.offset((j + jj) + (i + ii) * ldb) = *src.offset((i + ii) + (j + jj) * lda);
}
}
}
if rem_a > 0 {
let i = (full_a * MICRO) as isize;
for jj in 0..rem_b as isize {
for ii in 0..rem_a as isize {
*dst.offset((j + jj) + (i + ii) * ldb) = *src.offset((i + ii) + (j + jj) * lda);
}
}
}
}
}
#[inline]
pub unsafe fn macro_kernel_f32(
src: *const f32,
lda: isize,
block_a: usize,
dst: *mut f32,
ldb: isize,
block_b: usize,
) {
const MICRO: usize = <ScalarKernel as MicroKernel<f32>>::MICRO;
let full_a = block_a / MICRO;
let rem_a = block_a % MICRO;
let full_b = block_b / MICRO;
let rem_b = block_b % MICRO;
for jb in 0..full_b {
let j = (jb * MICRO) as isize;
for ia in 0..full_a {
let i = (ia * MICRO) as isize;
ScalarKernel::transpose_micro(
src.offset(i + j * lda),
lda,
dst.offset(j + i * ldb),
ldb,
);
}
if rem_a > 0 {
let i = (full_a * MICRO) as isize;
for jj in 0..MICRO as isize {
for ii in 0..rem_a as isize {
*dst.offset((j + jj) + (i + ii) * ldb) = *src.offset((i + ii) + (j + jj) * lda);
}
}
}
}
if rem_b > 0 {
let j = (full_b * MICRO) as isize;
for ia in 0..full_a {
let i = (ia * MICRO) as isize;
for jj in 0..rem_b as isize {
for ii in 0..MICRO as isize {
*dst.offset((j + jj) + (i + ii) * ldb) = *src.offset((i + ii) + (j + jj) * lda);
}
}
}
if rem_a > 0 {
let i = (full_a * MICRO) as isize;
for jj in 0..rem_b as isize {
for ii in 0..rem_a as isize {
*dst.offset((j + jj) + (i + ii) * ldb) = *src.offset((i + ii) + (j + jj) * lda);
}
}
}
}
}
#[inline(always)]
pub unsafe fn const_stride1_copy<T: Copy>(
src: *const T,
dst: *mut T,
count: usize,
src_stride: isize,
dst_stride: isize,
) {
if src_stride == 1 && dst_stride == 1 {
std::ptr::copy_nonoverlapping(src, dst, count);
} else if dst_stride == 1 {
let mut s = src;
let mut d = dst;
for _ in 0..count {
*d = *s;
s = s.wrapping_offset(src_stride);
d = d.wrapping_offset(1);
}
} else if src_stride == 1 {
let mut s = src;
let mut d = dst;
for _ in 0..count {
*d = *s;
s = s.wrapping_offset(1);
d = d.wrapping_offset(dst_stride);
}
} else {
let mut s = src;
let mut d = dst;
for _ in 0..count {
*d = *s;
s = s.wrapping_offset(src_stride);
d = d.wrapping_offset(dst_stride);
}
}
}
#[inline]
pub unsafe fn macro_kernel_fallback<T: Copy>(
src: *const T,
lda: isize,
block_a: usize,
dst: *mut T,
ldb: isize,
block_b: usize,
) {
for j in 0..block_b as isize {
for i in 0..block_a as isize {
*dst.offset(j + i * ldb) = *src.offset(i + j * lda);
}
}
}
#[cfg(test)]
mod tests;