#[cfg(feature = "simd")]
use scirs2_core::ndarray::{ArrayView1, ArrayView2};
#[cfg(feature = "simd")]
use scirs2_core::simd_ops::SimdUnifiedOps;
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_frobenius_norm_f32(matrix: &ArrayView2<f32>) -> f32 {
let mut sum_sq = 0.0f32;
for row in matrix.rows() {
sum_sq += f32::simd_dot(&row, &row);
}
sum_sq.sqrt()
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_frobenius_norm_f64(matrix: &ArrayView2<f64>) -> f64 {
let mut sum_sq = 0.0f64;
for row in matrix.rows() {
sum_sq += f64::simd_dot(&row, &row);
}
sum_sq.sqrt()
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_vector_norm_f32(vector: &ArrayView1<f32>) -> f32 {
f32::simd_norm(vector)
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_vector_norm_f64(vector: &ArrayView1<f64>) -> f64 {
f64::simd_norm(vector)
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_vector_norm1_f32(vector: &ArrayView1<f32>) -> f32 {
let abs_vec = f32::simd_abs(vector);
f32::simd_sum(&abs_vec.view())
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_vector_norm1_f64(vector: &ArrayView1<f64>) -> f64 {
let abs_vec = f64::simd_abs(vector);
f64::simd_sum(&abs_vec.view())
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_vector_norm_inf_f32(vector: &ArrayView1<f32>) -> f32 {
let abs_vec = f32::simd_abs(vector);
f32::simd_max_element(&abs_vec.view())
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simd_vector_norm_inf_f64(vector: &ArrayView1<f64>) -> f64 {
let abs_vec = f64::simd_abs(vector);
f64::simd_max_element(&abs_vec.view())
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simdmatrix_norm1_f32(matrix: &ArrayView2<f32>) -> f32 {
let mut max_col_sum = 0.0f32;
for j in 0..matrix.ncols() {
let col = matrix.column(j);
let col_sum = simd_vector_norm1_f32(&col);
max_col_sum = max_col_sum.max(col_sum);
}
max_col_sum
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simdmatrix_norm1_f64(matrix: &ArrayView2<f64>) -> f64 {
let mut max_col_sum = 0.0f64;
for j in 0..matrix.ncols() {
let col = matrix.column(j);
let col_sum = simd_vector_norm1_f64(&col);
max_col_sum = max_col_sum.max(col_sum);
}
max_col_sum
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simdmatrix_norm_inf_f32(matrix: &ArrayView2<f32>) -> f32 {
let mut max_row_sum = 0.0f32;
for i in 0..matrix.nrows() {
let row = matrix.row(i);
let row_sum = simd_vector_norm1_f32(&row);
max_row_sum = max_row_sum.max(row_sum);
}
max_row_sum
}
#[cfg(feature = "simd")]
#[allow(dead_code)]
pub fn simdmatrix_norm_inf_f64(matrix: &ArrayView2<f64>) -> f64 {
let mut max_row_sum = 0.0f64;
for i in 0..matrix.nrows() {
let row = matrix.row(i);
let row_sum = simd_vector_norm1_f64(&row);
max_row_sum = max_row_sum.max(row_sum);
}
max_row_sum
}
#[cfg(all(test, feature = "simd"))]
mod tests {
use super::*;
use approx::assert_relative_eq;
use scirs2_core::ndarray::{array, Array1};
#[test]
#[cfg(feature = "simd")]
fn test_simd_frobenius_norm_f32() {
let matrix = array![[3.0f32, 4.0, 0.0], [0.0, 0.0, 12.0], [5.0, 0.0, 0.0]];
let result = simd_frobenius_norm_f32(&matrix.view());
let expected = (9.0 + 16.0 + 144.0 + 25.0f32).sqrt();
assert_relative_eq!(result, expected, epsilon = 1e-6);
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_vector_norm_f32() {
let vector = array![3.0f32, 4.0, 0.0, 12.0, 5.0];
let result = simd_vector_norm_f32(&vector.view());
let expected = (9.0 + 16.0 + 0.0 + 144.0 + 25.0f32).sqrt();
assert_relative_eq!(result, expected, epsilon = 1e-6);
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_vector_norm1_f32() {
let vector = array![3.0f32, -4.0, 0.0, 12.0, -5.0];
let result = simd_vector_norm1_f32(&vector.view());
let expected = 24.0f32;
assert_relative_eq!(result, expected, epsilon = 1e-6);
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_vector_norm_inf_f32() {
let vector = array![3.0f32, -4.0, 0.0, 12.0, -5.0];
let result = simd_vector_norm_inf_f32(&vector.view());
let expected = 12.0f32;
assert_relative_eq!(result, expected, epsilon = 1e-6);
}
#[test]
#[cfg(feature = "simd")]
fn test_simdmatrix_norm1_f32() {
let matrix = array![[1.0f32, -2.0, 3.0], [-4.0, 5.0, -6.0], [7.0, -8.0, 9.0]];
let result = simdmatrix_norm1_f32(&matrix.view());
let expected = 18.0f32;
assert_relative_eq!(result, expected, epsilon = 1e-6);
}
#[test]
#[cfg(feature = "simd")]
fn test_simdmatrix_norm_inf_f32() {
let matrix = array![[1.0f32, -2.0, 3.0], [-4.0, 5.0, -6.0], [7.0, -8.0, 9.0]];
let result = simdmatrix_norm_inf_f32(&matrix.view());
let expected = 24.0f32;
assert_relative_eq!(result, expected, epsilon = 1e-6);
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_frobenius_norm_f64() {
let matrix = array![[3.0f64, 4.0], [0.0, 12.0]];
let result = simd_frobenius_norm_f64(&matrix.view());
let expected = 13.0f64;
assert_relative_eq!(result, expected, epsilon = 1e-12);
}
#[test]
#[cfg(feature = "simd")]
fn test_simd_large_vector() {
let size = 100;
let vector: Array1<f32> = Array1::from_shape_fn(size, |i| (i as f32) * 0.1);
let result = simd_vector_norm_f32(&vector.view());
let expected = vector.iter().map(|&x| x * x).sum::<f32>().sqrt();
assert_relative_eq!(result, expected, epsilon = 1e-6);
}
}