#[cfg(feature = "simd")]
use crate::error::{LinalgError, LinalgResult};
#[cfg(feature = "simd")]
use scirs2_core::ndarray::{Array2, ArrayView2};
#[cfg(feature = "simd")]
use scirs2_core::simd_ops::SimdUnifiedOps;
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_transpose_f32(matrix: &ArrayView2<f32>) -> LinalgResult<Array2<f32>> {
Ok(f32::simd_transpose_blocked(matrix))
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_transpose_blocked_f32(matrix: &ArrayView2<f32>) -> LinalgResult<Array2<f32>> {
Ok(f32::simd_transpose_blocked(matrix))
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_transpose_f64(matrix: &ArrayView2<f64>) -> LinalgResult<Array2<f64>> {
Ok(f64::simd_transpose_blocked(matrix))
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_transpose_blocked_f64(matrix: &ArrayView2<f64>) -> LinalgResult<Array2<f64>> {
Ok(f64::simd_transpose_blocked(matrix))
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_transpose_inplace_f32(matrix: &mut Array2<f32>) -> LinalgResult<()> {
let (rows, cols) = matrix.dim();
if rows != cols {
return Err(LinalgError::ShapeError(format!(
"In-place transpose requires square matrix, got shape ({rows}, {cols})"
)));
}
let n = rows;
for i in 0..n {
for j in (i + 1)..n {
let temp = matrix[[i, j]];
matrix[[i, j]] = matrix[[j, i]];
matrix[[j, i]] = temp;
}
}
Ok(())
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_transpose_inplace_f64(matrix: &mut Array2<f64>) -> LinalgResult<()> {
let (rows, cols) = matrix.dim();
if rows != cols {
return Err(LinalgError::ShapeError(format!(
"In-place transpose requires square matrix, got shape ({rows}, {cols})"
)));
}
let n = rows;
for i in 0..n {
for j in (i + 1)..n {
let temp = matrix[[i, j]];
matrix[[i, j]] = matrix[[j, i]];
matrix[[j, i]] = temp;
}
}
Ok(())
}
#[cfg(all(test, feature = "simd"))]
mod tests {
use super::*;
use approx::assert_relative_eq;
use scirs2_core::ndarray::array;
#[test]
#[cfg(feature = "simd")]
fn test_simd_transpose_f32() {
let matrix = array![
[1.0f32, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, 10.0, 11.0, 12.0]
];
let result = simd_transpose_f32(&matrix.view()).expect("Operation failed");
let expected = array![
[1.0f32, 5.0, 9.0],
[2.0, 6.0, 10.0],
[3.0, 7.0, 11.0],
[4.0, 8.0, 12.0]
];
assert_eq!(result.shape(), expected.shape());
for ((i, j), &val) in result.indexed_iter() {
assert_relative_eq!(val, expected[[i, j]], epsilon = 1e-6);
}
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_transpose_f64() {
let matrix = array![[1.0f64, 2.0, 3.0], [4.0, 5.0, 6.0]];
let result = simd_transpose_f64(&matrix.view()).expect("Operation failed");
let expected = array![[1.0f64, 4.0], [2.0, 5.0], [3.0, 6.0]];
assert_eq!(result.shape(), expected.shape());
for ((i, j), &val) in result.indexed_iter() {
assert_relative_eq!(val, expected[[i, j]], epsilon = 1e-12);
}
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_transpose_inplace_f32() {
let mut matrix = array![[1.0f32, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]];
simd_transpose_inplace_f32(&mut matrix).expect("Operation failed");
let expected = array![[1.0f32, 4.0, 7.0], [2.0, 5.0, 8.0], [3.0, 6.0, 9.0]];
assert_eq!(matrix.shape(), expected.shape());
for ((i, j), &val) in matrix.indexed_iter() {
assert_relative_eq!(val, expected[[i, j]], epsilon = 1e-6);
}
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_transpose_largematrix() {
let size = 100;
let mut matrix = Array2::zeros((size, size));
for i in 0..size {
for j in 0..size {
matrix[[i, j]] = (i * size + j) as f32;
}
}
let result = simd_transpose_f32(&matrix.view()).expect("Operation failed");
for i in 0..size {
for j in 0..size {
assert_relative_eq!(result[[j, i]], matrix[[i, j]], epsilon = 1e-6);
}
}
}
}