use super::{MicroKernel, ScalarKernel};
impl MicroKernel<f64> for ScalarKernel {
const MICRO: usize = 4;
const BLOCK: usize = 16;
#[inline(always)]
unsafe fn transpose_micro(src: *const f64, lda: isize, dst: *mut f64, ldb: isize) {
for j in 0..4_isize {
for i in 0..4_isize {
*dst.offset(i + j * ldb) = *src.offset(i * lda + j);
}
}
}
}
impl MicroKernel<f32> for ScalarKernel {
const MICRO: usize = 8;
const BLOCK: usize = 32;
#[inline(always)]
unsafe fn transpose_micro(src: *const f32, lda: isize, dst: *mut f32, ldb: isize) {
for j in 0..8_isize {
for i in 0..8_isize {
*dst.offset(i + j * ldb) = *src.offset(i * lda + j);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scalar_f64_4x4() {
let src: Vec<f64> = (0..16).map(|i| i as f64).collect();
let mut dst = vec![0.0f64; 16];
unsafe {
ScalarKernel::transpose_micro(src.as_ptr(), 4, dst.as_mut_ptr(), 4);
}
for j in 0..4 {
for i in 0..4 {
assert_eq!(dst[i + j * 4], src[i * 4 + j], "mismatch at i={i}, j={j}");
}
}
}
#[test]
fn test_scalar_f64_non_square_strides() {
let mut src = vec![0.0f64; 20];
for i in 0..4 {
for j in 0..4 {
src[i * 5 + j] = (i * 10 + j) as f64;
}
}
let mut dst = vec![0.0f64; 24];
unsafe {
ScalarKernel::transpose_micro(src.as_ptr(), 5, dst.as_mut_ptr(), 6);
}
for j in 0..4 {
for i in 0..4 {
assert_eq!(dst[i + j * 6], src[i * 5 + j], "mismatch at i={i}, j={j}");
}
}
}
#[test]
fn test_scalar_f32_8x8() {
let src: Vec<f32> = (0..64).map(|i| i as f32).collect();
let mut dst = vec![0.0f32; 64];
unsafe {
ScalarKernel::transpose_micro(src.as_ptr(), 8, dst.as_mut_ptr(), 8);
}
for j in 0..8 {
for i in 0..8 {
assert_eq!(dst[i + j * 8], src[i * 8 + j], "mismatch at i={i}, j={j}");
}
}
}
}