use std::sync::Arc;
pub(crate) trait Transposition<T> {
fn transpose(&self, src: &[T], dst: &mut [T]);
}
pub(crate) trait TransposeFactory: Sized {
fn make_transpose(width: usize, height: usize) -> Arc<dyn Transposition<Self> + Send + Sync>;
}
pub(crate) struct TransposeTiny {
pub(crate) width: usize,
pub(crate) height: usize,
}
impl<T: Copy> Transposition<T> for TransposeTiny {
fn transpose(&self, src: &[T], dst: &mut [T]) {
for x in 0..self.width {
for y in 0..self.height {
let input_index = x + y * self.width;
let output_index = y + x * self.height;
unsafe {
*dst.get_unchecked_mut(output_index) = *src.get_unchecked(input_index);
}
}
}
}
}
impl TransposeFactory for f32 {
fn make_transpose(width: usize, height: usize) -> Arc<dyn Transposition<Self> + Send + Sync> {
#[cfg(all(target_arch = "aarch64", feature = "neon"))]
{
if height.is_multiple_of(11) {
use crate::neon::NeonTransposeNx11F32;
return Arc::new(NeonTransposeNx11F32 { width, height });
}
if height.is_multiple_of(7) {
use crate::neon::NeonTransposeNx7F32;
return Arc::new(NeonTransposeNx7F32 { width, height });
}
if height.is_multiple_of(6) {
use crate::neon::NeonTransposeNx6F32;
return Arc::new(NeonTransposeNx6F32 { width, height });
}
if height.is_multiple_of(5) {
use crate::neon::NeonTransposeNx5F32;
return Arc::new(NeonTransposeNx5F32 { width, height });
}
use crate::neon::NeonTranspose4x4;
Arc::new(NeonTranspose4x4 { width, height })
}
#[cfg(all(target_arch = "x86_64", feature = "avx"))]
{
use crate::util::has_valid_avx;
if has_valid_avx() {
use crate::avx::AvxTransposeFReal4x4;
return Arc::new(AvxTransposeFReal4x4 { width, height });
}
}
#[cfg(not(all(target_arch = "aarch64", feature = "neon")))]
{
Arc::new(TransposeTiny { width, height })
}
}
}
impl TransposeFactory for f64 {
fn make_transpose(width: usize, height: usize) -> Arc<dyn Transposition<Self> + Send + Sync> {
Arc::new(TransposeTiny { width, height })
}
}