# Project Context
**Language**: rust
**Project Path**: .
## Project Structure
- **Total Files**: 28
- **Total Functions**: 90
- **Median Cyclomatic**: 2.00
- **Median Cognitive**: 1.00
## Quality Scorecard
- **Overall Health**: 81.7%
- **Maintainability Index**: 70.0
- **Complexity Score**: 90.0
- **Test Coverage**: 65.0%
## Files
### ./benches/gpu_ops.rs
**File Complexity**: 3 | **Functions**: 14
- **Function**: `generate_test_data` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_vec_add` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_dot` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_matmul` [complexity: 6] [cognitive: 13] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_relu` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_leaky_relu` [complexity: 4] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_elu` [complexity: 4] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_clip` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_sigmoid` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_tanh` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_swish` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_gelu` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_softmax` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
- **Function**: `bench_gpu_log_softmax` [complexity: 3] [cognitive: 4] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(9)] [tdg: 2.5]
### ./benches/matrix_ops.rs
**File Complexity**: 2 | **Functions**: 6
- **Function**: `bench_matmul_sizes` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_matmul_rectangular` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_transpose` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_matvec` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_convolve2d` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `bench_convolve2d_edge_detection` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
### ./benches/vector_ops.rs
**File Complexity**: 1 | **Functions**: 25
- **Function**: `generate_test_data` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_add` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_sub` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_mul` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_scale` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_div` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_fma` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_dot` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_sum` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_max` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_min` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_argmax` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_argmin` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_relu` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_softmax` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_log_softmax` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_clip` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_sigmoid` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_gelu` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_swish` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_tanh` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_norm_l1` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_norm_l2` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_norm_linf` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
- **Function**: `bench_abs` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: high(21)] [tdg: 2.5]
### ./book/book.toml
### ./deny.toml
### ./docs/roadmaps/roadmap.yaml
### ./examples/activation_functions.rs
**File Complexity**: 1 | **Functions**: 2
- **Function**: `main` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `print_activation_row` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
### ./examples/backend_detection.rs
**File Complexity**: 1 | **Functions**: 1
- **Function**: `main` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
### ./examples/matrix_operations.rs
**File Complexity**: 3 | **Functions**: 3
- **Function**: `main` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `print_matrix` [complexity: 4] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `print_vector` [complexity: 3] [cognitive: 3] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
### ./examples/ml_similarity.rs
**File Complexity**: 1 | **Functions**: 4
- **Function**: `main` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `cosine_similarity` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `l2_normalize` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `euclidean_distance` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
### ./examples/performance_demo.rs
**File Complexity**: 5 | **Functions**: 3
- **Function**: `main` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `demo_operation` [complexity: 7] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `demo_operation_vec` [complexity: 7] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
### ./scripts/check_regression.py
**File Complexity**: 48 | **Functions**: 5
- **Function**: `parse_time` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `parse_criterion_output` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `format_time` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `compare_benchmarks` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `main` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
### ./src/backends/avx2.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `Avx2Backend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for Avx2Backend { # [target_feature (enable = "avx2")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_add_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "avx2")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_sub_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "avx2")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_mul_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "avx2")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm256_div_ps (va , vb) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "avx2" , enable = "fma")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm256_setzero_ps () ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; acc = _mm256_fmadd_ps (va , vb , acc) ; i += 8 ; } let mut result = { let sum_halves = _mm_add_ps (_mm256_castps256_ps128 (acc) , _mm256_extractf128_ps (acc , 1)) ; let temp = _mm_add_ps (sum_halves , _mm_movehl_ps (sum_halves , sum_halves)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "avx2")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm256_setzero_ps () ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; acc = _mm256_add_ps (acc , va) ; i += 8 ; } let mut result = { let sum_halves = _mm_add_ps (_mm256_castps256_ps128 (acc) , _mm256_extractf128_ps (acc , 1)) ; let temp = _mm_add_ps (sum_halves , _mm_movehl_ps (sum_halves , sum_halves)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "avx2")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = _mm256_set1_ps (a [0]) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; vmax = _mm256_max_ps (vmax , va) ; i += 8 ; } let mut result = { let max_halves = _mm_max_ps (_mm256_castps256_ps128 (vmax) , _mm256_extractf128_ps (vmax , 1)) ; let temp = _mm_max_ps (max_halves , _mm_movehl_ps (max_halves , max_halves)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "avx2")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = _mm256_set1_ps (a [0]) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; vmin = _mm256_min_ps (vmin , va) ; i += 8 ; } let mut result = { let min_halves = _mm_min_ps (_mm256_castps256_ps128 (vmin) , _mm256_extractf128_ps (vmin , 1)) ; let temp = _mm_min_ps (min_halves , _mm_movehl_ps (min_halves , min_halves)) ; let temp = _mm_min_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "avx2")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut max_value = a [0] ; let mut max_index = 0 ; let mut vmax = _mm256_set1_ps (a [0]) ; let mut vmax_idx = _mm256_set1_ps (0.0) ; let mut vidx_current = _mm256_set_ps (7.0 , 6.0 , 5.0 , 4.0 , 3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm256_set1_ps (8.0) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm256_cmp_ps :: < 30 > (va , vmax) ; vmax = _mm256_blendv_ps (vmax , va , mask) ; vmax_idx = _mm256_blendv_ps (vmax_idx , vidx_current , mask) ; vidx_current = _mm256_add_ps (vidx_current , vinc) ; i += 8 ; } let mut values = [0.0f32 ; 8] ; let mut indices = [0.0f32 ; 8] ; _mm256_storeu_ps (values . as_mut_ptr () , vmax) ; _mm256_storeu_ps (indices . as_mut_ptr () , vmax_idx) ; for lane in 0 .. 8 { if values [lane] > max_value { max_value = values [lane] ; max_index = indices [lane] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "avx2")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut min_value = a [0] ; let mut min_index = 0 ; let mut vmin = _mm256_set1_ps (a [0]) ; let mut vmin_idx = _mm256_set1_ps (0.0) ; let mut vidx_current = _mm256_set_ps (7.0 , 6.0 , 5.0 , 4.0 , 3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm256_set1_ps (8.0) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm256_cmp_ps :: < 17 > (va , vmin) ; vmin = _mm256_blendv_ps (vmin , va , mask) ; vmin_idx = _mm256_blendv_ps (vmin_idx , vidx_current , mask) ; vidx_current = _mm256_add_ps (vidx_current , vinc) ; i += 8 ; } let mut values = [0.0f32 ; 8] ; let mut indices = [0.0f32 ; 8] ; _mm256_storeu_ps (values . as_mut_ptr () , vmin) ; _mm256_storeu_ps (indices . as_mut_ptr () , vmin_idx) ; for lane in 0 .. 8 { if values [lane] < min_value { min_value = values [lane] ; min_index = indices [lane] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "avx2")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [target_feature (enable = "avx2")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = _mm256_setzero_ps () ; let sign_mask = _mm256_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm256_and_ps (va , sign_mask) ; acc = _mm256_add_ps (acc , abs_va) ; i += 8 ; } let mut result = { let sum_halves = _mm_add_ps (_mm256_castps256_ps128 (acc) , _mm256_extractf128_ps (acc , 1)) ; let temp = _mm_add_ps (sum_halves , _mm_movehl_ps (sum_halves , sum_halves)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { result += val . abs () ; } result } # [target_feature (enable = "avx2")] unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut max_vec = _mm256_setzero_ps () ; let sign_mask = _mm256_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm256_and_ps (va , sign_mask) ; max_vec = _mm256_max_ps (max_vec , abs_va) ; i += 8 ; } let mut result = { let max_halves = _mm_max_ps (_mm256_castps256_ps128 (max_vec) , _mm256_extractf128_ps (max_vec , 1) ,) ; let temp = _mm_max_ps (max_halves , _mm_movehl_ps (max_halves , max_halves)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { let abs_val = val . abs () ; if abs_val > result { result = abs_val ; } } result } # [target_feature (enable = "avx2")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = _mm256_set1_ps (scalar) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm256_mul_ps (va , scalar_vec) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sign_mask = _mm256_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm256_and_ps (va , sign_mask) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , abs_va) ; i += 8 ; } while i < len { result [i] = a [i] . abs () ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = _mm256_set1_ps (min_val) ; let max_vec = _mm256_set1_ps (max_val) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let clamped = _mm256_min_ps (_mm256_max_ps (va , min_vec) , max_vec) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , clamped) ; i += 8 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [target_feature (enable = "avx2" , enable = "fma")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = _mm256_set1_ps (t) ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let diff = _mm256_sub_ps (vb , va) ; let vresult = _mm256_fmadd_ps (t_vec , diff , va) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [target_feature (enable = "avx2" , enable = "fma")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm256_loadu_ps (b . as_ptr () . add (i)) ; let vc = _mm256_loadu_ps (c . as_ptr () . add (i)) ; let vresult = _mm256_fmadd_ps (va , vb , vc) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = _mm256_setzero_ps () ; while i + 8 <= len { let va = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm256_max_ps (zero , va) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let x = _mm256_max_ps (_mm256_min_ps (x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let vresult = _mm256_mul_ps (p , scale) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 8 ; } while i < len { result [i] = a [i] . exp () ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm256_sub_ps (_mm256_setzero_ps () , x) ; let neg_x = _mm256_max_ps (_mm256_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (neg_x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (neg_x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_neg_x = _mm256_mul_ps (p , scale) ; let denom = _mm256_add_ps (one , exp_neg_x) ; let sigmoid_result = _mm256_div_ps (one , denom) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , sigmoid_result) ; i += 8 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = _mm256_set1_ps (0.797_884_6) ; let coeff = _mm256_set1_ps (0.044715) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let two = _mm256_set1_ps (2.0) ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let x2 = _mm256_mul_ps (x , x) ; let x3 = _mm256_mul_ps (x2 , x) ; let inner_sum = _mm256_fmadd_ps (coeff , x3 , x) ; let inner = _mm256_mul_ps (sqrt_2_over_pi , inner_sum) ; let two_inner = _mm256_mul_ps (two , inner) ; let two_inner = _mm256_max_ps (_mm256_min_ps (two_inner , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (two_inner , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (two_inner , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_2inner = _mm256_mul_ps (p , scale) ; let tanh_numer = _mm256_sub_ps (exp_2inner , one) ; let tanh_denom = _mm256_add_ps (exp_2inner , one) ; let tanh_result = _mm256_div_ps (tanh_numer , tanh_denom) ; let one_plus_tanh = _mm256_add_ps (one , tanh_result) ; let gelu_result = _mm256_mul_ps (half , _mm256_mul_ps (x , one_plus_tanh)) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , gelu_result) ; i += 8 ; } const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm256_sub_ps (_mm256_setzero_ps () , x) ; let neg_x = _mm256_max_ps (_mm256_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (neg_x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (neg_x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_neg_x = _mm256_mul_ps (p , scale) ; let denom = _mm256_add_ps (one , exp_neg_x) ; let swish_result = _mm256_div_ps (x , denom) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , swish_result) ; i += 8 ; } while i < len { let x = a [i] ; result [i] = if x < - 50.0 { 0.0 } else if x > 50.0 { x } else { x / (1.0 + (- x) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "avx2")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm256_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm256_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm256_set1_ps (0.5) ; let one = _mm256_set1_ps (1.0) ; let two = _mm256_set1_ps (2.0) ; let c1 = _mm256_set1_ps (1.0) ; let c2 = _mm256_set1_ps (0.5) ; let c3 = _mm256_set1_ps (0.166_666_67) ; let c4 = _mm256_set1_ps (0.041_666_668) ; let c5 = _mm256_set1_ps (0.008_333_334) ; let c6 = _mm256_set1_ps (0.001_388_889) ; let exp_hi = _mm256_set1_ps (88.376_26) ; let exp_lo = _mm256_set1_ps (- 87.336_55) ; while i + 8 <= len { let x = _mm256_loadu_ps (a . as_ptr () . add (i)) ; let two_x = _mm256_mul_ps (two , x) ; let two_x = _mm256_max_ps (_mm256_min_ps (two_x , exp_hi) , exp_lo) ; let x_scaled = _mm256_mul_ps (two_x , log2e) ; let k = _mm256_floor_ps (_mm256_add_ps (x_scaled , half)) ; let r = _mm256_sub_ps (two_x , _mm256_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm256_fmadd_ps (p , r , c5) ; p = _mm256_fmadd_ps (p , r , c4) ; p = _mm256_fmadd_ps (p , r , c3) ; p = _mm256_fmadd_ps (p , r , c2) ; p = _mm256_fmadd_ps (p , r , c1) ; p = _mm256_fmadd_ps (p , r , one) ; let k_int = _mm256_cvtps_epi32 (k) ; let k_shifted = _mm256_slli_epi32 (k_int , 23) ; let scale = _mm256_castsi256_ps (_mm256_add_epi32 (_mm256_castps_si256 (one) , k_shifted)) ; let exp_2x = _mm256_mul_ps (p , scale) ; let tanh_numer = _mm256_sub_ps (exp_2x , one) ; let tanh_denom = _mm256_add_ps (exp_2x , one) ; let tanh_result = _mm256_div_ps (tanh_numer , tanh_denom) ; _mm256_storeu_ps (result . as_mut_ptr () . add (i) , tanh_result) ; i += 8 ; } while i < len { result [i] = a [i] . tanh () ; i += 1 ; } } } . self_ty`
- **Function**: `tests::test_avx2_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_scale_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_clamp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_fma_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_lerp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sum_kahan_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_norm_l1_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_norm_l2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_dot_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_add_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_sum_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_max_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
- **Function**: `tests::test_avx2_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(36)] [tdg: 2.5]
### ./src/backends/avx512.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `Avx512Backend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for Avx512Backend { # [target_feature (enable = "avx512f")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm512_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm512_add_ps (va , vb) ; _mm512_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 16 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "avx512f")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] - b [i] ; } } # [target_feature (enable = "avx512f")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] * b [i] ; } } # [target_feature (enable = "avx512f")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] / b [i] ; } } # [target_feature (enable = "avx512f")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm512_setzero_ps () ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm512_loadu_ps (b . as_ptr () . add (i)) ; acc = _mm512_fmadd_ps (va , vb , acc) ; i += 16 ; } let mut result = _mm512_reduce_add_ps (acc) ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "avx512f")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = _mm512_setzero_ps () ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; acc = _mm512_add_ps (acc , va) ; i += 16 ; } let mut result = _mm512_reduce_add_ps (acc) ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "avx512f")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmax = _mm512_max_ps (vmax , va) ; i += 16 ; } let mut result = _mm512_reduce_max_ps (vmax) ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "avx512f")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmin = _mm512_min_ps (vmin , va) ; i += 16 ; } let mut result = _mm512_reduce_min_ps (vmin) ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "avx512f")] unsafe fn argmax (a : & [f32]) -> usize { if a . is_empty () { return 0 ; } let len = a . len () ; let mut i = 0 ; let mut vmax = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmax = _mm512_max_ps (vmax , va) ; i += 16 ; } let mut max_val = _mm512_reduce_max_ps (vmax) ; for & val in & a [i ..] { if val > max_val { max_val = val ; } } a . iter () . position (| & x | x == max_val) . unwrap_or (0) } # [target_feature (enable = "avx512f")] unsafe fn argmin (a : & [f32]) -> usize { if a . is_empty () { return 0 ; } let len = a . len () ; let mut i = 0 ; let mut vmin = _mm512_set1_ps (a [0]) ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; vmin = _mm512_min_ps (vmin , va) ; i += 16 ; } let mut min_val = _mm512_reduce_min_ps (vmin) ; for & val in & a [i ..] { if val < min_val { min_val = val ; } } a . iter () . position (| & x | x == min_val) . unwrap_or (0) } # [target_feature (enable = "avx512f")] unsafe fn sum_kahan (a : & [f32]) -> f32 { let mut sum = 0.0 ; let mut c = 0.0 ; for & x in a { let y = x - c ; let t = sum + y ; c = (t - sum) - y ; sum = t ; } sum } # [target_feature (enable = "avx512f")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = _mm512_setzero_ps () ; while i + 16 <= len { let va = _mm512_loadu_ps (a . as_ptr () . add (i)) ; let squared = _mm512_mul_ps (va , va) ; acc = _mm512_add_ps (acc , squared) ; i += 16 ; } let mut sum_of_squares = _mm512_reduce_add_ps (acc) ; for & val in & a [i ..] { sum_of_squares += val * val ; } sum_of_squares . sqrt () } # [target_feature (enable = "avx512f")] unsafe fn norm_l1 (a : & [f32]) -> f32 { a . iter () . map (| x | x . abs ()) . sum () } # [target_feature (enable = "avx512f")] unsafe fn norm_linf (a : & [f32]) -> f32 { a . iter () . map (| x | x . abs ()) . fold (0.0f32 , f32 :: max) } # [target_feature (enable = "avx512f")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] * scalar ; } } # [target_feature (enable = "avx512f")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . abs () ; } } # [target_feature (enable = "avx512f")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . clamp (min_val , max_val) ; } } # [target_feature (enable = "avx512f")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] + t * (b [i] - a [i]) ; } } # [target_feature (enable = "avx512f")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . mul_add (b [i] , c [i]) ; } } # [target_feature (enable = "avx512f")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . max (0.0) ; } } # [target_feature (enable = "avx512f")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . exp () ; } } # [target_feature (enable = "avx512f")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = 1.0 / (1.0 + (- a [i]) . exp ()) ; } } # [target_feature (enable = "avx512f")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; for i in 0 .. a . len () { let x = a [i] ; let cube = x * x * x ; let inner = SQRT_2_OVER_PI * (x + 0.044715 * cube) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; } } # [target_feature (enable = "avx512f")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { let sigmoid_val = 1.0 / (1.0 + (- a [i]) . exp ()) ; result [i] = a [i] * sigmoid_val ; } } # [target_feature (enable = "avx512f")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] . tanh () ; } } } . self_ty`
- **Function**: `tests::avx512_test` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_special_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_add_remainder_correctness` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_special_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_remainder_sizes` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_dot_orthogonal` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_sum_remainder_sizes` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_max_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_positive_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_min_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_non_aligned_18` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_max_at_start` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmax_backend_equivalence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_non_aligned_18` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_positive_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_min_at_start` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_argmin_backend_equivalence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_aligned_16` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_non_aligned` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_equivalence_to_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
- **Function**: `tests::test_avx512_norm_l2_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(7)] [tdg: 2.5]
### ./src/backends/gpu/device.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `GpuDevice` [fields: 2]
- **Impl**: `impl GpuDevice { # [doc = " Initialize GPU device"] pub fn new () -> Result < Self , String > { pollster :: block_on (async { Self :: new_async () . await }) } async fn new_async () -> Result < Self , String > { let instance = wgpu :: Instance :: default () ; let adapter = instance . request_adapter (& wgpu :: RequestAdapterOptions { power_preference : wgpu :: PowerPreference :: HighPerformance , compatible_surface : None , force_fallback_adapter : false , }) . await . ok_or ("Failed to find GPU adapter") ? ; let (device , queue) = adapter . request_device (& wgpu :: DeviceDescriptor { label : Some ("Trueno GPU Device") , required_features : wgpu :: Features :: empty () , required_limits : wgpu :: Limits :: default () , memory_hints : wgpu :: MemoryHints :: Performance , } , None ,) . await . map_err (| e | format ! ("Failed to create device: {}" , e)) ? ; Ok (Self { device , queue }) } # [doc = " Check if GPU is available"] pub fn is_available () -> bool { pollster :: block_on (async { let instance = wgpu :: Instance :: default () ; instance . request_adapter (& wgpu :: RequestAdapterOptions { power_preference : wgpu :: PowerPreference :: HighPerformance , compatible_surface : None , force_fallback_adapter : false , }) . await . is_some () }) } # [doc = " Execute matrix multiplication on GPU"] pub fn matmul (& self , a : & [f32] , b : & [f32] , result : & mut [f32] , m : usize , k : usize , n : usize ,) -> Result < () , String > { pollster :: block_on (async { self . matmul_async (a , b , result , m , k , n) . await }) } async fn matmul_async (& self , a : & [f32] , b : & [f32] , result : & mut [f32] , m : usize , k : usize , n : usize ,) -> Result < () , String > { let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Matmul Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: MATMUL_SHADER . into ()) , }) ; let a_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Matrix A") , size : std :: mem :: size_of_val (a) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let b_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Matrix B") , size : std :: mem :: size_of_val (b) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let c_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Matrix C") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct Dimensions { m : u32 , k : u32 , n : u32 , _padding : u32 , } let dims = Dimensions { m : m as u32 , k : k as u32 , n : n as u32 , _padding : 0 , } ; let dims_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Dimensions") , size : std :: mem :: size_of :: < Dimensions > () as u64 , usage : wgpu :: BufferUsages :: UNIFORM | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& a_buffer , 0 , bytemuck :: cast_slice (a)) ; self . queue . write_buffer (& b_buffer , 0 , bytemuck :: cast_slice (b)) ; self . queue . write_buffer (& dims_buffer , 0 , bytemuck :: bytes_of (& dims)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Matmul Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 3 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Uniform , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Matmul Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : a_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : b_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : c_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 3 , resource : dims_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Matmul Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Matmul Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Matmul Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Matmul Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size_x = 16 ; let workgroup_size_y = 16 ; let num_workgroups_x = (m as u32) . div_ceil (workgroup_size_x) ; let num_workgroups_y = (n as u32) . div_ceil (workgroup_size_y) ; compute_pass . dispatch_workgroups (num_workgroups_x , num_workgroups_y , 1) ; } encoder . copy_buffer_to_buffer (& c_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; result . copy_from_slice (bytemuck :: cast_slice (& data)) ; } staging_buffer . unmap () ; Ok (()) } # [doc = " Execute vector addition on GPU: c = a + b"] pub fn vec_add (& self , a : & [f32] , b : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . vec_add_async (a , b , result) . await }) } async fn vec_add_async (& self , a : & [f32] , b : & [f32] , result : & mut [f32]) -> Result < () , String > { let len = a . len () ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Vec Add Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: VEC_ADD_SHADER . into ()) , }) ; let a_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector A") , size : std :: mem :: size_of_val (a) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let b_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector B") , size : std :: mem :: size_of_val (b) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let c_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector C") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& a_buffer , 0 , bytemuck :: cast_slice (a)) ; self . queue . write_buffer (& b_buffer , 0 , bytemuck :: cast_slice (b)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Vec Add Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Vec Add Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : a_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : b_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : c_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Vec Add Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Vec Add Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Vec Add Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Vec Add Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } encoder . copy_buffer_to_buffer (& c_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; result . copy_from_slice (bytemuck :: cast_slice (& data)) ; } staging_buffer . unmap () ; Ok (()) } # [doc = " Generic helper for element-wise GPU operations"] # [doc = ""] # [doc = " This helper eliminates code duplication between element-wise operations"] # [doc = " (relu, clip, sigmoid, tanh, etc.) by abstracting the common GPU compute pattern."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `op_name` - Operation name for labels (e.g., \"ReLU\", \"Clip\")"] # [doc = " * `shader_source` - WGSL shader source code"] # [doc = " * `input` - Input data"] # [doc = " * `result` - Output buffer"] # [doc = " * `uniform_data` - Optional uniform buffer data (e.g., clip parameters)"] async fn execute_element_wise_op (& self , op_name : & str , shader_source : & str , input : & [f32] , result : & mut [f32] , uniform_data : Option < & [u8] > ,) -> Result < () , String > { let len = input . len () ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some (& format ! ("{} Shader" , op_name)) , source : wgpu :: ShaderSource :: Wgsl (shader_source . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Input" , op_name)) , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let output_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Output" , op_name)) , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; let uniform_buffer = uniform_data . map (| data | { let buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Uniform" , op_name)) , size : data . len () as u64 , usage : wgpu :: BufferUsages :: UNIFORM | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& buffer , 0 , data) ; buffer }) ; let mut bind_group_entries = vec ! [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] ; if uniform_buffer . is_some () { bind_group_entries . push (wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Uniform , has_dynamic_offset : false , min_binding_size : None , } , count : None , }) ; } let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some (& format ! ("{} Bind Group Layout" , op_name)) , entries : & bind_group_entries , }) ; let mut bind_entries = vec ! [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : output_buffer . as_entire_binding () , } ,] ; if let Some (ref uniform_buf) = uniform_buffer { bind_entries . push (wgpu :: BindGroupEntry { binding : 2 , resource : uniform_buf . as_entire_binding () , }) ; } let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some (& format ! ("{} Bind Group" , op_name)) , layout : & bind_group_layout , entries : & bind_entries , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some (& format ! ("{} Pipeline Layout" , op_name)) , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some (& format ! ("{} Pipeline" , op_name)) , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some (& format ! ("{} Staging Buffer" , op_name)) , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some (& format ! ("{} Encoder" , op_name)) , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some (& format ! ("{} Pass" , op_name)) , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } encoder . copy_buffer_to_buffer (& output_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; result . copy_from_slice (bytemuck :: cast_slice (& data)) ; } staging_buffer . unmap () ; Ok (()) } # [doc = " Execute ReLU activation on GPU: result[i] = max(0, input[i])"] pub fn relu (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("ReLU" , shaders :: RELU_SHADER , input , result , None) . await }) } # [doc = " Execute leaky ReLU activation on GPU: result[i] = max(negative_slope * input[i], input[i])"] pub fn leaky_relu (& self , input : & [f32] , result : & mut [f32] , negative_slope : f32 ,) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct LeakyReluParams { negative_slope : f32 , } let params = LeakyReluParams { negative_slope } ; let uniform_data = bytemuck :: bytes_of (& params) ; pollster :: block_on (async { self . execute_element_wise_op ("LeakyReLU" , shaders :: LEAKY_RELU_SHADER , input , result , Some (uniform_data) ,) . await }) } # [doc = " Execute ELU activation on GPU: result[i] = x if x > 0, else alpha * (exp(x) - 1)"] pub fn elu (& self , input : & [f32] , result : & mut [f32] , alpha : f32) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct EluParams { alpha : f32 , } let params = EluParams { alpha } ; let uniform_data = bytemuck :: bytes_of (& params) ; pollster :: block_on (async { self . execute_element_wise_op ("ELU" , shaders :: ELU_SHADER , input , result , Some (uniform_data) ,) . await }) } # [doc = " Execute sigmoid activation on GPU: result[i] = 1 / (1 + exp(-input[i]))"] pub fn sigmoid (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("Sigmoid" , shaders :: SIGMOID_SHADER , input , result , None) . await }) } # [doc = " Execute tanh activation on GPU: result[i] = tanh(input[i])"] pub fn tanh (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("Tanh" , shaders :: TANH_SHADER , input , result , None) . await }) } # [doc = " Execute swish activation on GPU: result[i] = input[i] / (1 + exp(-input[i]))"] pub fn swish (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("Swish" , shaders :: SWISH_SHADER , input , result , None) . await }) } # [doc = " Execute GELU activation on GPU: result[i] = 0.5 * input[i] * (1 + tanh(...))"] pub fn gelu (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . execute_element_wise_op ("GELU" , shaders :: GELU_SHADER , input , result , None) . await }) } # [doc = " Execute clip (clamp) operation on GPU: result[i] = clamp(input[i], min_val, max_val)"] pub fn clip (& self , input : & [f32] , result : & mut [f32] , min_val : f32 , max_val : f32 ,) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct ClipParams { min_val : f32 , max_val : f32 , } let params = ClipParams { min_val , max_val } ; let uniform_data = bytemuck :: bytes_of (& params) ; pollster :: block_on (async { self . execute_element_wise_op ("Clip" , shaders :: CLIP_SHADER , input , result , Some (uniform_data) ,) . await }) } # [doc = " Execute softmax on GPU: result[i] = exp(input[i] - max) / sum(exp(input - max))"] # [doc = ""] # [doc = " Multi-pass implementation:"] # [doc = " 1. Find max value (parallel reduction)"] # [doc = " 2. Compute exp(x - max) (element-wise)"] # [doc = " 3. Sum exp values (parallel reduction)"] # [doc = " 4. Normalize by sum (element-wise)"] pub fn softmax (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . softmax_async (input , result) . await }) } async fn softmax_async (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { let max_val = self . reduce_max (input) . await ? ; let exp_vals = self . compute_exp_subtract (input , max_val) . await ? ; let sum_exp = self . reduce_sum (& exp_vals) . await ? ; self . normalize_by_sum (& exp_vals , result , sum_exp) . await ? ; Ok (()) } # [doc = " Execute log_softmax on GPU: result[i] = input[i] - max - log(sum(exp(input - max)))"] # [doc = ""] # [doc = " Multi-pass implementation:"] # [doc = " 1. Find max value (parallel reduction)"] # [doc = " 2. Compute exp(x - max) (element-wise)"] # [doc = " 3. Sum exp values (parallel reduction)"] # [doc = " 4. Compute log_softmax (element-wise)"] pub fn log_softmax (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { pollster :: block_on (async { self . log_softmax_async (input , result) . await }) } async fn log_softmax_async (& self , input : & [f32] , result : & mut [f32]) -> Result < () , String > { let max_val = self . reduce_max (input) . await ? ; let exp_vals = self . compute_exp_subtract (input , max_val) . await ? ; let sum_exp = self . reduce_sum (& exp_vals) . await ? ; let log_sum_exp = sum_exp . ln () ; # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct LogSoftmaxParams { max_val : f32 , log_sum_exp : f32 , } let params = LogSoftmaxParams { max_val , log_sum_exp , } ; let uniform_data = bytemuck :: bytes_of (& params) ; self . execute_element_wise_op ("LogSoftmax" , shaders :: LOG_SOFTMAX_SHADER , input , result , Some (uniform_data) ,) . await ? ; Ok (()) } # [doc = " Helper: Parallel max reduction"] async fn reduce_max (& self , input : & [f32]) -> Result < f32 , String > { let len = input . len () ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Max Reduction Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: MAX_REDUCTION_SHADER . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Max Reduction Input") , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let partial_results = vec ! [f32 :: NEG_INFINITY ; num_workgroups as usize] ; let result_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Max Partial Results") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Max Reduction Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Max Reduction Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : result_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Max Reduction Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Max Reduction Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Max Reduction Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Max Reduction Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Max Staging Buffer") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; encoder . copy_buffer_to_buffer (& result_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (partial_results . as_slice ()) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Channel receive failed") ? . map_err (| e | format ! ("Buffer map failed: {:?}" , e)) ? ; let data = buffer_slice . get_mapped_range () ; let result : Vec < f32 > = bytemuck :: cast_slice (& data) . to_vec () ; drop (data) ; staging_buffer . unmap () ; Ok (result . iter () . copied () . fold (f32 :: NEG_INFINITY , f32 :: max)) } # [doc = " Helper: Parallel sum reduction"] async fn reduce_sum (& self , input : & [f32]) -> Result < f32 , String > { let len = input . len () ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Sum Reduction Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: SUM_REDUCTION_SHADER . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Sum Reduction Input") , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let partial_results = vec ! [0.0f32 ; num_workgroups as usize] ; let result_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Sum Partial Results") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Sum Reduction Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Sum Reduction Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : result_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Sum Reduction Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Sum Reduction Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Sum Reduction Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Sum Reduction Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Sum Staging Buffer") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; encoder . copy_buffer_to_buffer (& result_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (partial_results . as_slice ()) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Channel receive failed") ? . map_err (| e | format ! ("Buffer map failed: {:?}" , e)) ? ; let data = buffer_slice . get_mapped_range () ; let result : Vec < f32 > = bytemuck :: cast_slice (& data) . to_vec () ; drop (data) ; staging_buffer . unmap () ; Ok (result . iter () . sum ()) } # [doc = " Helper: Compute exp(input[i] - max_val)"] async fn compute_exp_subtract (& self , input : & [f32] , max_val : f32) -> Result < Vec < f32 > , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct MaxValue { max_val : f32 , } let params = MaxValue { max_val } ; let uniform_data = bytemuck :: bytes_of (& params) ; let mut result = vec ! [0.0f32 ; input . len ()] ; self . execute_element_wise_op ("SoftmaxExp" , shaders :: SOFTMAX_EXP_SHADER , input , & mut result , Some (uniform_data) ,) . await ? ; Ok (result) } # [doc = " Helper: Normalize by sum"] async fn normalize_by_sum (& self , input : & [f32] , result : & mut [f32] , sum_val : f32 ,) -> Result < () , String > { # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct SumValue { sum_val : f32 , } let params = SumValue { sum_val } ; let uniform_data = bytemuck :: bytes_of (& params) ; self . execute_element_wise_op ("SoftmaxNormalize" , shaders :: SOFTMAX_NORMALIZE_SHADER , input , result , Some (uniform_data) ,) . await ? ; Ok (()) } # [doc = " Execute dot product on GPU: result = sum(a[i] * b[i])"] pub fn dot (& self , a : & [f32] , b : & [f32]) -> Result < f32 , String > { pollster :: block_on (async { self . dot_async (a , b) . await }) } async fn dot_async (& self , a : & [f32] , b : & [f32]) -> Result < f32 , String > { let len = a . len () ; let workgroup_size = 256 ; let num_workgroups = (len as u32) . div_ceil (workgroup_size) ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Dot Product Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: DOT_PRODUCT_SHADER . into ()) , }) ; let a_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector A") , size : std :: mem :: size_of_val (a) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let b_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Vector B") , size : std :: mem :: size_of_val (b) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let partial_results = vec ! [0.0f32 ; num_workgroups as usize] ; let result_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Partial Results") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& a_buffer , 0 , bytemuck :: cast_slice (a)) ; self . queue . write_buffer (& b_buffer , 0 , bytemuck :: cast_slice (b)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Dot Product Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Dot Product Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : a_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : b_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : result_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Dot Product Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Dot Product Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (partial_results . as_slice ()) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Dot Product Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Dot Product Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; compute_pass . dispatch_workgroups (num_workgroups , 1 , 1) ; } encoder . copy_buffer_to_buffer (& result_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (partial_results . as_slice ()) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . ok () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; let final_result = { let data = buffer_slice . get_mapped_range () ; let partial_sums : & [f32] = bytemuck :: cast_slice (& data) ; partial_sums . iter () . sum () } ; staging_buffer . unmap () ; Ok (final_result) } # [doc = " Perform 2D convolution on GPU"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input image (row-major)"] # [doc = " * `kernel` - Convolution kernel (row-major)"] # [doc = " * `result` - Output buffer (row-major)"] # [doc = " * `input_rows` - Number of rows in input"] # [doc = " * `input_cols` - Number of columns in input"] # [doc = " * `kernel_rows` - Number of rows in kernel"] # [doc = " * `kernel_cols` - Number of columns in kernel"] # [doc = ""] # [doc = " Output dimensions: (input_rows - kernel_rows + 1) × (input_cols - kernel_cols + 1)"] # [allow (clippy :: too_many_arguments)] pub fn convolve2d (& self , input : & [f32] , kernel : & [f32] , result : & mut [f32] , input_rows : usize , input_cols : usize , kernel_rows : usize , kernel_cols : usize ,) -> Result < () , String > { pollster :: block_on (async { self . convolve2d_async (input , kernel , result , input_rows , input_cols , kernel_rows , kernel_cols ,) . await }) } # [allow (clippy :: too_many_arguments)] async fn convolve2d_async (& self , input : & [f32] , kernel : & [f32] , result : & mut [f32] , input_rows : usize , input_cols : usize , kernel_rows : usize , kernel_cols : usize ,) -> Result < () , String > { let output_rows = input_rows - kernel_rows + 1 ; let output_cols = input_cols - kernel_cols + 1 ; let shader = self . device . create_shader_module (wgpu :: ShaderModuleDescriptor { label : Some ("Convolve2D Shader") , source : wgpu :: ShaderSource :: Wgsl (shaders :: CONVOLVE2D_SHADER . into ()) , }) ; let input_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Input Image") , size : std :: mem :: size_of_val (input) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let kernel_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Kernel") , size : std :: mem :: size_of_val (kernel) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; let output_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Output") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: STORAGE | wgpu :: BufferUsages :: COPY_SRC | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; # [repr (C)] # [derive (Copy , Clone , bytemuck :: Pod , bytemuck :: Zeroable)] struct ConvDimensions { input_rows : u32 , input_cols : u32 , kernel_rows : u32 , kernel_cols : u32 , output_rows : u32 , output_cols : u32 , } let dims = ConvDimensions { input_rows : input_rows as u32 , input_cols : input_cols as u32 , kernel_rows : kernel_rows as u32 , kernel_cols : kernel_cols as u32 , output_rows : output_rows as u32 , output_cols : output_cols as u32 , } ; let dims_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Conv Dimensions") , size : std :: mem :: size_of :: < ConvDimensions > () as u64 , usage : wgpu :: BufferUsages :: UNIFORM | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; self . queue . write_buffer (& input_buffer , 0 , bytemuck :: cast_slice (input)) ; self . queue . write_buffer (& kernel_buffer , 0 , bytemuck :: cast_slice (kernel)) ; self . queue . write_buffer (& dims_buffer , 0 , bytemuck :: bytes_of (& dims)) ; let bind_group_layout = self . device . create_bind_group_layout (& wgpu :: BindGroupLayoutDescriptor { label : Some ("Convolve2D Bind Group Layout") , entries : & [wgpu :: BindGroupLayoutEntry { binding : 0 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 1 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : true } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 2 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Storage { read_only : false } , has_dynamic_offset : false , min_binding_size : None , } , count : None , } , wgpu :: BindGroupLayoutEntry { binding : 3 , visibility : wgpu :: ShaderStages :: COMPUTE , ty : wgpu :: BindingType :: Buffer { ty : wgpu :: BufferBindingType :: Uniform , has_dynamic_offset : false , min_binding_size : None , } , count : None , } ,] , }) ; let bind_group = self . device . create_bind_group (& wgpu :: BindGroupDescriptor { label : Some ("Convolve2D Bind Group") , layout : & bind_group_layout , entries : & [wgpu :: BindGroupEntry { binding : 0 , resource : input_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 1 , resource : kernel_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 2 , resource : output_buffer . as_entire_binding () , } , wgpu :: BindGroupEntry { binding : 3 , resource : dims_buffer . as_entire_binding () , } ,] , }) ; let pipeline_layout = self . device . create_pipeline_layout (& wgpu :: PipelineLayoutDescriptor { label : Some ("Convolve2D Pipeline Layout") , bind_group_layouts : & [& bind_group_layout] , push_constant_ranges : & [] , }) ; let pipeline = self . device . create_compute_pipeline (& wgpu :: ComputePipelineDescriptor { label : Some ("Convolve2D Pipeline") , layout : Some (& pipeline_layout) , module : & shader , entry_point : "main" , compilation_options : Default :: default () , cache : None , }) ; let mut encoder = self . device . create_command_encoder (& wgpu :: CommandEncoderDescriptor { label : Some ("Convolve2D Encoder") , }) ; { let mut compute_pass = encoder . begin_compute_pass (& wgpu :: ComputePassDescriptor { label : Some ("Convolve2D Pass") , timestamp_writes : None , }) ; compute_pass . set_pipeline (& pipeline) ; compute_pass . set_bind_group (0 , & bind_group , & []) ; let workgroup_size_x = 16 ; let workgroup_size_y = 16 ; let num_workgroups_x = (output_rows as u32) . div_ceil (workgroup_size_x) ; let num_workgroups_y = (output_cols as u32) . div_ceil (workgroup_size_y) ; compute_pass . dispatch_workgroups (num_workgroups_x , num_workgroups_y , 1) ; } let staging_buffer = self . device . create_buffer (& wgpu :: BufferDescriptor { label : Some ("Staging Buffer") , size : std :: mem :: size_of_val (result) as u64 , usage : wgpu :: BufferUsages :: MAP_READ | wgpu :: BufferUsages :: COPY_DST , mapped_at_creation : false , }) ; encoder . copy_buffer_to_buffer (& output_buffer , 0 , & staging_buffer , 0 , std :: mem :: size_of_val (result) as u64 ,) ; self . queue . submit (Some (encoder . finish ())) ; let buffer_slice = staging_buffer . slice (..) ; let (sender , receiver) = futures_intrusive :: channel :: shared :: oneshot_channel () ; buffer_slice . map_async (wgpu :: MapMode :: Read , move | result | { sender . send (result) . unwrap () ; }) ; self . device . poll (wgpu :: Maintain :: Wait) ; receiver . receive () . await . ok_or ("Failed to receive mapping result") ? . map_err (| e | format ! ("Buffer mapping failed: {:?}" , e)) ? ; { let data = buffer_slice . get_mapped_range () ; let output_data : & [f32] = bytemuck :: cast_slice (& data) ; result . copy_from_slice (output_data) ; } staging_buffer . unmap () ; Ok (()) } } . self_ty`
- **Struct**: `Dimensions` [fields: 4]
- **Struct**: `LeakyReluParams` [fields: 1]
- **Struct**: `EluParams` [fields: 1]
- **Struct**: `ClipParams` [fields: 2]
- **Struct**: `LogSoftmaxParams` [fields: 2]
- **Struct**: `MaxValue` [fields: 1]
- **Struct**: `SumValue` [fields: 1]
- **Struct**: `ConvDimensions` [fields: 6]
- **Function**: `tests::test_is_available_consistency` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(16)] [tdg: 2.5]
- **Function**: `tests::test_reduce_sum_not_hardcoded` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(16)] [tdg: 2.5]
### ./src/backends/gpu/mod.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `GpuBackend` [fields: 1]
- **Impl**: `# [cfg (feature = "gpu")] impl GpuBackend { # [doc = " Create a new GPU backend"] pub fn new () -> Self { Self { device : None } } # [doc = " Initialize GPU device (lazy)"] fn ensure_device (& mut self) -> Result < & GpuDevice , String > { if self . device . is_none () { self . device = Some (GpuDevice :: new () ?) ; } Ok (self . device . as_ref () . unwrap ()) } # [doc = " Check if GPU is available"] pub fn is_available () -> bool { GpuDevice :: is_available () } # [doc = " Vector addition on GPU: c = a + b"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `a` - Vector a"] # [doc = " * `b` - Vector b"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector c (element-wise sum)"] pub fn vec_add (& mut self , a : & [f32] , b : & [f32]) -> Result < Vec < f32 > , String > { if a . len () != b . len () { return Err (format ! ("Vector length mismatch: {} != {}" , a . len () , b . len ())) ; } if a . is_empty () { return Err ("Cannot perform GPU operation on empty vectors" . to_string ()) ; } let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; a . len ()] ; device . vec_add (a , b , & mut result) ? ; Ok (result) } # [doc = " Dot product on GPU: result = sum(a[i] * b[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `a` - Vector a"] # [doc = " * `b` - Vector b"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Scalar dot product result"] pub fn dot (& mut self , a : & [f32] , b : & [f32]) -> Result < f32 , String > { if a . len () != b . len () { return Err (format ! ("Vector length mismatch: {} != {}" , a . len () , b . len ())) ; } let device = self . ensure_device () ? ; device . dot (a , b) } # [doc = " ReLU activation on GPU: result[i] = max(0, input[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with ReLU applied element-wise"] pub fn relu (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . relu (input , & mut result) ? ; Ok (result) } # [doc = " Leaky ReLU activation on GPU: result[i] = max(negative_slope * input[i], input[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = " * `negative_slope` - Slope for negative values (typically 0.01)"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with leaky ReLU applied element-wise"] pub fn leaky_relu (& mut self , input : & [f32] , negative_slope : f32) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . leaky_relu (input , & mut result , negative_slope) ? ; Ok (result) } # [doc = " ELU activation on GPU: result[i] = x if x > 0, else alpha * (exp(x) - 1)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = " * `alpha` - Scaling factor for negative values (typically 1.0)"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with ELU applied element-wise"] pub fn elu (& mut self , input : & [f32] , alpha : f32) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . elu (input , & mut result , alpha) ? ; Ok (result) } # [doc = " Clip (clamp) operation on GPU: result[i] = clamp(input[i], min_val, max_val)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = " * `min_val` - Minimum value"] # [doc = " * `max_val` - Maximum value"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with clip applied element-wise"] pub fn clip (& mut self , input : & [f32] , min_val : f32 , max_val : f32) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . clip (input , & mut result , min_val , max_val) ? ; Ok (result) } # [doc = " Sigmoid activation on GPU: result[i] = 1 / (1 + exp(-input[i]))"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with sigmoid applied element-wise"] pub fn sigmoid (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . sigmoid (input , & mut result) ? ; Ok (result) } # [doc = " Tanh activation on GPU: result[i] = tanh(input[i])"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with tanh applied element-wise"] pub fn tanh (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . tanh (input , & mut result) ? ; Ok (result) } # [doc = " Swish activation on GPU: result[i] = input[i] / (1 + exp(-input[i]))"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with swish applied element-wise"] pub fn swish (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . swish (input , & mut result) ? ; Ok (result) } # [doc = " GELU activation on GPU: result[i] = 0.5 * input[i] * (1 + tanh(...))"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with GELU applied element-wise"] pub fn gelu (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . gelu (input , & mut result) ? ; Ok (result) } # [doc = " Softmax activation on GPU: result[i] = exp(input[i] - max) / sum(exp(input - max))"] # [doc = ""] # [doc = " Uses multi-pass reduction for numerical stability:"] # [doc = " - Pass 1: Max reduction (parallel)"] # [doc = " - Pass 2: Exp-subtract (element-wise)"] # [doc = " - Pass 3: Sum reduction (parallel)"] # [doc = " - Pass 4: Normalize (element-wise)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with softmax applied element-wise"] pub fn softmax (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . softmax (input , & mut result) ? ; Ok (result) } # [doc = " Log-softmax activation on GPU: result[i] = log(softmax(input)[i])"] # [doc = ""] # [doc = " Uses multi-pass reduction for numerical stability:"] # [doc = " - Pass 1: Max reduction (parallel)"] # [doc = " - Pass 2: Exp-subtract (element-wise)"] # [doc = " - Pass 3: Sum reduction (parallel)"] # [doc = " - Pass 4: Log-normalize (element-wise)"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input vector"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Vector with log-softmax applied element-wise"] pub fn log_softmax (& mut self , input : & [f32]) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; input . len ()] ; device . log_softmax (input , & mut result) ? ; Ok (result) } # [doc = " 2D Convolution on GPU: output = input ⊗ kernel"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `input` - Input matrix (flattened row-major)"] # [doc = " * `kernel` - Convolution kernel (flattened row-major)"] # [doc = " * `input_rows` - Number of rows in input"] # [doc = " * `input_cols` - Number of columns in input"] # [doc = " * `kernel_rows` - Number of rows in kernel"] # [doc = " * `kernel_cols` - Number of columns in kernel"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Output matrix (flattened row-major, \"valid\" convolution)"] # [doc = " - output_rows = input_rows - kernel_rows + 1"] # [doc = " - output_cols = input_cols - kernel_cols + 1"] pub fn convolve2d (& mut self , input : & [f32] , kernel : & [f32] , input_rows : usize , input_cols : usize , kernel_rows : usize , kernel_cols : usize ,) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let output_rows = input_rows . saturating_sub (kernel_rows) . saturating_add (1) ; let output_cols = input_cols . saturating_sub (kernel_cols) . saturating_add (1) ; let mut result = vec ! [0.0f32 ; output_rows * output_cols] ; device . convolve2d (input , kernel , & mut result , input_rows , input_cols , kernel_rows , kernel_cols ,) ? ; Ok (result) } # [doc = " Matrix multiplication on GPU: C = A × B"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `a` - Matrix A (m×k) in row-major order"] # [doc = " * `b` - Matrix B (k×n) in row-major order"] # [doc = " * `m` - Rows of A and C"] # [doc = " * `k` - Cols of A, rows of B"] # [doc = " * `n` - Cols of B and C"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Matrix C (m×n) in row-major order"] pub fn matmul (& mut self , a : & [f32] , b : & [f32] , m : usize , k : usize , n : usize ,) -> Result < Vec < f32 > , String > { let device = self . ensure_device () ? ; let mut result = vec ! [0.0f32 ; m * n] ; device . matmul (a , b , & mut result , m , k , n) ? ; Ok (result) } } . self_ty`
- **Impl**: `Default` for `# [cfg (feature = "gpu")] impl Default for GpuBackend { fn default () -> Self { Self :: new () } } . self_ty`
- **Struct**: `GpuBackend` [fields: 0]
- **Impl**: `# [cfg (not (feature = "gpu"))] impl GpuBackend { pub fn new () -> Self { Self } pub fn is_available () -> bool { false } } . self_ty`
- **Impl**: `Default` for `# [cfg (not (feature = "gpu"))] impl Default for GpuBackend { fn default () -> Self { Self } } . self_ty`
- **Function**: `tests::test_gpu_vec_add_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_length_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_length_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_dot_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_vec_add_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_clip_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_leaky_relu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_elu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_tanh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_tanh_not_hardcoded` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
- **Function**: `tests::test_gpu_log_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(20)] [tdg: 2.5]
### ./src/backends/gpu/shaders.rs
**File Complexity**: 1 | **Functions**: 0
### ./src/backends/mod.rs
**File Complexity**: 1 | **Functions**: 0
- **Trait**: `VectorBackend`
### ./src/backends/neon.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `NeonBackend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for NeonBackend { # [target_feature (enable = "neon")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vaddq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "neon")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vsubq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "neon")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vmulq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "neon")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vresult = vdivq_f32 (va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "neon")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; acc = vmlaq_f32 (acc , va , vb) ; i += 4 ; } let sum2 = vpadd_f32 (vget_low_f32 (acc) , vget_high_f32 (acc)) ; let sum1 = vpadd_f32 (sum2 , sum2) ; let mut result = vget_lane_f32 (sum1 , 0) ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "neon")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; acc = vaddq_f32 (acc , va) ; i += 4 ; } let sum2 = vpadd_f32 (vget_low_f32 (acc) , vget_high_f32 (acc)) ; let sum1 = vpadd_f32 (sum2 , sum2) ; let mut result = vget_lane_f32 (sum1 , 0) ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "neon")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmax = vmaxq_f32 (vmax , va) ; i += 4 ; } let max2 = vpmax_f32 (vget_low_f32 (vmax) , vget_high_f32 (vmax)) ; let max1 = vpmax_f32 (max2 , max2) ; let mut result = vget_lane_f32 (max1 , 0) ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "neon")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmin = vminq_f32 (vmin , va) ; i += 4 ; } let min2 = vpmin_f32 (vget_low_f32 (vmin) , vget_high_f32 (vmin)) ; let min1 = vpmin_f32 (min2 , min2) ; let mut result = vget_lane_f32 (min1 , 0) ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "neon")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut max_value = a [0] ; let mut max_index = 0 ; let mut vmax = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmax = vmaxq_f32 (vmax , va) ; i += 4 ; } let max2 = vpmax_f32 (vget_low_f32 (vmax) , vget_high_f32 (vmax)) ; let max1 = vpmax_f32 (max2 , max2) ; for (idx , & val) in a [.. i] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "neon")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut min_value = a [0] ; let mut min_index = 0 ; let mut vmin = vdupq_n_f32 (a [0]) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; vmin = vminq_f32 (vmin , va) ; i += 4 ; } let min2 = vpmin_f32 (vget_low_f32 (vmin) , vget_high_f32 (vmin)) ; let min1 = vpmin_f32 (min2 , min2) ; for (idx , & val) in a [.. i] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "neon")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [cfg (target_arch = "aarch64")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let abs_va = vabsq_f32 (va) ; acc = vaddq_f32 (acc , abs_va) ; i += 4 ; } let mut result = vaddvq_f32 (acc) ; for & val in & a [i ..] { result += val . abs () ; } result } # [cfg (target_arch = "arm")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let abs_va = vabsq_f32 (va) ; acc = vaddq_f32 (acc , abs_va) ; i += 4 ; } let mut result = { let sum_halves = vpadd_f32 (vget_low_f32 (acc) , vget_high_f32 (acc)) ; let sum_all = vpadd_f32 (sum_halves , sum_halves) ; vget_lane_f32 (sum_all , 0) } ; for & val in & a [i ..] { result += val . abs () ; } result } # [cfg (target_arch = "aarch64")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = vdupq_n_f32 (scalar) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmulq_f32 (va , scalar_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = vdupq_n_f32 (scalar) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmulq_f32 (va , scalar_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = vdupq_n_f32 (min_val) ; let max_vec = vdupq_n_f32 (max_val) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let clamped = vminq_f32 (vmaxq_f32 (va , min_vec) , max_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = vdupq_n_f32 (min_val) ; let max_vec = vdupq_n_f32 (max_val) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let clamped = vminq_f32 (vmaxq_f32 (va , min_vec) , max_vec) ; vst1q_f32 (result . as_mut_ptr () . add (i) , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = vdupq_n_f32 (t) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let diff = vsubq_f32 (vb , va) ; let vresult = vfmaq_f32 (va , t_vec , diff) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = vdupq_n_f32 (t) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let diff = vsubq_f32 (vb , va) ; let vresult = vmlaq_f32 (va , t_vec , diff) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vc = vld1q_f32 (c . as_ptr () . add (i)) ; let vresult = vfmaq_f32 (vc , va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vb = vld1q_f32 (b . as_ptr () . add (i)) ; let vc = vld1q_f32 (c . as_ptr () . add (i)) ; let vresult = vmlaq_f32 (vc , va , vb) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmaxq_f32 (zero , va) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = vdupq_n_f32 (0.0) ; while i + 4 <= len { let va = vld1q_f32 (a . as_ptr () . add (i)) ; let vresult = vmaxq_f32 (zero , va) ; vst1q_f32 (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let one = vdupq_n_f32 (1.0) ; let half = vdupq_n_f32 (0.5) ; let zero = vdupq_n_f32 (0.0) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let neg_x = vsubq_f32 (zero , x) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (neg_x , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (neg_x , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_neg_x = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let sigmoid_result = vdivq_f32 (one , vaddq_f32 (one , exp_neg_x)) ; vst1q_f32 (result . as_mut_ptr () . add (i) , sigmoid_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; } } # [cfg (target_arch = "aarch64")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = vdupq_n_f32 (0.797_884_6) ; let coeff = vdupq_n_f32 (0.044715) ; let half = vdupq_n_f32 (0.5) ; let one = vdupq_n_f32 (1.0) ; let two = vdupq_n_f32 (2.0) ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let x2 = vmulq_f32 (x , x) ; let x3 = vmulq_f32 (x2 , x) ; let inner = vmulq_f32 (sqrt_2_over_pi , vaddq_f32 (x , vmulq_f32 (coeff , x3))) ; let z = vmulq_f32 (two , inner) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (z , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (z , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_2z = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let tanh_val = vdivq_f32 (vsubq_f32 (exp_2z , one) , vaddq_f32 (exp_2z , one)) ; let gelu_result = vmulq_f32 (half , vmulq_f32 (x , vaddq_f32 (one , tanh_val))) ; vst1q_f32 (result . as_mut_ptr () . add (i) , gelu_result) ; i += 4 ; } while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = 0.797_884_6 * (x + 0.044715 * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; for (i , & x) in a . iter () . enumerate () { let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; } } # [cfg (target_arch = "aarch64")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let one = vdupq_n_f32 (1.0) ; let half = vdupq_n_f32 (0.5) ; let zero = vdupq_n_f32 (0.0) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let neg_x = vsubq_f32 (zero , x) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (neg_x , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (neg_x , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_neg_x = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let swish_result = vdivq_f32 (x , vaddq_f32 (one , exp_neg_x)) ; vst1q_f32 (result . as_mut_ptr () . add (i) , swish_result) ; i += 4 ; } while i < len { let x = a [i] ; if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } i += 1 ; } } # [cfg (target_arch = "aarch64")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = vdupq_n_f32 (std :: f32 :: consts :: LOG2_E) ; let ln2 = vdupq_n_f32 (std :: f32 :: consts :: LN_2) ; let one = vdupq_n_f32 (1.0) ; let two = vdupq_n_f32 (2.0) ; let half = vdupq_n_f32 (0.5) ; let c1 = vdupq_n_f32 (1.0) ; let c2 = vdupq_n_f32 (0.5) ; let c3 = vdupq_n_f32 (0.166_666_67) ; let c4 = vdupq_n_f32 (0.041_666_668) ; let c5 = vdupq_n_f32 (0.008_333_334) ; let c6 = vdupq_n_f32 (0.001_388_889) ; while i + 4 <= len { let x = vld1q_f32 (a . as_ptr () . add (i)) ; let z = vmulq_f32 (two , x) ; let kf = vrndmq_f32 (vaddq_f32 (vmulq_f32 (z , log2e) , half)) ; let k = vcvtq_s32_f32 (kf) ; let r = vsubq_f32 (z , vmulq_f32 (kf , ln2)) ; let mut poly = vaddq_f32 (c5 , vmulq_f32 (r , c6)) ; poly = vaddq_f32 (c4 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c3 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c2 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (c1 , vmulq_f32 (r , poly)) ; poly = vaddq_f32 (one , vmulq_f32 (r , poly)) ; let k_shifted = vshlq_n_s32 (vaddq_s32 (k , vdupq_n_s32 (127)) , 23) ; let exp_2x = vmulq_f32 (poly , vreinterpretq_f32_s32 (k_shifted)) ; let tanh_result = vdivq_f32 (vsubq_f32 (exp_2x , one) , vaddq_f32 (exp_2x , one)) ; vst1q_f32 (result . as_mut_ptr () . add (i) , tanh_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = val . tanh () ; i += 1 ; } } # [cfg (target_arch = "arm")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } } } # [cfg (target_arch = "arm")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { result [i] = x . tanh () ; } } } . self_ty`
- **Function**: `tests::test_neon_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
- **Function**: `tests::test_neon_tanh_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(22)] [tdg: 2.5]
### ./src/backends/scalar.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `ScalarBackend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for ScalarBackend { unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] + b [i] ; } } unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] - b [i] ; } } unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] * b [i] ; } } unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { for i in 0 .. a . len () { result [i] = a [i] / b [i] ; } } unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let mut sum = 0.0 ; for i in 0 .. a . len () { sum += a [i] * b [i] ; } sum } unsafe fn sum (a : & [f32]) -> f32 { let mut total = 0.0 ; for & val in a { total += val ; } total } unsafe fn max (a : & [f32]) -> f32 { let mut maximum = a [0] ; for & val in & a [1 ..] { if val > maximum { maximum = val ; } } maximum } unsafe fn min (a : & [f32]) -> f32 { let mut minimum = a [0] ; for & val in & a [1 ..] { if val < minimum { minimum = val ; } } minimum } unsafe fn argmax (a : & [f32]) -> usize { let mut max_value = a [0] ; let mut max_index = 0 ; for (i , & val) in a . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i ; } } max_index } unsafe fn argmin (a : & [f32]) -> usize { let mut min_value = a [0] ; let mut min_index = 0 ; for (i , & val) in a . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { let mut sum = 0.0 ; let mut c = 0.0 ; for & value in a { let y = value - c ; let t = sum + y ; c = (t - sum) - y ; sum = t ; } sum } unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let mut sum_of_squares = 0.0 ; for & val in a { sum_of_squares += val * val ; } sum_of_squares . sqrt () } unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let mut sum = 0.0 ; for & val in a { sum += val . abs () ; } sum } unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let mut max_val = 0.0_f32 ; for & val in a { let abs_val = val . abs () ; if abs_val > max_val { max_val = abs_val ; } } max_val } unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val * scalar ; } } unsafe fn abs (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val . abs () ; } } unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val . max (min_val) . min (max_val) ; } } unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { for (i , (& a_val , & b_val)) in a . iter () . zip (b . iter ()) . enumerate () { result [i] = a_val + t * (b_val - a_val) ; } } unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { for (i , ((& a_val , & b_val) , & c_val)) in a . iter () . zip (b . iter ()) . zip (c . iter ()) . enumerate () { result [i] = a_val * b_val + c_val ; } } unsafe fn relu (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = if val > 0.0 { val } else { 0.0 } ; } } unsafe fn exp (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = val . exp () ; } } unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { for (i , & val) in a . iter () . enumerate () { result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; } } unsafe fn gelu (a : & [f32] , result : & mut [f32]) { const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; for (i , & x) in a . iter () . enumerate () { let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; } } unsafe fn swish (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } } } unsafe fn tanh (a : & [f32] , result : & mut [f32]) { for (i , & x) in a . iter () . enumerate () { result [i] = x . tanh () ; } } } . self_ty`
- **Function**: `tests::test_scalar_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sub` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_div` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_argmax` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_argmin` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sum_kahan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_norm_l1` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_norm_l2` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_scale` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_clamp` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_lerp` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_fma` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_sigmoid` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_gelu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
- **Function**: `tests::test_scalar_swish` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(25)] [tdg: 2.5]
### ./src/backends/sse2.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `Sse2Backend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for Sse2Backend { # [target_feature (enable = "sse2")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm_add_ps (va , vb) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm_sub_ps (va , vb) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vresult = _mm_mul_ps (va , vb) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let two = _mm_set1_ps (2.0) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let rcp = _mm_rcp_ps (vb) ; let refined = _mm_mul_ps (rcp , _mm_sub_ps (two , _mm_mul_ps (vb , rcp))) ; let vresult = _mm_mul_ps (va , refined) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "sse2")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut sum_vec = _mm_setzero_ps () ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vmul = _mm_mul_ps (va , vb) ; sum_vec = _mm_add_ps (sum_vec , vmul) ; i += 4 ; } let mut sum = { let temp = _mm_add_ps (sum_vec , _mm_movehl_ps (sum_vec , sum_vec)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for j in i .. len { sum += a [j] * b [j] ; } sum } # [target_feature (enable = "sse2")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut sum_vec = _mm_setzero_ps () ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; sum_vec = _mm_add_ps (sum_vec , va) ; i += 4 ; } let mut sum = { let temp = _mm_add_ps (sum_vec , _mm_movehl_ps (sum_vec , sum_vec)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; sum += a [i .. len] . iter () . sum :: < f32 > () ; sum } # [target_feature (enable = "sse2")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut max_vec = _mm_set1_ps (a [0]) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; max_vec = _mm_max_ps (max_vec , va) ; i += 4 ; } let mut maximum = { let temp = _mm_max_ps (max_vec , _mm_movehl_ps (max_vec , max_vec)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i .. len] { if val > maximum { maximum = val ; } } maximum } # [target_feature (enable = "sse2")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut min_vec = _mm_set1_ps (a [0]) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; min_vec = _mm_min_ps (min_vec , va) ; i += 4 ; } let mut minimum = { let temp = _mm_min_ps (min_vec , _mm_movehl_ps (min_vec , min_vec)) ; let temp = _mm_min_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i .. len] { if val < minimum { minimum = val ; } } minimum } # [target_feature (enable = "sse2")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut vmax = _mm_set1_ps (a [0]) ; let mut vmax_idx = _mm_set1_ps (0.0) ; let mut vidx_current = _mm_set_ps (3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm_set1_ps (4.0) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm_cmpgt_ps (va , vmax) ; vmax = _mm_or_ps (_mm_and_ps (mask , va) , _mm_andnot_ps (mask , vmax)) ; vmax_idx = _mm_or_ps (_mm_and_ps (mask , vidx_current) , _mm_andnot_ps (mask , vmax_idx) ,) ; vidx_current = _mm_add_ps (vidx_current , vinc) ; i += 4 ; } let mut max_array = [0.0f32 ; 4] ; let mut idx_array = [0.0f32 ; 4] ; _mm_storeu_ps (max_array . as_mut_ptr () , vmax) ; _mm_storeu_ps (idx_array . as_mut_ptr () , vmax_idx) ; let mut max_value = max_array [0] ; let mut max_index = idx_array [0] as usize ; for j in 1 .. 4 { if max_array [j] > max_value { max_value = max_array [j] ; max_index = idx_array [j] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "sse2")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut vmin = _mm_set1_ps (a [0]) ; let mut vmin_idx = _mm_set1_ps (0.0) ; let mut vidx_current = _mm_set_ps (3.0 , 2.0 , 1.0 , 0.0) ; let vinc = _mm_set1_ps (4.0) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let mask = _mm_cmplt_ps (va , vmin) ; vmin = _mm_or_ps (_mm_and_ps (mask , va) , _mm_andnot_ps (mask , vmin)) ; vmin_idx = _mm_or_ps (_mm_and_ps (mask , vidx_current) , _mm_andnot_ps (mask , vmin_idx) ,) ; vidx_current = _mm_add_ps (vidx_current , vinc) ; i += 4 ; } let mut min_array = [0.0f32 ; 4] ; let mut idx_array = [0.0f32 ; 4] ; _mm_storeu_ps (min_array . as_mut_ptr () , vmin) ; _mm_storeu_ps (idx_array . as_mut_ptr () , vmin_idx) ; let mut min_value = min_array [0] ; let mut min_index = idx_array [0] as usize ; for j in 1 .. 4 { if min_array [j] < min_value { min_value = min_array [j] ; min_index = idx_array [j] as usize ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "sse2")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [target_feature (enable = "sse2")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = _mm_setzero_ps () ; let sign_mask = _mm_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm_and_ps (va , sign_mask) ; acc = _mm_add_ps (acc , abs_va) ; i += 4 ; } let mut result = { let temp = _mm_add_ps (acc , _mm_movehl_ps (acc , acc)) ; let temp = _mm_add_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { result += val . abs () ; } result } # [target_feature (enable = "sse2")] unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut max_vec = _mm_setzero_ps () ; let sign_mask = _mm_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm_and_ps (va , sign_mask) ; max_vec = _mm_max_ps (max_vec , abs_va) ; i += 4 ; } let mut result = { let temp = _mm_max_ps (max_vec , _mm_movehl_ps (max_vec , max_vec)) ; let temp = _mm_max_ss (temp , _mm_shuffle_ps (temp , temp , 1)) ; _mm_cvtss_f32 (temp) } ; for & val in & a [i ..] { let abs_val = val . abs () ; if abs_val > result { result = abs_val ; } } result } # [target_feature (enable = "sse2")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = _mm_set1_ps (scalar) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm_mul_ps (va , scalar_vec) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sign_mask = _mm_set1_ps (f32 :: from_bits (0x7FFF_FFFF)) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let abs_va = _mm_and_ps (va , sign_mask) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , abs_va) ; i += 4 ; } while i < len { result [i] = a [i] . abs () ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = _mm_set1_ps (min_val) ; let max_vec = _mm_set1_ps (max_val) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let clamped = _mm_min_ps (_mm_max_ps (va , min_vec) , max_vec) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = _mm_set1_ps (t) ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let diff = _mm_sub_ps (vb , va) ; let scaled_diff = _mm_mul_ps (t_vec , diff) ; let vresult = _mm_add_ps (va , scaled_diff) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vb = _mm_loadu_ps (b . as_ptr () . add (i)) ; let vc = _mm_loadu_ps (c . as_ptr () . add (i)) ; let product = _mm_mul_ps (va , vb) ; let vresult = _mm_add_ps (product , vc) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = _mm_setzero_ps () ; while i + 4 <= len { let va = _mm_loadu_ps (a . as_ptr () . add (i)) ; let vresult = _mm_max_ps (zero , va) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let x = _mm_max_ps (_mm_min_ps (x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let vresult = _mm_mul_ps (p , scale) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , vresult) ; i += 4 ; } while i < len { result [i] = a [i] . exp () ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm_sub_ps (_mm_setzero_ps () , x) ; let neg_x = _mm_max_ps (_mm_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (neg_x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (neg_x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_neg_x = _mm_mul_ps (p , scale) ; let denom = _mm_add_ps (one , exp_neg_x) ; let sigmoid_result = _mm_div_ps (one , denom) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , sigmoid_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = _mm_set1_ps (0.797_884_6) ; let coeff = _mm_set1_ps (0.044715) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let two = _mm_set1_ps (2.0) ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let x2 = _mm_mul_ps (x , x) ; let x3 = _mm_mul_ps (x2 , x) ; let inner_sum = _mm_add_ps (x , _mm_mul_ps (coeff , x3)) ; let inner = _mm_mul_ps (sqrt_2_over_pi , inner_sum) ; let two_inner = _mm_mul_ps (two , inner) ; let two_inner = _mm_max_ps (_mm_min_ps (two_inner , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (two_inner , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (two_inner , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_2inner = _mm_mul_ps (p , scale) ; let tanh_numer = _mm_sub_ps (exp_2inner , one) ; let tanh_denom = _mm_add_ps (exp_2inner , one) ; let tanh_result = _mm_div_ps (tanh_numer , tanh_denom) ; let one_plus_tanh = _mm_add_ps (one , tanh_result) ; let gelu_result = _mm_mul_ps (half , _mm_mul_ps (x , one_plus_tanh)) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , gelu_result) ; i += 4 ; } const SQRT_2_OVER_PI : f32 = 0.797_884_6 ; const COEFF : f32 = 0.044715 ; while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = SQRT_2_OVER_PI * (x + COEFF * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let neg_x = _mm_sub_ps (_mm_setzero_ps () , x) ; let neg_x = _mm_max_ps (_mm_min_ps (neg_x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (neg_x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (neg_x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_neg_x = _mm_mul_ps (p , scale) ; let denom = _mm_add_ps (one , exp_neg_x) ; let swish_result = _mm_div_ps (x , denom) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , swish_result) ; i += 4 ; } while i < len { let x = a [i] ; result [i] = if x < - 50.0 { 0.0 } else if x > 50.0 { x } else { x / (1.0 + (- x) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "sse2")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = _mm_set1_ps (std :: f32 :: consts :: LOG2_E) ; let ln2 = _mm_set1_ps (std :: f32 :: consts :: LN_2) ; let half = _mm_set1_ps (0.5) ; let one = _mm_set1_ps (1.0) ; let two = _mm_set1_ps (2.0) ; let c1 = _mm_set1_ps (1.0) ; let c2 = _mm_set1_ps (0.5) ; let c3 = _mm_set1_ps (0.166_666_67) ; let c4 = _mm_set1_ps (0.041_666_668) ; let c5 = _mm_set1_ps (0.008_333_334) ; let c6 = _mm_set1_ps (0.001_388_889) ; let exp_hi = _mm_set1_ps (88.376_26) ; let exp_lo = _mm_set1_ps (- 87.336_55) ; while i + 4 <= len { let x = _mm_loadu_ps (a . as_ptr () . add (i)) ; let two_x = _mm_mul_ps (two , x) ; let two_x = _mm_max_ps (_mm_min_ps (two_x , exp_hi) , exp_lo) ; let x_scaled = _mm_mul_ps (two_x , log2e) ; let k_plus_half = _mm_add_ps (x_scaled , half) ; let k_int = _mm_cvttps_epi32 (k_plus_half) ; let k = _mm_cvtepi32_ps (k_int) ; let mask = _mm_cmpgt_ps (k , k_plus_half) ; let k = _mm_sub_ps (k , _mm_and_ps (mask , one)) ; let r = _mm_sub_ps (two_x , _mm_mul_ps (k , ln2)) ; let mut p = c6 ; p = _mm_add_ps (_mm_mul_ps (p , r) , c5) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c4) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c3) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c2) ; p = _mm_add_ps (_mm_mul_ps (p , r) , c1) ; p = _mm_add_ps (_mm_mul_ps (p , r) , one) ; let k_int = _mm_cvtps_epi32 (k) ; let k_shifted = _mm_slli_epi32 (k_int , 23) ; let scale = _mm_castsi128_ps (_mm_add_epi32 (_mm_castps_si128 (one) , k_shifted)) ; let exp_2x = _mm_mul_ps (p , scale) ; let tanh_numer = _mm_sub_ps (exp_2x , one) ; let tanh_denom = _mm_add_ps (exp_2x , one) ; let tanh_result = _mm_div_ps (tanh_numer , tanh_denom) ; _mm_storeu_ps (result . as_mut_ptr () . add (i) , tanh_result) ; i += 4 ; } while i < len { let x = a [i] ; result [i] = if x < - 30.0 { - 1.0 } else if x > 30.0 { 1.0 } else { let exp_2x = (2.0 * x) . exp () ; (exp_2x - 1.0) / (exp_2x + 1.0) } ; i += 1 ; } } } . self_ty`
- **Function**: `tests::test_sse2_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_scale_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_clamp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_fma_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_lerp_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sum_kahan_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_norm_l1_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_norm_l2_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_dot_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_add_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_sum_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_max_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
- **Function**: `tests::test_sse2_tanh_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(33)] [tdg: 2.5]
### ./src/backends/wasm.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `WasmBackend` [fields: 0]
- **Impl**: `VectorBackend` for `impl VectorBackend for WasmBackend { # [target_feature (enable = "simd128")] unsafe fn add (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_add (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] + b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn sub (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_sub (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] - b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn mul (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_mul (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] * b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn div (a : & [f32] , b : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_div (va , vb) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } for j in i .. len { result [j] = a [j] / b [j] ; } } # [target_feature (enable = "simd128")] unsafe fn dot (a : & [f32] , b : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let prod = f32x4_mul (va , vb) ; acc = f32x4_add (acc , prod) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (acc) + f32x4_extract_lane :: < 1 > (acc) + f32x4_extract_lane :: < 2 > (acc) + f32x4_extract_lane :: < 3 > (acc) ; result += a [i ..] . iter () . zip (& b [i ..]) . map (| (x , y) | x * y) . sum :: < f32 > () ; result } # [target_feature (enable = "simd128")] unsafe fn sum (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut acc = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; acc = f32x4_add (acc , va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (acc) + f32x4_extract_lane :: < 1 > (acc) + f32x4_extract_lane :: < 2 > (acc) + f32x4_extract_lane :: < 3 > (acc) ; result += a [i ..] . iter () . sum :: < f32 > () ; result } # [target_feature (enable = "simd128")] unsafe fn max (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmax = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmax = f32x4_max (vmax , va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (vmax) . max (f32x4_extract_lane :: < 1 > (vmax)) . max (f32x4_extract_lane :: < 2 > (vmax)) . max (f32x4_extract_lane :: < 3 > (vmax)) ; for & val in & a [i ..] { if val > result { result = val ; } } result } # [target_feature (enable = "simd128")] unsafe fn min (a : & [f32]) -> f32 { let len = a . len () ; let mut i = 0 ; let mut vmin = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmin = f32x4_min (vmin , va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (vmin) . min (f32x4_extract_lane :: < 1 > (vmin)) . min (f32x4_extract_lane :: < 2 > (vmin)) . min (f32x4_extract_lane :: < 3 > (vmin)) ; for & val in & a [i ..] { if val < result { result = val ; } } result } # [target_feature (enable = "simd128")] unsafe fn argmax (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut max_value = a [0] ; let mut max_index = 0 ; let mut vmax = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmax = f32x4_max (vmax , va) ; i += 4 ; } for (idx , & val) in a [.. i] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val > max_value { max_value = val ; max_index = i + idx ; } } max_index } # [target_feature (enable = "simd128")] unsafe fn argmin (a : & [f32]) -> usize { let len = a . len () ; let mut i = 0 ; let mut min_value = a [0] ; let mut min_index = 0 ; let mut vmin = f32x4_splat (a [0]) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; vmin = f32x4_min (vmin , va) ; i += 4 ; } for (idx , & val) in a [.. i] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = idx ; } } for (idx , & val) in a [i ..] . iter () . enumerate () { if val < min_value { min_value = val ; min_index = i + idx ; } } min_index } unsafe fn sum_kahan (a : & [f32]) -> f32 { super :: scalar :: ScalarBackend :: sum_kahan (a) } # [target_feature (enable = "simd128")] unsafe fn norm_l2 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let sum_of_squares = Self :: dot (a , a) ; sum_of_squares . sqrt () } # [target_feature (enable = "simd128")] unsafe fn norm_l1 (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut acc = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let abs_va = f32x4_abs (va) ; acc = f32x4_add (acc , abs_va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (acc) + f32x4_extract_lane :: < 1 > (acc) + f32x4_extract_lane :: < 2 > (acc) + f32x4_extract_lane :: < 3 > (acc) ; for & val in & a [i ..] { result += val . abs () ; } result } # [target_feature (enable = "simd128")] unsafe fn norm_linf (a : & [f32]) -> f32 { if a . is_empty () { return 0.0 ; } let len = a . len () ; let mut i = 0 ; let mut vmax = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let abs_va = f32x4_abs (va) ; vmax = f32x4_max (vmax , abs_va) ; i += 4 ; } let mut result = f32x4_extract_lane :: < 0 > (vmax) . max (f32x4_extract_lane :: < 1 > (vmax)) . max (f32x4_extract_lane :: < 2 > (vmax)) . max (f32x4_extract_lane :: < 3 > (vmax)) ; for & val in & a [i ..] { let abs_val = val . abs () ; if abs_val > result { result = abs_val ; } } result } # [target_feature (enable = "simd128")] unsafe fn abs (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_abs (va) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] . abs () ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn exp (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let half = f32x4_splat (0.5) ; let one = f32x4_splat (1.0) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; let exp_hi = f32x4_splat (88.376_26) ; let exp_lo = f32x4_splat (- 87.336_55) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let x = f32x4_pmin (f32x4_pmax (x , exp_lo) , exp_hi) ; let x_scaled = f32x4_mul (x , log2e) ; let k = f32x4_floor (f32x4_add (x_scaled , half)) ; let r = f32x4_sub (x , f32x4_mul (k , ln2)) ; let mut p = c6 ; p = f32x4_add (f32x4_mul (p , r) , c5) ; p = f32x4_add (f32x4_mul (p , r) , c4) ; p = f32x4_add (f32x4_mul (p , r) , c3) ; p = f32x4_add (f32x4_mul (p , r) , c2) ; p = f32x4_add (f32x4_mul (p , r) , c1) ; p = f32x4_add (f32x4_mul (p , r) , one) ; let k_int = i32x4_trunc_sat_f32x4 (k) ; let k_shifted = i32x4_shl (k_int , 23) ; let one_bits = i32x4_splat (0x3f80_0000_i32) ; let scale = v128_bitselect (i32x4_add (one_bits , k_shifted) , one_bits , i32x4_ne (k_int , i32x4_splat (0)) ,) ; let scale = i32x4_add (one_bits , k_shifted) ; let vresult = f32x4_mul (p , scale) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] . exp () ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn scale (a : & [f32] , scalar : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let scalar_vec = f32x4_splat (scalar) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_mul (va , scalar_vec) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * scalar ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn clamp (a : & [f32] , min_val : f32 , max_val : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let min_vec = f32x4_splat (min_val) ; let max_vec = f32x4_splat (max_val) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let clamped = f32x4_pmin (f32x4_pmax (va , min_vec) , max_vec) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , clamped) ; i += 4 ; } while i < len { result [i] = a [i] . max (min_val) . min (max_val) ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn lerp (a : & [f32] , b : & [f32] , t : f32 , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let t_vec = f32x4_splat (t) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let diff = f32x4_sub (vb , va) ; let scaled_diff = f32x4_mul (t_vec , diff) ; let vresult = f32x4_add (va , scaled_diff) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] + t * (b [i] - a [i]) ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn fma (a : & [f32] , b : & [f32] , c : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vb = v128_load (b . as_ptr () . add (i) as * const v128) ; let vc = v128_load (c . as_ptr () . add (i) as * const v128) ; let product = f32x4_mul (va , vb) ; let vresult = f32x4_add (product , vc) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = a [i] * b [i] + c [i] ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn relu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let zero = f32x4_splat (0.0) ; while i + 4 <= len { let va = v128_load (a . as_ptr () . add (i) as * const v128) ; let vresult = f32x4_max (zero , va) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , vresult) ; i += 4 ; } while i < len { result [i] = if a [i] > 0.0 { a [i] } else { 0.0 } ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn sigmoid (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let one = f32x4_splat (1.0) ; let half = f32x4_splat (0.5) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let neg_x = f32x4_sub (f32x4_splat (0.0) , x) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (neg_x , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (neg_x , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_neg_x = f32x4_mul (poly , k_shifted) ; let sigmoid_result = f32x4_div (one , f32x4_add (one , exp_neg_x)) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , sigmoid_result) ; i += 4 ; } while i < len { let val = a [i] ; result [i] = if val < - 50.0 { 0.0 } else if val > 50.0 { 1.0 } else { 1.0 / (1.0 + (- val) . exp ()) } ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn gelu (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let sqrt_2_over_pi = f32x4_splat (0.797_884_6) ; let coeff = f32x4_splat (0.044715) ; let half = f32x4_splat (0.5) ; let one = f32x4_splat (1.0) ; let two = f32x4_splat (2.0) ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let x2 = f32x4_mul (x , x) ; let x3 = f32x4_mul (x2 , x) ; let inner = f32x4_mul (sqrt_2_over_pi , f32x4_add (x , f32x4_mul (coeff , x3))) ; let z = f32x4_mul (two , inner) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (z , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (z , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_2z = f32x4_mul (poly , k_shifted) ; let tanh_val = f32x4_div (f32x4_sub (exp_2z , one) , f32x4_add (exp_2z , one)) ; let gelu_result = f32x4_mul (half , f32x4_mul (x , f32x4_add (one , tanh_val))) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , gelu_result) ; i += 4 ; } while i < len { let x = a [i] ; let x3 = x * x * x ; let inner = 0.797_884_6 * (x + 0.044715 * x3) ; result [i] = 0.5 * x * (1.0 + inner . tanh ()) ; i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn swish (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let one = f32x4_splat (1.0) ; let half = f32x4_splat (0.5) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let neg_x = f32x4_sub (f32x4_splat (0.0) , x) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (neg_x , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (neg_x , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_neg_x = f32x4_mul (poly , k_shifted) ; let swish_result = f32x4_div (x , f32x4_add (one , exp_neg_x)) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , swish_result) ; i += 4 ; } while i < len { let x = a [i] ; if x < - 50.0 { result [i] = 0.0 ; } else if x > 50.0 { result [i] = x ; } else { let sigmoid = 1.0 / (1.0 + (- x) . exp ()) ; result [i] = x * sigmoid ; } i += 1 ; } } # [target_feature (enable = "simd128")] unsafe fn tanh (a : & [f32] , result : & mut [f32]) { let len = a . len () ; let mut i = 0 ; let log2e = f32x4_splat (std :: f32 :: consts :: LOG2_E) ; let ln2 = f32x4_splat (std :: f32 :: consts :: LN_2) ; let one = f32x4_splat (1.0) ; let two = f32x4_splat (2.0) ; let half = f32x4_splat (0.5) ; let c1 = f32x4_splat (1.0) ; let c2 = f32x4_splat (0.5) ; let c3 = f32x4_splat (0.166_666_67) ; let c4 = f32x4_splat (0.041_666_668) ; let c5 = f32x4_splat (0.008_333_334) ; let c6 = f32x4_splat (0.001_388_889) ; while i + 4 <= len { let x = v128_load (a . as_ptr () . add (i) as * const v128) ; let two_x = f32x4_mul (two , x) ; let kf = f32x4_floor (f32x4_add (f32x4_mul (two_x , log2e) , half)) ; let k = i32x4_trunc_sat_f32x4 (kf) ; let r = f32x4_sub (two_x , f32x4_mul (kf , ln2)) ; let mut poly = f32x4_add (c5 , f32x4_mul (r , c6)) ; poly = f32x4_add (c4 , f32x4_mul (r , poly)) ; poly = f32x4_add (c3 , f32x4_mul (r , poly)) ; poly = f32x4_add (c2 , f32x4_mul (r , poly)) ; poly = f32x4_add (c1 , f32x4_mul (r , poly)) ; poly = f32x4_add (one , f32x4_mul (r , poly)) ; let k_shifted = i32x4_shl (i32x4_add (k , i32x4_splat (127)) , 23) ; let exp_2x = f32x4_mul (poly , k_shifted) ; let numerator = f32x4_sub (exp_2x , one) ; let denominator = f32x4_add (exp_2x , one) ; let tanh_result = f32x4_div (numerator , denominator) ; v128_store (result . as_mut_ptr () . add (i) as * mut v128 , tanh_result) ; i += 4 ; } while i < len { result [i] = a [i] . tanh () ; i += 1 ; } } } . self_ty`
- **Function**: `tests::test_wasm_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_sub_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_mul_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_div_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_min_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_argmax_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_argmin_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_relu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_sigmoid_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_gelu_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_swish_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
- **Function**: `tests::test_wasm_tanh_matches_scalar` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(23)] [tdg: 2.5]
### ./src/chaos.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `ChaosConfig` [fields: 4]
- **Impl**: `Default` for `impl Default for ChaosConfig { fn default () -> Self { Self { memory_limit : 0 , cpu_limit : 0.0 , timeout : Duration :: from_secs (60) , signal_injection : false , } } } . self_ty`
- **Impl**: `impl ChaosConfig { # [doc = " Create a new chaos configuration with default values (no limits)"] pub fn new () -> Self { Self :: default () } # [doc = " Set memory limit in bytes"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = ""] # [doc = " let config = ChaosConfig::new()"] # [doc = " .with_memory_limit(512 * 1024 * 1024); // 512 MB"] # [doc = " assert_eq!(config.memory_limit, 512 * 1024 * 1024);"] # [doc = " ```"] pub fn with_memory_limit (mut self , bytes : usize) -> Self { self . memory_limit = bytes ; self } # [doc = " Set CPU usage limit as fraction (0.0-1.0)"] # [doc = ""] # [doc = " Values are automatically clamped to valid range."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = ""] # [doc = " let config = ChaosConfig::new().with_cpu_limit(0.75);"] # [doc = " assert_eq!(config.cpu_limit, 0.75);"] # [doc = ""] # [doc = " // Values outside range are clamped"] # [doc = " let clamped = ChaosConfig::new().with_cpu_limit(1.5);"] # [doc = " assert_eq!(clamped.cpu_limit, 1.0);"] # [doc = " ```"] pub fn with_cpu_limit (mut self , fraction : f64) -> Self { self . cpu_limit = fraction . clamp (0.0 , 1.0) ; self } # [doc = " Set maximum execution timeout"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = " use std::time::Duration;"] # [doc = ""] # [doc = " let config = ChaosConfig::new()"] # [doc = " .with_timeout(Duration::from_secs(30));"] # [doc = " assert_eq!(config.timeout, Duration::from_secs(30));"] # [doc = " ```"] pub fn with_timeout (mut self , timeout : Duration) -> Self { self . timeout = timeout ; self } # [doc = " Enable/disable random signal injection during execution"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = ""] # [doc = " let config = ChaosConfig::new().with_signal_injection(true);"] # [doc = " assert!(config.signal_injection);"] # [doc = " ```"] pub fn with_signal_injection (mut self , enabled : bool) -> Self { self . signal_injection = enabled ; self } # [doc = " Finalize configuration (no-op, for builder pattern consistency)"] pub fn build (self) -> Self { self } # [doc = " Gentle chaos configuration preset"] # [doc = ""] # [doc = " - 512 MB memory limit"] # [doc = " - 80% CPU limit"] # [doc = " - 120 second timeout"] # [doc = " - No signal injection"] # [doc = ""] # [doc = " Suitable for gradual stress testing and CI environments."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = " use std::time::Duration;"] # [doc = ""] # [doc = " let config = ChaosConfig::gentle();"] # [doc = " assert_eq!(config.memory_limit, 512 * 1024 * 1024);"] # [doc = " assert_eq!(config.cpu_limit, 0.8);"] # [doc = " assert_eq!(config.timeout, Duration::from_secs(120));"] # [doc = " assert!(!config.signal_injection);"] # [doc = " ```"] pub fn gentle () -> Self { Self :: new () . with_memory_limit (512 * 1024 * 1024) . with_cpu_limit (0.8) . with_timeout (Duration :: from_secs (120)) } # [doc = " Aggressive chaos configuration preset"] # [doc = ""] # [doc = " - 64 MB memory limit"] # [doc = " - 25% CPU limit"] # [doc = " - 10 second timeout"] # [doc = " - Signal injection enabled"] # [doc = ""] # [doc = " Suitable for extreme stress testing and finding edge cases."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::chaos::ChaosConfig;"] # [doc = " use std::time::Duration;"] # [doc = ""] # [doc = " let config = ChaosConfig::aggressive();"] # [doc = " assert_eq!(config.memory_limit, 64 * 1024 * 1024);"] # [doc = " assert_eq!(config.cpu_limit, 0.25);"] # [doc = " assert_eq!(config.timeout, Duration::from_secs(10));"] # [doc = " assert!(config.signal_injection);"] # [doc = " ```"] pub fn aggressive () -> Self { Self :: new () . with_memory_limit (64 * 1024 * 1024) . with_cpu_limit (0.25) . with_timeout (Duration :: from_secs (10)) . with_signal_injection (true) } } . self_ty`
- **Enum**: `ChaosError` [variants: 3]
- **Impl**: `std :: fmt :: Display` for `impl std :: fmt :: Display for ChaosError { fn fmt (& self , f : & mut std :: fmt :: Formatter < '_ >) -> std :: fmt :: Result { match self { ChaosError :: MemoryLimitExceeded { limit , used } => { write ! (f , "Memory limit exceeded: {} > {} bytes" , used , limit) } ChaosError :: Timeout { elapsed , limit } => { write ! (f , "Timeout: {:?} > {:?}" , elapsed , limit) } ChaosError :: SignalInjectionFailed { signal , reason } => { write ! (f , "Signal injection failed ({}): {}" , signal , reason) } } } } . self_ty`
- **Impl**: `std :: error :: Error` for `impl std :: error :: Error for ChaosError { } . self_ty`
- **Function**: `tests::test_default_config` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_builder_pattern` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_cpu_limit_clamping` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_gentle_preset` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_aggressive_preset` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
- **Function**: `tests::test_chaos_error_display` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
### ./src/error.rs
**File Complexity**: 1 | **Functions**: 0
- **Enum**: `TruenoError` [variants: 6]
- **Function**: `tests::test_unsupported_backend_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_size_mismatch_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_gpu_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_invalid_input_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_error_equality` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_division_by_zero_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
- **Function**: `tests::test_empty_vector_error` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(3)] [tdg: 2.5]
### ./src/lib.rs
**File Complexity**: 2 | **Functions**: 4
- **Enum**: `Backend` [variants: 9]
- **Impl**: `impl Backend { # [doc = " Select the best available backend for the current platform"] # [doc = ""] # [doc = " This is a convenience wrapper around `select_best_available_backend()`"] pub fn select_best () -> Self { select_best_available_backend () } } . self_ty`
- **Enum**: `OpComplexity` [variants: 3]
- **Function**: `detect_x86_backend` [complexity: 6] [cognitive: 13] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `detect_arm_backend` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `detect_wasm_backend` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `select_best_available_backend` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_backend_enum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_op_complexity_ordering` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_select_best_available_backend` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
- **Function**: `tests::test_backend_selection_is_deterministic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: med(6)] [tdg: 2.5]
### ./src/matrix.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `Matrix` [fields: 4]
- **Impl**: `impl Matrix < f32 > { # [doc = " Creates a new matrix with uninitialized values"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `rows` - Number of rows"] # [doc = " * `cols` - Number of columns"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new matrix with dimensions `rows x cols` containing uninitialized values"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::new(3, 4);"] # [doc = " assert_eq!(m.rows(), 3);"] # [doc = " assert_eq!(m.cols(), 4);"] # [doc = " ```"] pub fn new (rows : usize , cols : usize) -> Self { let backend = Backend :: select_best () ; Matrix { rows , cols , data : vec ! [0.0 ; rows * cols] , backend , } } # [doc = " Creates a matrix from a vector of data"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `rows` - Number of rows"] # [doc = " * `cols` - Number of columns"] # [doc = " * `data` - Vector containing matrix elements in row-major order"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if `data.len() != rows * cols`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 2, vec![1.0, 2.0, 3.0, 4.0]).unwrap();"] # [doc = " assert_eq!(m.rows(), 2);"] # [doc = " assert_eq!(m.cols(), 2);"] # [doc = " ```"] pub fn from_vec (rows : usize , cols : usize , data : Vec < f32 >) -> Result < Self , TruenoError > { if data . len () != rows * cols { return Err (TruenoError :: InvalidInput (format ! ("Data length {} does not match matrix dimensions {}x{} (expected {})" , data . len () , rows , cols , rows * cols))) ; } let backend = Backend :: select_best () ; Ok (Matrix { rows , cols , data , backend , }) } # [doc = " Creates a matrix filled with zeros"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::zeros(3, 3);"] # [doc = " assert_eq!(m.get(1, 1), Some(&0.0));"] # [doc = " ```"] pub fn zeros (rows : usize , cols : usize) -> Self { Matrix :: new (rows , cols) } # [doc = " Creates an identity matrix (square matrix with 1s on diagonal)"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::identity(3);"] # [doc = " assert_eq!(m.get(0, 0), Some(&1.0));"] # [doc = " assert_eq!(m.get(0, 1), Some(&0.0));"] # [doc = " assert_eq!(m.get(1, 1), Some(&1.0));"] # [doc = " ```"] pub fn identity (n : usize) -> Self { let mut data = vec ! [0.0 ; n * n] ; for i in 0 .. n { data [i * n + i] = 1.0 ; } let backend = Backend :: select_best () ; Matrix { rows : n , cols : n , data , backend , } } # [doc = " Returns the number of rows"] pub fn rows (& self) -> usize { self . rows } # [doc = " Returns the number of columns"] pub fn cols (& self) -> usize { self . cols } # [doc = " Returns the shape as (rows, cols)"] pub fn shape (& self) -> (usize , usize) { (self . rows , self . cols) } # [doc = " Gets a reference to an element at (row, col)"] # [doc = ""] # [doc = " Returns `None` if indices are out of bounds"] pub fn get (& self , row : usize , col : usize) -> Option < & f32 > { if row >= self . rows || col >= self . cols { None } else { self . data . get (row * self . cols + col) } } # [doc = " Gets a mutable reference to an element at (row, col)"] # [doc = ""] # [doc = " Returns `None` if indices are out of bounds"] pub fn get_mut (& mut self , row : usize , col : usize) -> Option < & mut f32 > { if row >= self . rows || col >= self . cols { None } else { let idx = row * self . cols + col ; self . data . get_mut (idx) } } # [doc = " Returns a reference to the underlying data"] pub fn as_slice (& self) -> & [f32] { & self . data } # [doc = " Matrix multiplication (matmul)"] # [doc = ""] # [doc = " Computes `C = A × B` where A is `m×n`, B is `n×p`, and C is `m×p`."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `other` - The matrix to multiply with (right operand)"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new matrix containing the result of matrix multiplication"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if matrix dimensions are incompatible"] # [doc = " (i.e., `self.cols != other.rows`)"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let a = Matrix::from_vec(2, 2, vec![1.0, 2.0, 3.0, 4.0]).unwrap();"] # [doc = " let b = Matrix::from_vec(2, 2, vec![5.0, 6.0, 7.0, 8.0]).unwrap();"] # [doc = " let c = a.matmul(&b).unwrap();"] # [doc = ""] # [doc = " // [[1, 2], [[5, 6], [[19, 22],"] # [doc = " // [3, 4]] × [7, 8]] = [43, 50]]"] # [doc = " assert_eq!(c.get(0, 0), Some(&19.0));"] # [doc = " assert_eq!(c.get(0, 1), Some(&22.0));"] # [doc = " assert_eq!(c.get(1, 0), Some(&43.0));"] # [doc = " assert_eq!(c.get(1, 1), Some(&50.0));"] # [doc = " ```"] pub fn matmul (& self , other : & Matrix < f32 >) -> Result < Matrix < f32 > , TruenoError > { if self . cols != other . rows { return Err (TruenoError :: InvalidInput (format ! ("Matrix dimension mismatch for multiplication: {}×{} × {}×{} (inner dimensions {} and {} must match)" , self . rows , self . cols , other . rows , other . cols , self . cols , other . rows))) ; } let mut result = Matrix :: zeros (self . rows , other . cols) ; # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = 500 ; const SIMD_THRESHOLD : usize = 64 ; # [cfg (feature = "gpu")] { if self . rows >= GPU_THRESHOLD && self . cols >= GPU_THRESHOLD && other . cols >= GPU_THRESHOLD { if let Ok (gpu_result) = self . matmul_gpu (other) { return Ok (gpu_result) ; } } } if self . rows >= SIMD_THRESHOLD || self . cols >= SIMD_THRESHOLD || other . cols >= SIMD_THRESHOLD { self . matmul_simd (other , & mut result) ? ; } else { self . matmul_naive (other , & mut result) ? ; } Ok (result) } # [doc = " Naive O(n³) matrix multiplication (baseline for small matrices)"] fn matmul_naive (& self , other : & Matrix < f32 > , result : & mut Matrix < f32 > ,) -> Result < () , TruenoError > { for i in 0 .. self . rows { for j in 0 .. other . cols { let mut sum = 0.0 ; for k in 0 .. self . cols { sum += self . get (i , k) . unwrap () * other . get (k , j) . unwrap () ; } * result . get_mut (i , j) . unwrap () = sum ; } } Ok (()) } # [doc = " SIMD-optimized matrix multiplication using Vector operations"] fn matmul_simd (& self , other : & Matrix < f32 > , result : & mut Matrix < f32 > ,) -> Result < () , TruenoError > { let b_transposed = other . transpose () ; for i in 0 .. self . rows { let row_start = i * self . cols ; let row_end = row_start + self . cols ; let a_row = & self . data [row_start .. row_end] ; let a_vec = Vector :: from_slice (a_row) ; for j in 0 .. other . cols { let col_start = j * b_transposed . cols ; let col_end = col_start + b_transposed . cols ; let b_col = & b_transposed . data [col_start .. col_end] ; let b_vec = Vector :: from_slice (b_col) ; let dot_result = a_vec . dot (& b_vec) ? ; * result . get_mut (i , j) . unwrap () = dot_result ; } } Ok (()) } # [doc = " GPU-accelerated matrix multiplication (very large matrices only)"] # [cfg (feature = "gpu")] fn matmul_gpu (& self , other : & Matrix < f32 >) -> Result < Matrix < f32 > , TruenoError > { use crate :: backends :: gpu :: GpuBackend ; if ! GpuBackend :: is_available () { return Err (TruenoError :: InvalidInput ("GPU not available" . to_string ())) ; } let mut gpu = GpuBackend :: new () ; let result_data = gpu . matmul (& self . data , & other . data , self . rows , self . cols , other . cols) . map_err (| e | TruenoError :: InvalidInput (format ! ("GPU matmul failed: {}" , e))) ? ; let mut result = Matrix :: zeros (self . rows , other . cols) ; result . data = result_data ; Ok (result) } # [doc = " Transpose the matrix (swap rows and columns)"] # [doc = ""] # [doc = " Returns a new matrix where element `(i, j)` of the original becomes"] # [doc = " element `(j, i)` in the result."] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new matrix with dimensions swapped: if input is `m×n`, output is `n×m`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).unwrap();"] # [doc = " let t = m.transpose();"] # [doc = ""] # [doc = " // [[1, 2, 3], [[1, 4],"] # [doc = " // [4, 5, 6]] → [2, 5],"] # [doc = " // [3, 6]]"] # [doc = " assert_eq!(t.rows(), 3);"] # [doc = " assert_eq!(t.cols(), 2);"] # [doc = " assert_eq!(t.get(0, 0), Some(&1.0));"] # [doc = " assert_eq!(t.get(0, 1), Some(&4.0));"] # [doc = " assert_eq!(t.get(1, 0), Some(&2.0));"] # [doc = " ```"] pub fn transpose (& self) -> Matrix < f32 > { let mut result = Matrix :: zeros (self . cols , self . rows) ; for i in 0 .. self . rows { for j in 0 .. self . cols { * result . get_mut (j , i) . unwrap () = * self . get (i , j) . unwrap () ; } } result } # [doc = " Matrix-vector multiplication (column vector): A × v"] # [doc = ""] # [doc = " Multiplies this matrix by a column vector, computing `A × v` where the result"] # [doc = " is a column vector with length equal to the number of rows in `A`."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " For an m×n matrix A and an n-dimensional vector v:"] # [doc = " ```text"] # [doc = " result[i] = Σ(j=0 to n-1) A[i,j] × v[j]"] # [doc = " ```"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `v` - Column vector with length equal to `self.cols()`"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector with length `self.rows()`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if `v.len() != self.cols()`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Matrix, Vector};"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).unwrap();"] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = m.matvec(&v).unwrap();"] # [doc = ""] # [doc = " // [[1, 2, 3] [1] [1×1 + 2×2 + 3×3] [14]"] # [doc = " // [4, 5, 6]] × [2] = [4×1 + 5×2 + 6×3] = [32]"] # [doc = " // [3]"] # [doc = " assert_eq!(result.as_slice(), &[14.0, 32.0]);"] # [doc = " ```"] pub fn matvec (& self , v : & Vector < f32 >) -> Result < Vector < f32 > , TruenoError > { if v . len () != self . cols { return Err (TruenoError :: InvalidInput (format ! ("Vector length {} does not match matrix columns {} for matrix-vector multiplication" , v . len () , self . cols))) ; } let mut result_data = vec ! [0.0 ; self . rows] ; for (i , result_elem) in result_data . iter_mut () . enumerate () { let mut sum = 0.0 ; for j in 0 .. self . cols { sum += self . get (i , j) . unwrap () * v . as_slice () [j] ; } * result_elem = sum ; } Ok (Vector :: from_slice (& result_data)) } # [doc = " Vector-matrix multiplication (row vector): v^T × A"] # [doc = ""] # [doc = " Multiplies a row vector by this matrix, computing `v^T × A` where the result"] # [doc = " is a row vector with length equal to the number of columns in `A`."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " For an m-dimensional vector v and an m×n matrix A:"] # [doc = " ```text"] # [doc = " result[j] = Σ(i=0 to m-1) v[i] × A[i,j]"] # [doc = " ```"] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `v` - Row vector with length equal to `m.rows()`"] # [doc = " * `m` - Matrix to multiply"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector with length `m.cols()`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if `v.len() != m.rows()`"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Matrix, Vector};"] # [doc = ""] # [doc = " let m = Matrix::from_vec(2, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).unwrap();"] # [doc = " let v = Vector::from_slice(&[1.0, 2.0]);"] # [doc = " let result = Matrix::vecmat(&v, &m).unwrap();"] # [doc = ""] # [doc = " // [1, 2] × [[1, 2, 3] = [1×1 + 2×4, 1×2 + 2×5, 1×3 + 2×6]"] # [doc = " // [4, 5, 6]]"] # [doc = " // = [9, 12, 15]"] # [doc = " assert_eq!(result.as_slice(), &[9.0, 12.0, 15.0]);"] # [doc = " ```"] pub fn vecmat (v : & Vector < f32 > , m : & Matrix < f32 >) -> Result < Vector < f32 > , TruenoError > { if v . len () != m . rows { return Err (TruenoError :: InvalidInput (format ! ("Vector length {} does not match matrix rows {} for vector-matrix multiplication" , v . len () , m . rows))) ; } let mut result_data = vec ! [0.0 ; m . cols] ; for (j , result_elem) in result_data . iter_mut () . enumerate () { let mut sum = 0.0 ; for i in 0 .. m . rows { sum += v . as_slice () [i] * m . get (i , j) . unwrap () ; } * result_elem = sum ; } Ok (Vector :: from_slice (& result_data)) } # [doc = " Perform 2D convolution with a kernel"] # [doc = ""] # [doc = " Applies a 2D convolution operation using \"valid\" padding (no padding),"] # [doc = " resulting in an output smaller than the input."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `kernel` - Convolution kernel (filter) to apply"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " Convolved matrix with dimensions:"] # [doc = " - rows: `input.rows - kernel.rows + 1`"] # [doc = " - cols: `input.cols - kernel.cols + 1`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if:"] # [doc = " - Kernel is larger than input in any dimension"] # [doc = " - Kernel has even dimensions (center pixel ambiguous)"] # [doc = ""] # [doc = " # Example"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Matrix;"] # [doc = ""] # [doc = " // 5x5 input image"] # [doc = " let input = Matrix::from_vec("] # [doc = " 5, 5,"] # [doc = " vec!["] # [doc = " 0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = " 0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = " 0.0, 0.0, 9.0, 0.0, 0.0,"] # [doc = " 0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = " 0.0, 0.0, 0.0, 0.0, 0.0,"] # [doc = " ]"] # [doc = " ).unwrap();"] # [doc = ""] # [doc = " // 3x3 averaging kernel"] # [doc = " let kernel_val = 1.0 / 9.0;"] # [doc = " let kernel = Matrix::from_vec("] # [doc = " 3, 3,"] # [doc = " vec![kernel_val; 9]"] # [doc = " ).unwrap();"] # [doc = ""] # [doc = " let result = input.convolve2d(&kernel).unwrap();"] # [doc = " assert_eq!(result.rows(), 3); // 5 - 3 + 1"] # [doc = " assert_eq!(result.cols(), 3);"] # [doc = " ```"] pub fn convolve2d (& self , kernel : & Matrix < f32 >) -> Result < Matrix < f32 > , TruenoError > { if kernel . rows > self . rows || kernel . cols > self . cols { return Err (TruenoError :: InvalidInput (format ! ("Kernel size ({}x{}) larger than input ({}x{})" , kernel . rows , kernel . cols , self . rows , self . cols))) ; } let output_rows = self . rows - kernel . rows + 1 ; let output_cols = self . cols - kernel . cols + 1 ; let mut result = Matrix :: zeros (output_rows , output_cols) ; # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = 10_000 ; # [cfg (feature = "gpu")] { if output_rows * output_cols >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuBackend ; if GpuBackend :: is_available () { if let Ok (gpu_result) = self . convolve2d_gpu (kernel , & mut result , output_rows , output_cols) { return Ok (gpu_result) ; } } } } for out_row in 0 .. output_rows { for out_col in 0 .. output_cols { let mut sum = 0.0 ; for k_row in 0 .. kernel . rows { for k_col in 0 .. kernel . cols { let in_row = out_row + k_row ; let in_col = out_col + k_col ; let input_val = self . get (in_row , in_col) . unwrap () ; let kernel_val = kernel . get (k_row , k_col) . unwrap () ; sum += input_val * kernel_val ; } } * result . get_mut (out_row , out_col) . unwrap () = sum ; } } Ok (result) } # [doc = " GPU-accelerated 2D convolution helper"] # [cfg (feature = "gpu")] fn convolve2d_gpu (& self , kernel : & Matrix < f32 > , result : & mut Matrix < f32 > , _output_rows : usize , _output_cols : usize ,) -> Result < Matrix < f32 > , TruenoError > { use crate :: backends :: gpu :: GpuDevice ; let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; gpu . convolve2d (self . as_slice () , kernel . as_slice () , result . data . as_mut_slice () , self . rows , self . cols , kernel . rows , kernel . cols ,) . map_err (TruenoError :: InvalidInput) ? ; Ok (result . clone ()) } } . self_ty`
- **Function**: `tests::test_matrix_new` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_from_vec` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_from_vec_invalid_size` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matrix_get_out_of_bounds` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_dimension_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_non_square` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_simd_equivalence_small` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_simd_equivalence_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_matmul_simd_equivalence_rectangular` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_gpu_availability` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_gpu_matmul_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_square` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_single_row` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_single_col` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `tests::test_transpose_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::matrix_strategy` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_dimension_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_identity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_dimension_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_vecmat_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_matvec_transpose_equivalence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_basic_3x3` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_edge_detection` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_averaging_filter` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
- **Function**: `property_tests::test_convolve2d_invalid_kernel` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(13)] [tdg: 2.5]
### ./src/vector.rs
**File Complexity**: 1 | **Functions**: 0
- **Struct**: `Vector` [fields: 2]
- **Impl**: `impl < T > Vector < T > where T : Clone , { # [doc = " Create vector from slice using auto-selected optimal backend"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Auto-selects the best available backend at creation time based on:"] # [doc = " - CPU feature detection (AVX-512 > AVX2 > AVX > SSE2)"] # [doc = " - Vector size (GPU for large workloads)"] # [doc = " - Platform availability (NEON on ARM, WASM SIMD in browser)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " assert_eq!(v.len(), 4);"] # [doc = " ```"] pub fn from_slice (data : & [T]) -> Self { Self { data : data . to_vec () , backend : crate :: select_best_available_backend () , } } # [doc = " Create vector with specific backend (for benchmarking or testing)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, Backend};"] # [doc = ""] # [doc = " let v = Vector::from_slice_with_backend(&[1.0, 2.0], Backend::Scalar);"] # [doc = " assert_eq!(v.len(), 2);"] # [doc = " ```"] pub fn from_slice_with_backend (data : & [T] , backend : Backend) -> Self { let resolved_backend = match backend { Backend :: Auto => crate :: select_best_available_backend () , _ => backend , } ; Self { data : data . to_vec () , backend : resolved_backend , } } } . self_ty`
- **Impl**: `impl Vector < f32 > { # [doc = " Create vector with specified alignment for optimal SIMD performance"] # [doc = ""] # [doc = " This method attempts to create a vector with memory aligned to the specified byte boundary."] # [doc = " Note: Rust's Vec allocator may already provide sufficient alignment for most use cases."] # [doc = " This method validates the alignment requirement but uses standard Vec allocation."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `size` - Number of elements to allocate"] # [doc = " * `backend` - Backend to use for operations"] # [doc = " * `alignment` - Requested alignment in bytes (must be power of 2: 16, 32, 64)"] # [doc = ""] # [doc = " # Recommended Alignments"] # [doc = ""] # [doc = " - SSE2: 16 bytes (128-bit)"] # [doc = " - AVX2: 32 bytes (256-bit)"] # [doc = " - AVX-512: 64 bytes (512-bit)"] # [doc = ""] # [doc = " # Note on Implementation"] # [doc = ""] # [doc = " Currently uses Rust's default Vec allocator, which typically provides 16-byte alignment"] # [doc = " on modern systems. Custom allocators for specific alignments will be added in future versions."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, Backend};"] # [doc = ""] # [doc = " // Create vector with requested 16-byte alignment"] # [doc = " let v = Vector::with_alignment(100, Backend::SSE2, 16).unwrap();"] # [doc = " assert_eq!(v.len(), 100);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `TruenoError::InvalidInput` if alignment is not a power of 2."] pub fn with_alignment (size : usize , backend : Backend , alignment : usize) -> Result < Self > { if alignment == 0 || (alignment & (alignment - 1)) != 0 { return Err (TruenoError :: InvalidInput (format ! ("Alignment must be power of 2, got {}" , alignment))) ; } let resolved_backend = match backend { Backend :: Auto => crate :: select_best_available_backend () , _ => backend , } ; let data = vec ! [0.0f32 ; size] ; let ptr = data . as_ptr () as usize ; let actual_alignment = ptr & ! (ptr - 1) ; if alignment > actual_alignment { eprintln ! ("Note: Requested {}-byte alignment, got {}-byte alignment. Using unaligned loads." , alignment , actual_alignment) ; } Ok (Self { data , backend : resolved_backend , }) } } . self_ty`
- **Impl**: `impl < T > Vector < T > where T : Clone , { # [doc = " Get underlying data as slice"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " assert_eq!(v.as_slice(), &[1.0, 2.0, 3.0]);"] # [doc = " ```"] pub fn as_slice (& self) -> & [T] { & self . data } # [doc = " Get vector length"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " assert_eq!(v.len(), 5);"] # [doc = " ```"] pub fn len (& self) -> usize { self . data . len () } # [doc = " Check if vector is empty"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v1: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(v1.is_empty());"] # [doc = ""] # [doc = " let v2 = Vector::from_slice(&[1.0]);"] # [doc = " assert!(!v2.is_empty());"] # [doc = " ```"] pub fn is_empty (& self) -> bool { self . data . is_empty () } # [doc = " Get the backend being used"] pub fn backend (& self) -> Backend { self . backend } } . self_ty`
- **Impl**: `impl Vector < f32 > { # [doc = " Element-wise addition"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Auto-selects the best available backend:"] # [doc = " - **AVX2**: ~4x faster than scalar for 1K+ elements"] # [doc = " - **GPU**: ~50x faster than scalar for 10M+ elements"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[4.0, 5.0, 6.0]);"] # [doc = " let result = a.add(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[5.0, 7.0, 9.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::SizeMismatch`] if vectors have different lengths."] pub fn add (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 => { Avx2Backend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX512 => { Avx512Backend :: add (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: add (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: add (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Element-wise subtraction"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Auto-selects the best available backend:"] # [doc = " - **AVX2**: ~4x faster than scalar for 1K+ elements"] # [doc = " - **GPU**: ~50x faster than scalar for 10M+ elements"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[5.0, 7.0, 9.0]);"] # [doc = " let b = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = a.sub(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[4.0, 5.0, 6.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::SizeMismatch`] if vectors have different lengths."] pub fn sub (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: sub (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: sub (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Element-wise multiplication"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let b = Vector::from_slice(&[5.0, 6.0, 7.0]);"] # [doc = " let result = a.mul(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[10.0, 18.0, 28.0]);"] # [doc = " ```"] pub fn mul (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: mul (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: mul (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Element-wise division"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[10.0, 20.0, 30.0]);"] # [doc = " let b = Vector::from_slice(&[2.0, 4.0, 5.0]);"] # [doc = " let result = a.div(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[5.0, 5.0, 6.0]);"] # [doc = " ```"] pub fn div (& self , other : & Self) -> Result < Self > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: div (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: div (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: div (& self . data , & other . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: div (& self . data , & other . data , & mut result) ; } } } Ok (Self { data : result , backend : self . backend , }) } # [doc = " Dot product"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[4.0, 5.0, 6.0]);"] # [doc = " let result = a.dot(&b).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result, 32.0); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32"] # [doc = " ```"] pub fn dot (& self , other : & Self) -> Result < f32 > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: dot (& self . data , & other . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: dot (& self . data , & other . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 => Avx2Backend :: dot (& self . data , & other . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX512 => Avx512Backend :: dot (& self . data , & other . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: dot (& self . data , & other . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: dot (& self . data , & other . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: dot (& self . data , & other . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: dot (& self . data , & other . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: dot (& self . data , & other . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: dot (& self . data , & other . data) , } } ; Ok (result) } # [doc = " Sum all elements"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " assert_eq!(v.sum().unwrap(), 10.0);"] # [doc = " ```"] pub fn sum (& self) -> Result < f32 > { let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: sum (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: sum (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: sum (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sum (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: sum (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: sum (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: sum (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: sum (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: sum (& self . data) , } } ; Ok (result) } # [doc = " Find maximum element"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.max().unwrap(), 5.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn max (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: max (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: max (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: max (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: max (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: max (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: max (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: max (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: max (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: max (& self . data) , } } ; Ok (result) } # [doc = " Find minimum value in the vector"] # [doc = ""] # [doc = " Returns the smallest element in the vector using SIMD optimization."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.min().unwrap(), 1.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn min (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: min (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: min (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: min (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: min (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: min (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: min (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: min (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: min (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: min (& self . data) , } } ; Ok (result) } # [doc = " Find index of maximum value in the vector"] # [doc = ""] # [doc = " Returns the index of the first occurrence of the maximum value using SIMD optimization."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.argmax().unwrap(), 1); // max value 5.0 is at index 1"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn argmax (& self) -> Result < usize > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: argmax (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: argmax (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: argmax (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: argmax (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: argmax (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: argmax (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: argmax (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: argmax (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: argmax (& self . data) , } } ; Ok (result) } # [doc = " Find index of minimum value in the vector"] # [doc = ""] # [doc = " Returns the index of the first occurrence of the minimum value using SIMD optimization."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 5.0, 3.0, 2.0]);"] # [doc = " assert_eq!(v.argmin().unwrap(), 0); // min value 1.0 is at index 0"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns [`TruenoError::InvalidInput`] if vector is empty."] pub fn argmin (& self) -> Result < usize > { if self . data . is_empty () { return Err (TruenoError :: InvalidInput ("Empty vector" . to_string ())) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: argmin (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: argmin (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: argmin (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: argmin (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: argmin (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: argmin (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: argmin (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: argmin (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: argmin (& self . data) , } } ; Ok (result) } # [doc = " Kahan summation (numerically stable sum)"] # [doc = ""] # [doc = " Uses the Kahan summation algorithm to reduce floating-point rounding errors"] # [doc = " when summing many numbers. This is more accurate than the standard sum() method"] # [doc = " for vectors with many elements or elements of vastly different magnitudes."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Note: Kahan summation is inherently sequential and cannot be effectively"] # [doc = " parallelized with SIMD. All backends use the scalar implementation."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " assert_eq!(v.sum_kahan().unwrap(), 10.0);"] # [doc = " ```"] pub fn sum_kahan (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: sum_kahan (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: sum_kahan (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: sum_kahan (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sum_kahan (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: sum_kahan (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: sum_kahan (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: sum_kahan (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: sum_kahan (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: sum_kahan (& self . data) , } } ; Ok (result) } # [doc = " Sum of squared elements"] # [doc = ""] # [doc = " Computes the sum of squares: sum(a\\[i\\]^2)."] # [doc = " This is the building block for computing L2 norm and variance."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let sum_sq = v.sum_of_squares().unwrap();"] # [doc = " assert_eq!(sum_sq, 14.0); // 1^2 + 2^2 + 3^2 = 1 + 4 + 9 = 14"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns 0.0 for empty vectors."] pub fn sum_of_squares (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } self . dot (self) } # [doc = " Arithmetic mean (average)"] # [doc = ""] # [doc = " Computes the arithmetic mean of all elements: sum(a\\[i\\]) / n."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD sum() implementation, then divides by length."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " let avg = v.mean().unwrap();"] # [doc = " assert!((avg - 2.5).abs() < 1e-5); // (1+2+3+4)/4 = 2.5"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors (division by zero)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(v.mean(), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn mean (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let total = self . sum () ? ; Ok (total / self . len () as f32) } # [doc = " Population variance"] # [doc = ""] # [doc = " Computes the population variance: Var(X) = E\\[(X - μ)²\\] = E\\[X²\\] - μ²"] # [doc = " Uses the computational formula to avoid two passes over the data."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via sum_of_squares() and mean()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let var = v.variance().unwrap();"] # [doc = " assert!((var - 2.0).abs() < 1e-5); // Population variance"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(v.variance(), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn variance (& self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let mean_val = self . mean () ? ; let sum_sq = self . sum_of_squares () ? ; let mean_sq = sum_sq / self . len () as f32 ; Ok (mean_sq - mean_val * mean_val) } # [doc = " Population standard deviation"] # [doc = ""] # [doc = " Computes the population standard deviation: σ = sqrt(Var(X))."] # [doc = " This is the square root of the variance."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via variance()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let sd = v.stddev().unwrap();"] # [doc = " assert!((sd - 1.4142135).abs() < 1e-5); // sqrt(2) ≈ 1.414"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(v.stddev(), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn stddev (& self) -> Result < f32 > { let var = self . variance () ? ; Ok (var . sqrt ()) } # [doc = " Population covariance between two vectors"] # [doc = ""] # [doc = " Computes the population covariance: Cov(X,Y) = E[(X - μx)(Y - μy)]"] # [doc = " Uses the computational formula: Cov(X,Y) = E\\[XY\\] - μx·μy"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via dot() and mean()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let y = Vector::from_slice(&[2.0, 4.0, 6.0]);"] # [doc = " let cov = x.covariance(&y).unwrap();"] # [doc = " assert!((cov - 1.333).abs() < 0.01); // Perfect positive covariance"] # [doc = " ```"] # [doc = ""] # [doc = " # Size mismatch"] # [doc = ""] # [doc = " Returns an error if vectors have different lengths."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[1.0, 2.0]);"] # [doc = " let y = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " assert!(matches!(x.covariance(&y), Err(TruenoError::SizeMismatch { .. })));"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns an error for empty vectors."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let x: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " let y: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert!(matches!(x.covariance(&y), Err(TruenoError::EmptyVector)));"] # [doc = " ```"] pub fn covariance (& self , other : & Self) -> Result < f32 > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mean_x = self . mean () ? ; let mean_y = other . mean () ? ; let dot_xy = self . dot (other) ? ; let mean_xy = dot_xy / self . len () as f32 ; Ok (mean_xy - mean_x * mean_y) } # [doc = " Pearson correlation coefficient"] # [doc = ""] # [doc = " Computes the Pearson correlation coefficient: ρ(X,Y) = Cov(X,Y) / (σx·σy)"] # [doc = " Normalized covariance in range [-1, 1]."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via covariance() and stddev()."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let y = Vector::from_slice(&[2.0, 4.0, 6.0]);"] # [doc = " let corr = x.correlation(&y).unwrap();"] # [doc = " assert!((corr - 1.0).abs() < 1e-5); // Perfect positive correlation"] # [doc = " ```"] # [doc = ""] # [doc = " # Size mismatch"] # [doc = ""] # [doc = " Returns an error if vectors have different lengths."] # [doc = ""] # [doc = " # Division by zero"] # [doc = ""] # [doc = " Returns DivisionByZero error if either vector has zero standard deviation"] # [doc = " (i.e., is constant)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let x = Vector::from_slice(&[5.0, 5.0, 5.0]); // Constant"] # [doc = " let y = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " assert!(matches!(x.correlation(&y), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn correlation (& self , other : & Self) -> Result < f32 > { let cov = self . covariance (other) ? ; let std_x = self . stddev () ? ; let std_y = other . stddev () ? ; if std_x . abs () < 1e-10 || std_y . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let corr = cov / (std_x * std_y) ; Ok (corr . clamp (- 1.0 , 1.0)) } # [doc = " Z-score normalization (standardization)"] # [doc = ""] # [doc = " Transforms the vector to have mean = 0 and standard deviation = 1."] # [doc = " Each element is transformed as: z\\[i\\] = (x\\[i\\] - μ) / σ"] # [doc = ""] # [doc = " This is a fundamental preprocessing step in machine learning and statistics,"] # [doc = " ensuring features have comparable scales and are centered around zero."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via mean() and stddev(), then applies"] # [doc = " element-wise operations (sub, scale) which also use SIMD."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let z = v.zscore().unwrap();"] # [doc = ""] # [doc = " // Verify mean ≈ 0"] # [doc = " let mean = z.mean().unwrap();"] # [doc = " assert!(mean.abs() < 1e-5);"] # [doc = ""] # [doc = " // Verify stddev ≈ 1"] # [doc = " let std = z.stddev().unwrap();"] # [doc = " assert!((std - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors (cannot compute mean/stddev)."] # [doc = ""] # [doc = " # Division by zero"] # [doc = ""] # [doc = " Returns DivisionByZero error if the vector has zero standard deviation"] # [doc = " (i.e., all elements are identical/constant)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[5.0, 5.0, 5.0]); // Constant"] # [doc = " assert!(matches!(v.zscore(), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn zscore (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let mean_val = self . mean () ? ; let std_val = self . stddev () ? ; if std_val . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let inv_std = 1.0 / std_val ; let data : Vec < f32 > = self . data . iter () . map (| & x | (x - mean_val) * inv_std) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Min-max normalization (scaling to [0, 1] range)"] # [doc = ""] # [doc = " Transforms the vector so that the minimum value becomes 0 and the maximum"] # [doc = " value becomes 1, with all other values scaled proportionally."] # [doc = " Formula: x'\\[i\\] = (x\\[i\\] - min) / (max - min)"] # [doc = ""] # [doc = " This is a fundamental preprocessing technique in machine learning, especially"] # [doc = " for algorithms sensitive to feature magnitudes (e.g., neural networks, k-NN)."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via min() and max() operations, then"] # [doc = " applies element-wise transformation."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);"] # [doc = " let normalized = v.minmax_normalize().unwrap();"] # [doc = ""] # [doc = " // Verify range [0, 1]"] # [doc = " let min = normalized.min().unwrap();"] # [doc = " let max = normalized.max().unwrap();"] # [doc = " assert!((min - 0.0).abs() < 1e-5);"] # [doc = " assert!((max - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors (cannot compute min/max)."] # [doc = ""] # [doc = " # Division by zero"] # [doc = ""] # [doc = " Returns DivisionByZero error if the vector has all identical elements"] # [doc = " (i.e., min = max, causing division by zero in the normalization formula)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[5.0, 5.0, 5.0]); // Constant"] # [doc = " assert!(matches!(v.minmax_normalize(), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn minmax_normalize (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let min_val = self . min () ? ; let max_val = self . max () ? ; let range = max_val - min_val ; if range . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let inv_range = 1.0 / range ; let data : Vec < f32 > = self . data . iter () . map (| & x | (x - min_val) * inv_range) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Clip values to a specified range [min_val, max_val]"] # [doc = ""] # [doc = " Constrains each element to be within the specified range:"] # [doc = " - Values below min_val become min_val"] # [doc = " - Values above max_val become max_val"] # [doc = " - Values within range stay unchanged"] # [doc = ""] # [doc = " This is useful for outlier handling, gradient clipping in neural networks,"] # [doc = " and ensuring values stay within valid bounds."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);"] # [doc = " let clipped = v.clip(0.0, 10.0).unwrap();"] # [doc = ""] # [doc = " // Values: [-5, 0, 5, 10, 15] → [0, 0, 5, 10, 10]"] # [doc = " assert_eq!(clipped.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Invalid range"] # [doc = ""] # [doc = " Returns InvalidInput error if min_val > max_val."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = v.clip(10.0, 5.0); // min > max"] # [doc = " assert!(matches!(result, Err(TruenoError::InvalidInput(_))));"] # [doc = " ```"] pub fn clip (& self , min_val : f32 , max_val : f32) -> Result < Self > { if min_val > max_val { return Err (TruenoError :: InvalidInput (format ! ("min_val ({}) must be <= max_val ({})" , min_val , max_val))) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . clip (& self . data , & mut result , min_val , max_val) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let data : Vec < f32 > = self . data . iter () . map (| & x | x . max (min_val) . min (max_val)) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Softmax activation function"] # [doc = ""] # [doc = " Converts a vector of real values into a probability distribution."] # [doc = " Formula: softmax(x)\\[i\\] = exp(x\\[i\\] - max(x)) / sum(exp(x\\[j\\] - max(x)))"] # [doc = ""] # [doc = " Uses the numerically stable version with max subtraction to prevent overflow."] # [doc = " The output is a probability distribution: all values in [0, 1] and sum to 1."] # [doc = ""] # [doc = " This is the standard activation function for multi-class classification in neural networks."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let logits = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let probs = logits.softmax().unwrap();"] # [doc = ""] # [doc = " // Verify sum ≈ 1"] # [doc = " let sum: f32 = probs.as_slice().iter().sum();"] # [doc = " assert!((sum - 1.0).abs() < 1e-5);"] # [doc = ""] # [doc = " // Verify all values in [0, 1]"] # [doc = " for &p in probs.as_slice() {"] # [doc = " assert!(p >= 0.0 && p <= 1.0);"] # [doc = " }"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors (cannot compute softmax)."] pub fn softmax (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . softmax (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let max_val = self . max () ? ; let exp_vals : Vec < f32 > = self . data . iter () . map (| & x | (x - max_val) . exp ()) . collect () ; let sum_exp : f32 = exp_vals . iter () . sum () ; let data : Vec < f32 > = exp_vals . iter () . map (| & e | e / sum_exp) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Log-softmax activation function"] # [doc = ""] # [doc = " Computes the logarithm of the softmax function in a numerically stable way."] # [doc = " Formula: log_softmax(x)\\[i\\] = x\\[i\\] - max(x) - log(sum(exp(x\\[j\\] - max(x))))"] # [doc = ""] # [doc = " This is more numerically stable than computing log(softmax(x)) and is commonly"] # [doc = " used in neural networks for computing cross-entropy loss."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let logits = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let log_probs = logits.log_softmax().unwrap();"] # [doc = ""] # [doc = " // Verify exp(log_softmax) = softmax"] # [doc = " let probs_from_log: Vec<f32> = log_probs.as_slice().iter().map(|&x| x.exp()).collect();"] # [doc = " let sum: f32 = probs_from_log.iter().sum();"] # [doc = " assert!((sum - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns EmptyVector error for empty vectors."] pub fn log_softmax (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . log_softmax (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let max_val = self . max () ? ; let exp_vals : Vec < f32 > = self . data . iter () . map (| & x | (x - max_val) . exp ()) . collect () ; let sum_exp : f32 = exp_vals . iter () . sum () ; let log_sum_exp = sum_exp . ln () ; let data : Vec < f32 > = self . data . iter () . map (| & x | x - max_val - log_sum_exp) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " ReLU (Rectified Linear Unit) activation function"] # [doc = ""] # [doc = " Computes the element-wise ReLU: max(0, x)."] # [doc = " ReLU is one of the most widely used activation functions in neural networks."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " relu(x)[i] = max(0, x\\[i\\])"] # [doc = " = x\\[i\\] if x\\[i\\] > 0"] # [doc = " = 0 otherwise"] # [doc = " ```"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Non-linearity**: Introduces non-linearity while preserving linearity for positive values"] # [doc = " - **Sparsity**: Produces exactly zero for negative inputs (sparse activations)"] # [doc = " - **Gradient**: Derivative is 1 for positive inputs, 0 for negative (solves vanishing gradient)"] # [doc = " - **Computational efficiency**: Simple max operation, no exponentials"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Deep neural networks**: Default activation for hidden layers"] # [doc = " - **Convolutional networks**: Standard activation in CNNs"] # [doc = " - **Feature learning**: Encourages sparse representations"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is memory-bound. SIMD provides modest speedups since"] # [doc = " the computation (comparison and selection) is simpler than memory access."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.relu().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[0.0, 0.0, 0.0, 1.0, 2.0]);"] # [doc = " ```"] pub fn relu (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . relu (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: relu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: relu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: relu (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: relu (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: relu (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: relu (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: relu (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: relu (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: relu (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Sigmoid (logistic) activation function"] # [doc = ""] # [doc = " Computes the element-wise sigmoid: σ(x) = 1 / (1 + e^(-x))."] # [doc = " Sigmoid is a classic activation function that squashes inputs to the range (0, 1)."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " sigmoid(x)[i] = 1 / (1 + exp(-x\\[i\\]))"] # [doc = " = exp(x\\[i\\]) / (1 + exp(x\\[i\\]))"] # [doc = " ```"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Bounded output**: Maps all inputs to (0, 1) range"] # [doc = " - **Smooth**: Infinitely differentiable (C^∞)"] # [doc = " - **Symmetric**: σ(-x) = 1 - σ(x)"] # [doc = " - **Derivative**: σ'(x) = σ(x) * (1 - σ(x))"] # [doc = " - **Interpretable**: Output can be interpreted as probability"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Binary classification**: Final layer for binary output (0 or 1)"] # [doc = " - **Logistic regression**: Traditional ML algorithm"] # [doc = " - **Gating mechanisms**: LSTM/GRU gates (input, forget, output)"] # [doc = " - **Attention mechanisms**: Soft attention weights"] # [doc = ""] # [doc = " # Numerical Considerations"] # [doc = ""] # [doc = " For very large negative inputs (x < -50), exp(-x) overflows to infinity."] # [doc = " However, sigmoid(x) approaches 0, so we return 0 for numerical stability."] # [doc = " For very large positive inputs (x > 50), exp(-x) underflows to 0,"] # [doc = " and sigmoid(x) approaches 1."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is compute-bound due to the exp() operation. SIMD provides"] # [doc = " modest speedups, but the exponential is the bottleneck."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, 0.0, 2.0]);"] # [doc = " let result = v.sigmoid().unwrap();"] # [doc = ""] # [doc = " // sigmoid(-2) ≈ 0.119, sigmoid(0) = 0.5, sigmoid(2) ≈ 0.881"] # [doc = " assert!((result.as_slice()[0] - 0.119).abs() < 0.001);"] # [doc = " assert!((result.as_slice()[1] - 0.5).abs() < 0.001);"] # [doc = " assert!((result.as_slice()[2] - 0.881).abs() < 0.001);"] # [doc = " ```"] pub fn sigmoid (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . sigmoid (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: sigmoid (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: sigmoid (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: sigmoid (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: sigmoid (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Leaky ReLU activation function"] # [doc = ""] # [doc = " Computes the element-wise Leaky ReLU with a configurable negative slope."] # [doc = " Leaky ReLU addresses the \"dying ReLU\" problem by allowing small negative values."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " leaky_relu(x, α)[i] = max(αx\\[i\\], x\\[i\\])"] # [doc = " = x\\[i\\] if x\\[i\\] > 0"] # [doc = " = αx\\[i\\] if x\\[i\\] ≤ 0"] # [doc = " ```"] # [doc = ""] # [doc = " # Parameters"] # [doc = ""] # [doc = " - `negative_slope`: The slope for negative values (typically 0.01)"] # [doc = " - Must be in range [0.0, 1.0)"] # [doc = " - Common values: 0.01 (default), 0.1, 0.2"] # [doc = " - α = 0 reduces to standard ReLU"] # [doc = " - α = 1 reduces to identity function"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Fixes dying ReLU**: Neurons can't completely die (always has gradient)"] # [doc = " - **Non-zero gradient**: Gradient is α for negative inputs (not zero)"] # [doc = " - **Unbounded positive**: No saturation for positive values"] # [doc = " - **Parameterized**: Negative slope can be tuned or learned (PReLU)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Deep networks**: Prevents dying neurons in very deep networks"] # [doc = " - **GANs**: Often used in generator and discriminator networks"] # [doc = " - **Better gradient flow**: Helps with vanishing gradient problem"] # [doc = " - **Empirical improvements**: Often outperforms ReLU in practice"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is memory-bound (simple multiplication and comparison)."] # [doc = " SIMD provides modest speedups."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = " Returns `InvalidInput` if negative_slope is not in [0.0, 1.0)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.leaky_relu(0.01).unwrap();"] # [doc = ""] # [doc = " // Negative values multiplied by 0.01, positive unchanged"] # [doc = " assert_eq!(result.as_slice(), &[-0.02, -0.01, 0.0, 1.0, 2.0]);"] # [doc = " ```"] pub fn leaky_relu (& self , negative_slope : f32) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } if ! (0.0 .. 1.0) . contains (& negative_slope) { return Err (TruenoError :: InvalidInput (format ! ("negative_slope must be in [0.0, 1.0), got {}" , negative_slope))) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . leaky_relu (& self . data , & mut result , negative_slope) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let data : Vec < f32 > = self . data . iter () . map (| & x | if x > 0.0 { x } else { negative_slope * x }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " ELU (Exponential Linear Unit) activation function"] # [doc = ""] # [doc = " Computes the element-wise ELU with a configurable alpha parameter."] # [doc = " ELU pushes mean activations closer to zero, improving learning."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " elu(x, α)[i] = x\\[i\\] if x\\[i\\] > 0"] # [doc = " = α(e^x\\[i\\] - 1) if x\\[i\\] ≤ 0"] # [doc = " ```"] # [doc = ""] # [doc = " # Parameters"] # [doc = ""] # [doc = " - `alpha`: Controls the saturation value for negative inputs (typically 1.0)"] # [doc = " - Must be > 0"] # [doc = " - Common value: 1.0 (original ELU paper)"] # [doc = " - Larger α → slower saturation for negative inputs"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Smooth**: Unlike ReLU/Leaky ReLU, has smooth gradients everywhere"] # [doc = " - **Negative values**: Allows negative outputs (pushes mean closer to zero)"] # [doc = " - **Bounded below**: Saturates to -α for very negative inputs"] # [doc = " - **Unbounded above**: No saturation for positive values"] # [doc = " - **Non-zero gradient**: Has gradient everywhere (no dead neurons)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Deep networks**: Better gradient flow than ReLU"] # [doc = " - **Mean activation near zero**: Reduces internal covariate shift"] # [doc = " - **Noise robustness**: Smooth activation helps with noisy gradients"] # [doc = " - **Empirical improvements**: Often outperforms ReLU and Leaky ReLU"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is compute-bound due to exp() for negative values."] # [doc = " More expensive than ReLU/Leaky ReLU but provides better properties."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = " Returns `InvalidInput` if alpha <= 0."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.elu(1.0).unwrap();"] # [doc = ""] # [doc = " // Negative values: α(e^x - 1), positive unchanged"] # [doc = " // elu(-2, 1) ≈ -0.865, elu(-1, 1) ≈ -0.632"] # [doc = " assert!((result.as_slice()[0] - (-0.865)).abs() < 0.01);"] # [doc = " assert!((result.as_slice()[1] - (-0.632)).abs() < 0.01);"] # [doc = " assert_eq!(result.as_slice()[2], 0.0);"] # [doc = " assert_eq!(result.as_slice()[3], 1.0);"] # [doc = " assert_eq!(result.as_slice()[4], 2.0);"] # [doc = " ```"] pub fn elu (& self , alpha : f32) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } if alpha <= 0.0 { return Err (TruenoError :: InvalidInput (format ! ("alpha must be > 0, got {}" , alpha))) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . elu (& self . data , & mut result , alpha) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let data : Vec < f32 > = self . data . iter () . map (| & x | if x > 0.0 { x } else { alpha * (x . exp () - 1.0) }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " GELU (Gaussian Error Linear Unit) activation function"] # [doc = ""] # [doc = " Computes the element-wise GELU activation using the tanh approximation."] # [doc = " GELU is the activation function used in transformers (BERT, GPT, etc.)."] # [doc = ""] # [doc = " # Formula"] # [doc = ""] # [doc = " ```text"] # [doc = " gelu(x) ≈ 0.5 * x * (1 + tanh(√(2/π) * (x + 0.044715 * x³)))"] # [doc = " ```"] # [doc = ""] # [doc = " This is the tanh approximation which is faster than the exact form"] # [doc = " involving the error function (erf)."] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Smooth**: Infinitely differentiable everywhere"] # [doc = " - **Non-monotonic**: Unlike ReLU variants, has slight non-monotonicity near zero"] # [doc = " - **Stochastic regularizer**: Can be viewed as adaptive dropout"] # [doc = " - **Zero-centered**: Mean activation close to zero"] # [doc = " - **Bounded below**: Approaches 0 as x → -∞"] # [doc = " - **Unbounded above**: Linear growth for large positive x"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - **Transformers**: BERT, GPT-2, GPT-3, GPT-4 (default activation)"] # [doc = " - **Vision transformers**: ViT, DINO, MAE"] # [doc = " - **Modern architectures**: State-of-the-art NLP and vision models"] # [doc = " - **Better than ReLU**: Empirically outperforms ReLU in many tasks"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " This operation is compute-intensive (tanh, x³ calculations)."] # [doc = " More expensive than ReLU but comparable to ELU."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.gelu().unwrap();"] # [doc = ""] # [doc = " // GELU is smooth and non-monotonic near zero"] # [doc = " assert!(result.as_slice()[0] < 0.0); // Negative inputs → small negative outputs"] # [doc = " assert_eq!(result.as_slice()[2], 0.0); // gelu(0) = 0"] # [doc = " assert!(result.as_slice()[4] > 1.5); // Large positive → ~linear"] # [doc = " ```"] pub fn gelu (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . gelu (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: gelu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: gelu (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: gelu (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: gelu (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: gelu (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: gelu (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: gelu (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: gelu (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: gelu (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Swish activation function (also known as SiLU - Sigmoid Linear Unit)"] # [doc = ""] # [doc = " Applies the Swish activation element-wise: swish(x) = x * sigmoid(x) = x / (1 + e^(-x))."] # [doc = ""] # [doc = " Swish is a smooth, non-monotonic activation function that consistently matches or"] # [doc = " outperforms ReLU in deep networks. It's used in EfficientNet, MobileNet v3, and"] # [doc = " many modern architectures. The function is self-gated: it adaptively gates the"] # [doc = " input based on its value."] # [doc = ""] # [doc = " Properties:"] # [doc = " - Smooth and differentiable everywhere"] # [doc = " - Non-monotonic: has a slight \"dip\" for negative values"] # [doc = " - swish(0) = 0"] # [doc = " - swish(x) ≈ x for large positive x (linear)"] # [doc = " - swish(x) ≈ 0 for large negative x"] # [doc = " - Unbounded above, bounded below by ≈ -0.278 at x ≈ -1.278"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Compute-bound operation requiring exponential and division."] # [doc = " Future SIMD optimizations planned for Phase 9 (GPU backend)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.swish().unwrap();"] # [doc = ""] # [doc = " // Swish is smooth and self-gated"] # [doc = " assert!(result.as_slice()[0] < 0.0); // Negative inputs → small negative outputs"] # [doc = " assert_eq!(result.as_slice()[2], 0.0); // swish(0) = 0"] # [doc = " assert!(result.as_slice()[4] > 1.5); // Large positive → ~linear"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Ramachandran et al. (2017): \"Searching for Activation Functions\""] # [doc = " - Also known as SiLU (Sigmoid Linear Unit): Elfwing et al. (2018)"] pub fn swish (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . swish (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: swish (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: swish (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: swish (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: swish (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: swish (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: swish (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: swish (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: swish (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { ScalarBackend :: swish (& self . data , & mut result) ; } } } Ok (Vector :: from_slice (& result)) } # [doc = " Hard Swish activation function"] # [doc = ""] # [doc = " Applies the hardswish activation element-wise: hardswish(x) = x * relu6(x + 3) / 6"] # [doc = ""] # [doc = " Hardswish is a piece-wise linear approximation to swish, designed for efficient"] # [doc = " computation in mobile neural networks. It's used in MobileNetV3 and avoids the"] # [doc = " expensive sigmoid computation of standard swish."] # [doc = ""] # [doc = " Properties:"] # [doc = " - Piece-wise linear: efficient to compute"] # [doc = " - hardswish(x) = 0 for x ≤ -3"] # [doc = " - hardswish(x) = x for x ≥ 3"] # [doc = " - hardswish(x) = x * (x + 3) / 6 for -3 < x < 3"] # [doc = " - hardswish(0) = 0"] # [doc = " - Smooth transitions at boundaries"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " More efficient than swish as it uses only multiply/divide operations"] # [doc = " instead of expensive exponential functions. Ideal for inference on"] # [doc = " resource-constrained devices."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-4.0, -3.0, 0.0, 3.0, 4.0]);"] # [doc = " let result = v.hardswish().unwrap();"] # [doc = ""] # [doc = " // Piece-wise linear behavior"] # [doc = " assert_eq!(result.as_slice()[0], 0.0); // x ≤ -3 → 0"] # [doc = " assert_eq!(result.as_slice()[1], 0.0); // x = -3 → 0"] # [doc = " assert_eq!(result.as_slice()[2], 0.0); // x = 0 → 0"] # [doc = " assert_eq!(result.as_slice()[3], 3.0); // x = 3 → x"] # [doc = " assert_eq!(result.as_slice()[4], 4.0); // x ≥ 3 → x"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Howard et al. (2019): \"Searching for MobileNetV3\""] pub fn hardswish (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let data : Vec < f32 > = self . data . iter () . map (| & x | { if x <= - 3.0 { 0.0 } else if x >= 3.0 { x } else { x * (x + 3.0) / 6.0 } }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " Mish activation function"] # [doc = ""] # [doc = " Applies the mish activation element-wise: mish(x) = x * tanh(softplus(x)) = x * tanh(ln(1 + e^x))"] # [doc = ""] # [doc = " Mish is a self-regularizing non-monotonic activation function that often outperforms"] # [doc = " ReLU and swish in computer vision tasks. It's used in YOLOv4 and many modern architectures."] # [doc = ""] # [doc = " Properties:"] # [doc = " - Smooth and non-monotonic (similar to swish)"] # [doc = " - Self-regularizing: prevents dying neurons"] # [doc = " - mish(0) ≈ 0 (small positive value)"] # [doc = " - mish(x) ≈ x for large positive x (nearly linear)"] # [doc = " - mish(x) ≈ 0 for large negative x"] # [doc = " - Bounded below by ≈ -0.31 at x ≈ -1.19"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Compute-bound operation requiring exponential, logarithm, and tanh."] # [doc = " More expensive than ReLU/swish but often provides better accuracy."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.mish().unwrap();"] # [doc = ""] # [doc = " // Mish is smooth and self-gated"] # [doc = " assert!(result.as_slice()[0] < 0.0); // Small negative output for negative inputs"] # [doc = " assert!(result.as_slice()[2].abs() < 1e-5); // mish(0) = 0"] # [doc = " assert!(result.as_slice()[4] > 1.5); // Large positive → near linear"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Misra (2019): \"Mish: A Self Regularized Non-Monotonic Neural Activation Function\""] pub fn mish (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } let data : Vec < f32 > = self . data . iter () . map (| & x | { if x < - 20.0 { 0.0 } else if x > 20.0 { x } else { let softplus = (1.0 + x . exp ()) . ln () ; x * softplus . tanh () } }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " SELU (Scaled Exponential Linear Unit) activation function"] # [doc = ""] # [doc = " Computes selu(x) = λ * (x if x > 0 else α * (exp(x) - 1))"] # [doc = " where λ ≈ 1.0507 and α ≈ 1.6733"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - **Self-normalizing**: Activations converge to zero mean and unit variance"] # [doc = " - **Vanishing gradient prevention**: Non-zero gradient for negative inputs"] # [doc = " - **Automatic normalization**: Reduces need for batch normalization"] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses scalar implementation (GPU disabled for element-wise ops)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-2.0, -1.0, 0.0, 1.0, 2.0]);"] # [doc = " let result = v.selu().unwrap();"] # [doc = ""] # [doc = " // Positive values scaled by λ ≈ 1.0507"] # [doc = " assert!((result.as_slice()[3] - 1.0507).abs() < 0.001);"] # [doc = " assert!((result.as_slice()[4] - 2.1014).abs() < 0.001);"] # [doc = ""] # [doc = " // Zero stays zero"] # [doc = " assert!(result.as_slice()[2].abs() < 1e-5);"] # [doc = ""] # [doc = " // Negative values use ELU-like formula"] # [doc = " assert!(result.as_slice()[0] < 0.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `EmptyVector` if the input vector is empty."] # [doc = ""] # [doc = " # References"] # [doc = ""] # [doc = " - Klambauer et al. (2017): \"Self-Normalizing Neural Networks\""] pub fn selu (& self) -> Result < Self > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } const LAMBDA : f32 = 1.0507009873554804934193349852946 ; const ALPHA : f32 = 1.6732632423543772848170429916717 ; let data : Vec < f32 > = self . data . iter () . map (| & x | { if x > 0.0 { LAMBDA * x } else { LAMBDA * ALPHA * (x . exp () - 1.0) } }) . collect () ; Ok (Vector :: from_slice (& data)) } # [doc = " L2 norm (Euclidean norm)"] # [doc = ""] # [doc = " Computes the Euclidean length of the vector: sqrt(sum(a\\[i\\]^2))."] # [doc = " This is mathematically equivalent to sqrt(dot(self, self))."] # [doc = ""] # [doc = " # Performance"] # [doc = ""] # [doc = " Uses optimized SIMD implementations via the dot product operation."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, 4.0]);"] # [doc = " let norm = v.norm_l2().unwrap();"] # [doc = " assert!((norm - 5.0).abs() < 1e-5); // sqrt(3^2 + 4^2) = 5"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty vectors"] # [doc = ""] # [doc = " Returns 0.0 for empty vectors (consistent with the mathematical definition)."] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert_eq!(v.norm_l2().unwrap(), 0.0);"] # [doc = " ```"] pub fn norm_l2 (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: norm_l2 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: norm_l2 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: norm_l2 (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: norm_l2 (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: norm_l2 (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: norm_l2 (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: norm_l2 (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: norm_l2 (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: norm_l2 (& self . data) , } } ; Ok (result) } # [doc = " Normalize the vector to unit length (L2 norm = 1)"] # [doc = ""] # [doc = " Returns a new vector in the same direction but with magnitude 1."] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `TruenoError::DivisionByZero` if the vector has zero norm (cannot normalize zero vector)."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, 4.0]);"] # [doc = " let unit = v.normalize().unwrap();"] # [doc = ""] # [doc = " // Result is [0.6, 0.8] (a unit vector)"] # [doc = " assert!((unit.as_slice()[0] - 0.6).abs() < 1e-5);"] # [doc = " assert!((unit.as_slice()[1] - 0.8).abs() < 1e-5);"] # [doc = ""] # [doc = " // Verify it's a unit vector (norm = 1)"] # [doc = " assert!((unit.norm_l2().unwrap() - 1.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Zero Vector Error"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::{Vector, TruenoError};"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 0.0]);"] # [doc = " assert!(matches!(v.normalize(), Err(TruenoError::DivisionByZero)));"] # [doc = " ```"] pub fn normalize (& self) -> Result < Vector < f32 > > { let norm = self . norm_l2 () ? ; if norm . abs () < 1e-10 { return Err (TruenoError :: DivisionByZero) ; } let norm_vec = Vector :: from_slice (& vec ! [norm ; self . len ()]) ; self . div (& norm_vec) } # [doc = " Compute the L1 norm (Manhattan norm) of the vector"] # [doc = ""] # [doc = " Returns the sum of absolute values: ||v||₁ = sum(|v\\[i\\]|)"] # [doc = ""] # [doc = " The L1 norm is used in:"] # [doc = " - Machine learning (L1 regularization, Lasso regression)"] # [doc = " - Distance metrics (Manhattan distance)"] # [doc = " - Sparse modeling and feature selection"] # [doc = " - Signal processing"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, -4.0, 5.0]);"] # [doc = " let norm = v.norm_l1().unwrap();"] # [doc = ""] # [doc = " // |3| + |-4| + |5| = 12"] # [doc = " assert!((norm - 12.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty Vector"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert_eq!(v.norm_l1().unwrap(), 0.0);"] # [doc = " ```"] pub fn norm_l1 (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let result = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: norm_l1 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: norm_l1 (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: norm_l1 (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: norm_l1 (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: norm_l1 (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: norm_l1 (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => WasmBackend :: norm_l1 (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: norm_l1 (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: norm_l1 (& self . data) , } } ; Ok (result) } # [doc = " Compute the L∞ norm (infinity norm / max norm) of the vector"] # [doc = ""] # [doc = " Returns the maximum absolute value: ||v||∞ = max(|v\\[i\\]|)"] # [doc = ""] # [doc = " The L∞ norm is used in:"] # [doc = " - Numerical analysis (error bounds, stability analysis)"] # [doc = " - Optimization (Chebyshev approximation)"] # [doc = " - Signal processing (peak detection)"] # [doc = " - Distance metrics (Chebyshev distance)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, -7.0, 5.0, -2.0]);"] # [doc = " let norm = v.norm_linf().unwrap();"] # [doc = ""] # [doc = " // max(|3|, |-7|, |5|, |-2|) = 7"] # [doc = " assert!((norm - 7.0).abs() < 1e-5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty Vector"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " assert_eq!(v.norm_linf().unwrap(), 0.0);"] # [doc = " ```"] pub fn norm_linf (& self) -> Result < f32 > { if self . data . is_empty () { return Ok (0.0) ; } let max_abs = unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: norm_linf (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: norm_linf (& self . data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => Avx2Backend :: norm_linf (& self . data) , # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: norm_linf (& self . data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => ScalarBackend :: norm_linf (& self . data) , # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => ScalarBackend :: norm_linf (& self . data) , # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => ScalarBackend :: norm_linf (& self . data) , # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => ScalarBackend :: norm_linf (& self . data) , Backend :: GPU | Backend :: Auto => ScalarBackend :: norm_linf (& self . data) , } } ; Ok (max_abs) } # [doc = " Compute element-wise absolute value"] # [doc = ""] # [doc = " Returns a new vector where each element is the absolute value of the corresponding input element."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.0, -4.0, 5.0, -2.0]);"] # [doc = " let result = v.abs().unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[3.0, 4.0, 5.0, 2.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Empty Vector"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v: Vector<f32> = Vector::from_slice(&[]);"] # [doc = " let result = v.abs().unwrap();"] # [doc = " assert_eq!(result.len(), 0);"] # [doc = " ```"] pub fn abs (& self) -> Result < Vector < f32 > > { let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: abs (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: abs (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: abs (& self . data , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: abs (& self . data , & mut result_data) , # [cfg (target_arch = "wasm32")] Backend :: WASM => WasmBackend :: abs (& self . data , & mut result_data) , Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: abs (& self . data , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Scalar multiplication (scale all elements by a scalar value)"] # [doc = ""] # [doc = " Returns a new vector where each element is multiplied by the scalar."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);"] # [doc = " let result = v.scale(2.0).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[2.0, 4.0, 6.0, 8.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Scaling by Zero"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = v.scale(0.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[0.0, 0.0, 0.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Negative Scaling"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, -2.0, 3.0]);"] # [doc = " let result = v.scale(-2.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-2.0, 4.0, -6.0]);"] # [doc = " ```"] pub fn scale (& self , scalar : f32) -> Result < Vector < f32 > > { let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: scale (& self . data , scalar , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: scale (& self . data , scalar , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: scale (& self . data , scalar , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: scale (& self . data , scalar , & mut result_data) , # [cfg (target_arch = "wasm32")] Backend :: WASM => WasmBackend :: scale (& self . data , scalar , & mut result_data) , Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: scale (& self . data , scalar , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Clamp elements to range [min_val, max_val]"] # [doc = ""] # [doc = " Returns a new vector where each element is constrained to the specified range."] # [doc = " Elements below min_val become min_val, elements above max_val become max_val."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);"] # [doc = " let result = v.clamp(0.0, 10.0).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Negative Range"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[-10.0, -5.0, 0.0, 5.0]);"] # [doc = " let result = v.clamp(-8.0, -2.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-8.0, -5.0, -2.0, -2.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `InvalidInput` if min_val > max_val."] pub fn clamp (& self , min_val : f32 , max_val : f32) -> Result < Vector < f32 > > { if min_val > max_val { return Err (TruenoError :: InvalidInput (format ! ("Invalid clamp range: min ({}) > max ({})" , min_val , max_val))) ; } let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: clamp (& self . data , min_val , max_val , & mut result_data) } # [cfg (target_arch = "wasm32")] Backend :: WASM => { WasmBackend :: clamp (& self . data , min_val , max_val , & mut result_data) } Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: clamp (& self . data , min_val , max_val , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Linear interpolation between two vectors"] # [doc = ""] # [doc = " Computes element-wise linear interpolation: `result\\[i\\] = a\\[i\\] + t * (b\\[i\\] - a\\[i\\])`"] # [doc = ""] # [doc = " - When `t = 0.0`, returns `self`"] # [doc = " - When `t = 1.0`, returns `other`"] # [doc = " - Values outside `[0, 1]` perform extrapolation"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[0.0, 10.0, 20.0]);"] # [doc = " let b = Vector::from_slice(&[100.0, 110.0, 120.0]);"] # [doc = " let result = a.lerp(&b, 0.5).unwrap();"] # [doc = ""] # [doc = " assert_eq!(result.as_slice(), &[50.0, 60.0, 70.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Extrapolation"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[0.0, 10.0]);"] # [doc = " let b = Vector::from_slice(&[10.0, 20.0]);"] # [doc = ""] # [doc = " // t > 1.0 extrapolates beyond b"] # [doc = " let result = a.lerp(&b, 2.0).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[20.0, 30.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `SizeMismatch` if vectors have different lengths."] pub fn lerp (& self , other : & Vector < f32 > , t : f32) -> Result < Vector < f32 > > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: lerp (& self . data , & other . data , t , & mut result_data) } # [cfg (target_arch = "wasm32")] Backend :: WASM => { WasmBackend :: lerp (& self . data , & other . data , t , & mut result_data) } Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: lerp (& self . data , & other . data , t , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Fused multiply-add: result\\[i\\] = self\\[i\\] * b\\[i\\] + c\\[i\\]"] # [doc = ""] # [doc = " Computes element-wise fused multiply-add operation. On hardware with FMA support"] # [doc = " (AVX2, NEON), this is a single instruction with better performance and numerical"] # [doc = " accuracy (no intermediate rounding). On platforms without FMA (SSE2, WASM), uses"] # [doc = " separate multiply and add operations."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `b` - The second vector to multiply with"] # [doc = " * `c` - The vector to add to the product"] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector where each element is `self\\[i\\] * b\\[i\\] + c\\[i\\]`"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `SizeMismatch` if vector lengths don't match"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let b = Vector::from_slice(&[5.0, 6.0, 7.0]);"] # [doc = " let c = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = a.fma(&b, &c).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[11.0, 20.0, 31.0]); // [2*5+1, 3*6+2, 4*7+3]"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = ""] # [doc = " - Neural networks: matrix multiplication, backpropagation"] # [doc = " - Scientific computing: polynomial evaluation, numerical integration"] # [doc = " - Graphics: transformation matrices, shader computations"] # [doc = " - Physics simulations: force calculations, particle systems"] pub fn fma (& self , b : & Vector < f32 > , c : & Vector < f32 >) -> Result < Vector < f32 > > { if self . len () != b . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : b . len () , }) ; } if self . len () != c . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : c . len () , }) ; } let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) } # [cfg (target_arch = "wasm32")] Backend :: WASM => { WasmBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) } Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: fma (& self . data , & b . data , & c . data , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Element-wise square root: result\\[i\\] = sqrt(self\\[i\\])"] # [doc = ""] # [doc = " Computes the square root of each element. For negative values, returns NaN"] # [doc = " following IEEE 754 floating-point semantics."] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector where each element is the square root of the corresponding input element"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[4.0, 9.0, 16.0, 25.0]);"] # [doc = " let result = a.sqrt().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[2.0, 3.0, 4.0, 5.0]);"] # [doc = " ```"] # [doc = ""] # [doc = " Negative values produce NaN:"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[-1.0, 4.0]);"] # [doc = " let result = a.sqrt().unwrap();"] # [doc = " assert!(result.as_slice()[0].is_nan());"] # [doc = " assert_eq!(result.as_slice()[1], 2.0);"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = ""] # [doc = " - Distance calculations: Euclidean distance computation"] # [doc = " - Statistics: Standard deviation, RMS (root mean square)"] # [doc = " - Machine learning: Normalization, gradient descent with adaptive learning rates"] # [doc = " - Signal processing: Amplitude calculations, power spectrum analysis"] # [doc = " - Physics simulations: Velocity from kinetic energy, wave propagation"] pub fn sqrt (& self) -> Result < Vector < f32 > > { let sqrt_data : Vec < f32 > = self . data . iter () . map (| x | x . sqrt ()) . collect () ; Ok (Vector { data : sqrt_data , backend : self . backend , }) } # [doc = " Element-wise reciprocal: result\\[i\\] = 1 / self\\[i\\]"] # [doc = ""] # [doc = " Computes the reciprocal (multiplicative inverse) of each element."] # [doc = " For zero values, returns infinity following IEEE 754 floating-point semantics."] # [doc = ""] # [doc = " # Returns"] # [doc = ""] # [doc = " A new vector where each element is the reciprocal of the corresponding input element"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[2.0, 4.0, 5.0, 10.0]);"] # [doc = " let result = a.recip().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[0.5, 0.25, 0.2, 0.1]);"] # [doc = " ```"] # [doc = ""] # [doc = " Zero values produce infinity:"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let a = Vector::from_slice(&[0.0, 2.0]);"] # [doc = " let result = a.recip().unwrap();"] # [doc = " assert!(result.as_slice()[0].is_infinite());"] # [doc = " assert_eq!(result.as_slice()[1], 0.5);"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = ""] # [doc = " - Division optimization: `a / b` → `a * recip(b)` (multiplication is faster)"] # [doc = " - Neural networks: Learning rate schedules, weight normalization"] # [doc = " - Statistics: Harmonic mean calculations, inverse transformations"] # [doc = " - Physics: Resistance (R = 1/G), optical power (P = 1/f)"] # [doc = " - Signal processing: Frequency to period conversion, filter design"] pub fn recip (& self) -> Result < Vector < f32 > > { let recip_data : Vec < f32 > = self . data . iter () . map (| x | x . recip ()) . collect () ; Ok (Vector { data : recip_data , backend : self . backend , }) } # [doc = " Element-wise power: result\\[i\\] = base\\[i\\]^n"] # [doc = ""] # [doc = " Raises each element to the given power `n`."] # [doc = " Uses Rust's optimized f32::powf() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let squared = v.pow(2.0).unwrap();"] # [doc = " assert_eq!(squared.as_slice(), &[4.0, 9.0, 16.0]);"] # [doc = ""] # [doc = " let sqrt = v.pow(0.5).unwrap(); // Fractional power = root"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `x.pow(0.0)` returns 1.0 for all x (even x=0)"] # [doc = " - `x.pow(1.0)` returns x (identity)"] # [doc = " - `x.pow(-1.0)` returns 1/x (reciprocal)"] # [doc = " - `x.pow(0.5)` returns sqrt(x) (square root)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Statistics: Power transformations (Box-Cox, Yeo-Johnson)"] # [doc = " - Machine learning: Polynomial features, activation functions"] # [doc = " - Physics: Inverse square law (1/r²), power laws"] # [doc = " - Signal processing: Power spectral density, root mean square"] pub fn pow (& self , n : f32) -> Result < Vector < f32 > > { let pow_data : Vec < f32 > = self . data . iter () . map (| x | x . powf (n)) . collect () ; Ok (Vector { data : pow_data , backend : self . backend , }) } # [doc = " Element-wise exponential: result\\[i\\] = e^x\\[i\\]"] # [doc = ""] # [doc = " Computes the natural exponential (e^x) for each element."] # [doc = " Uses Rust's optimized f32::exp() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, 2.0]);"] # [doc = " let result = v.exp().unwrap();"] # [doc = " // result ≈ [1.0, 2.718, 7.389]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `exp(0.0)` returns 1.0"] # [doc = " - `exp(1.0)` returns e ≈ 2.71828"] # [doc = " - `exp(-∞)` returns 0.0"] # [doc = " - `exp(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Machine learning: Softmax activation, sigmoid, exponential loss"] # [doc = " - Statistics: Exponential distribution, log-normal distribution"] # [doc = " - Physics: Radioactive decay, population growth models"] # [doc = " - Signal processing: Exponential smoothing, envelope detection"] # [doc = " - Numerical methods: Solving differential equations"] pub fn exp (& self) -> Result < Vector < f32 > > { let mut result_data = vec ! [0.0 ; self . len ()] ; if ! self . data . is_empty () { unsafe { match self . backend { Backend :: Scalar => ScalarBackend :: exp (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => Sse2Backend :: exp (& self . data , & mut result_data) , # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: exp (& self . data , & mut result_data) } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => NeonBackend :: exp (& self . data , & mut result_data) , # [cfg (target_arch = "wasm32")] Backend :: WASM => WasmBackend :: exp (& self . data , & mut result_data) , Backend :: GPU => return Err (TruenoError :: UnsupportedBackend (Backend :: GPU)) , Backend :: Auto => { return Err (TruenoError :: UnsupportedBackend (Backend :: Auto)) ; } # [allow (unreachable_patterns)] _ => ScalarBackend :: exp (& self . data , & mut result_data) , } } } Ok (Vector { data : result_data , backend : self . backend , }) } # [doc = " Element-wise natural logarithm: result\\[i\\] = ln(x\\[i\\])"] # [doc = ""] # [doc = " Computes the natural logarithm (base e) for each element."] # [doc = " Uses Rust's optimized f32::ln() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, std::f32::consts::E, std::f32::consts::E.powi(2)]);"] # [doc = " let result = v.ln().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 2.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `ln(1.0)` returns 0.0"] # [doc = " - `ln(e)` returns 1.0"] # [doc = " - `ln(x)` for x ≤ 0 returns NaN"] # [doc = " - `ln(0.0)` returns -∞"] # [doc = " - `ln(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Machine learning: Log loss, log-likelihood, softmax normalization"] # [doc = " - Statistics: Log-normal distribution, log transformation for skewed data"] # [doc = " - Information theory: Entropy calculation, mutual information"] # [doc = " - Economics: Log returns, elasticity calculations"] # [doc = " - Signal processing: Decibel conversion, log-frequency analysis"] pub fn ln (& self) -> Result < Vector < f32 > > { let ln_data : Vec < f32 > = self . data . iter () . map (| x | x . ln ()) . collect () ; Ok (Vector { data : ln_data , backend : self . backend , }) } # [doc = " Element-wise base-2 logarithm: result\\[i\\] = log₂(x\\[i\\])"] # [doc = ""] # [doc = " Computes the base-2 logarithm for each element."] # [doc = " Uses Rust's optimized f32::log2() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 4.0, 8.0]);"] # [doc = " let result = v.log2().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 2.0, 3.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `log2(1.0)` returns 0.0"] # [doc = " - `log2(2.0)` returns 1.0"] # [doc = " - `log2(x)` for x ≤ 0 returns NaN"] # [doc = " - `log2(0.0)` returns -∞"] # [doc = " - `log2(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Information theory: Entropy in bits, mutual information"] # [doc = " - Computer science: Bit manipulation, binary search complexity"] # [doc = " - Audio: Octave calculations, pitch detection"] # [doc = " - Data compression: Huffman coding, arithmetic coding"] pub fn log2 (& self) -> Result < Vector < f32 > > { let log2_data : Vec < f32 > = self . data . iter () . map (| x | x . log2 ()) . collect () ; Ok (Vector { data : log2_data , backend : self . backend , }) } # [doc = " Element-wise base-10 logarithm: result\\[i\\] = log₁₀(x\\[i\\])"] # [doc = ""] # [doc = " Computes the base-10 (common) logarithm for each element."] # [doc = " Uses Rust's optimized f32::log10() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 10.0, 100.0, 1000.0]);"] # [doc = " let result = v.log10().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 2.0, 3.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `log10(1.0)` returns 0.0"] # [doc = " - `log10(10.0)` returns 1.0"] # [doc = " - `log10(x)` for x ≤ 0 returns NaN"] # [doc = " - `log10(0.0)` returns -∞"] # [doc = " - `log10(+∞)` returns +∞"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Audio: Decibel calculations (dB = 20 * log10(amplitude))"] # [doc = " - Chemistry: pH calculations (-log10(H+ concentration))"] # [doc = " - Seismology: Richter scale"] # [doc = " - Scientific notation: Order of magnitude calculations"] pub fn log10 (& self) -> Result < Vector < f32 > > { let log10_data : Vec < f32 > = self . data . iter () . map (| x | x . log10 ()) . collect () ; Ok (Vector { data : log10_data , backend : self . backend , }) } # [doc = " Element-wise sine: result\\[i\\] = sin(x\\[i\\])"] # [doc = ""] # [doc = " Computes the sine for each element (input in radians)."] # [doc = " Uses Rust's optimized f32::sin() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, PI / 2.0, PI]);"] # [doc = " let result = v.sin().unwrap();"] # [doc = " // result ≈ [0.0, 1.0, 0.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `sin(0)` returns 0.0"] # [doc = " - `sin(π/2)` returns 1.0"] # [doc = " - `sin(π)` returns 0.0 (approximately)"] # [doc = " - `sin(-x)` returns -sin(x) (odd function)"] # [doc = " - Periodic with period 2π: sin(x + 2π) = sin(x)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Signal processing: Waveform generation, oscillators, modulation"] # [doc = " - Physics: Harmonic motion, wave propagation, pendulums"] # [doc = " - Audio: Synthesizers, tone generation, effects processing"] # [doc = " - Graphics: Animation, rotation transformations, procedural generation"] # [doc = " - Fourier analysis: Frequency decomposition, spectral analysis"] pub fn sin (& self) -> Result < Vector < f32 > > { let sin_data : Vec < f32 > = self . data . iter () . map (| x | x . sin ()) . collect () ; Ok (Vector { data : sin_data , backend : self . backend , }) } # [doc = " Element-wise cosine: result\\[i\\] = cos(x\\[i\\])"] # [doc = ""] # [doc = " Computes the cosine for each element (input in radians)."] # [doc = " Uses Rust's optimized f32::cos() method."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, PI / 2.0, PI]);"] # [doc = " let result = v.cos().unwrap();"] # [doc = " // result ≈ [1.0, 0.0, -1.0]"] # [doc = " ```"] # [doc = ""] # [doc = " # Special Cases"] # [doc = ""] # [doc = " - `cos(0)` returns 1.0"] # [doc = " - `cos(π/2)` returns 0.0 (approximately)"] # [doc = " - `cos(π)` returns -1.0"] # [doc = " - `cos(-x)` returns cos(x) (even function)"] # [doc = " - Periodic with period 2π: cos(x + 2π) = cos(x)"] # [doc = " - Relation to sine: cos(x) = sin(x + π/2)"] # [doc = ""] # [doc = " # Applications"] # [doc = ""] # [doc = " - Signal processing: Phase-shifted waveforms, I/Q modulation, quadrature signals"] # [doc = " - Physics: Projectile motion, wave interference, damped oscillations"] # [doc = " - Graphics: Rotation matrices, camera transforms, circular motion"] # [doc = " - Audio: Stereo panning, spatial audio, frequency synthesis"] # [doc = " - Engineering: Control systems, frequency response, AC circuits"] pub fn cos (& self) -> Result < Vector < f32 > > { let cos_data : Vec < f32 > = self . data . iter () . map (| x | x . cos ()) . collect () ; Ok (Vector { data : cos_data , backend : self . backend , }) } # [doc = " Computes element-wise tangent (tan) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the tangent of the corresponding input element."] # [doc = " tan(x) = sin(x) / cos(x)"] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with tan(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Odd function: tan(-x) = -tan(x)"] # [doc = " - Period: 2π (not π, despite common misconception)"] # [doc = " - Undefined at x = π/2 + nπ (where n is any integer)"] # [doc = " - tan(x) = sin(x) / cos(x)"] # [doc = " - Range: (-∞, +∞)"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::tan()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let angles = Vector::from_slice(&[0.0, PI / 4.0, -PI / 4.0]);"] # [doc = " let result = angles.tan().unwrap();"] # [doc = " // Result: [0.0, 1.0, -1.0] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Trigonometry: Slope calculations, angle relationships"] # [doc = " - Signal processing: Phase analysis, modulation"] # [doc = " - Physics: Projectile trajectories, optics (Snell's law angles)"] # [doc = " - Graphics: Perspective projection, field of view calculations"] # [doc = " - Engineering: Slope gradients, tangent lines to curves"] pub fn tan (& self) -> Result < Vector < f32 > > { let tan_data : Vec < f32 > = self . data . iter () . map (| x | x . tan ()) . collect () ; Ok (Vector { data : tan_data , backend : self . backend , }) } # [doc = " Computes element-wise arcsine (asin/sin⁻¹) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the inverse sine of the corresponding input element."] # [doc = " This is the inverse function of sin: if y = sin(x), then x = asin(y)."] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with asin(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Domain: [-1, 1] (inputs outside this range produce NaN)"] # [doc = " - Range: [-π/2, π/2]"] # [doc = " - Odd function: asin(-x) = -asin(x)"] # [doc = " - Inverse relation: asin(sin(x)) = x for x ∈ [-π/2, π/2]"] # [doc = " - asin(0) = 0"] # [doc = " - asin(1) = π/2"] # [doc = " - asin(-1) = -π/2"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::asin()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let values = Vector::from_slice(&[0.0, 0.5, 1.0]);"] # [doc = " let result = values.asin().unwrap();"] # [doc = " // Result: [0.0, π/6, π/2] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Physics: Calculating angles from sine values in mechanics, optics"] # [doc = " - Signal processing: Phase recovery, demodulation"] # [doc = " - Graphics: Inverse transformations, angle calculations"] # [doc = " - Navigation: GPS calculations, spherical trigonometry"] # [doc = " - Control systems: Inverse kinematics, servo positioning"] pub fn asin (& self) -> Result < Vector < f32 > > { let asin_data : Vec < f32 > = self . data . iter () . map (| x | x . asin ()) . collect () ; Ok (Vector { data : asin_data , backend : self . backend , }) } # [doc = " Computes element-wise arccosine (acos/cos⁻¹) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the inverse cosine of the corresponding input element."] # [doc = " This is the inverse function of cos: if y = cos(x), then x = acos(y)."] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with acos(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Domain: [-1, 1] (inputs outside this range produce NaN)"] # [doc = " - Range: [0, π]"] # [doc = " - Symmetry: acos(-x) = π - acos(x)"] # [doc = " - Inverse relation: acos(cos(x)) = x for x ∈ [0, π]"] # [doc = " - acos(0) = π/2"] # [doc = " - acos(1) = 0"] # [doc = " - acos(-1) = π"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::acos()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let values = Vector::from_slice(&[0.0, 0.5, 1.0]);"] # [doc = " let result = values.acos().unwrap();"] # [doc = " // Result: [π/2, π/3, 0.0] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Physics: Angle calculations in mechanics, optics, reflections"] # [doc = " - Signal processing: Phase analysis, correlation functions"] # [doc = " - Graphics: View angle calculations, lighting models"] # [doc = " - Navigation: Bearing calculations, great circle distances"] # [doc = " - Robotics: Joint angle solving, orientation calculations"] pub fn acos (& self) -> Result < Vector < f32 > > { let acos_data : Vec < f32 > = self . data . iter () . map (| x | x . acos ()) . collect () ; Ok (Vector { data : acos_data , backend : self . backend , }) } # [doc = " Computes element-wise arctangent (atan/tan⁻¹) of the vector."] # [doc = ""] # [doc = " Returns a new vector where each element is the inverse tangent of the corresponding input element."] # [doc = " This is the inverse function of tan: if y = tan(x), then x = atan(y)."] # [doc = ""] # [doc = " # Returns"] # [doc = " - `Ok(Vector<f32>)`: New vector with atan(x) for each element"] # [doc = ""] # [doc = " # Properties"] # [doc = " - Domain: All real numbers (-∞, +∞)"] # [doc = " - Range: (-π/2, π/2)"] # [doc = " - Odd function: atan(-x) = -atan(x)"] # [doc = " - Inverse relation: atan(tan(x)) = x for x ∈ (-π/2, π/2)"] # [doc = " - atan(0) = 0"] # [doc = " - atan(1) = π/4"] # [doc = " - atan(-1) = -π/4"] # [doc = " - lim(x→∞) atan(x) = π/2"] # [doc = " - lim(x→-∞) atan(x) = -π/2"] # [doc = ""] # [doc = " # Performance"] # [doc = " - Iterator map pattern for cache efficiency"] # [doc = " - Leverages Rust's optimized f32::atan()"] # [doc = " - Auto-vectorized by LLVM on supporting platforms"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " use std::f32::consts::PI;"] # [doc = ""] # [doc = " let values = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = values.atan().unwrap();"] # [doc = " // Result: [0.0, π/4, -π/4] (approximately)"] # [doc = " ```"] # [doc = ""] # [doc = " # Use Cases"] # [doc = " - Physics: Angle calculations from slopes, velocity components"] # [doc = " - Signal processing: Phase unwrapping, FM demodulation"] # [doc = " - Graphics: Rotation calculations, camera orientation"] # [doc = " - Robotics: Inverse kinematics, steering angles"] # [doc = " - Navigation: Heading calculations from coordinates"] pub fn atan (& self) -> Result < Vector < f32 > > { let atan_data : Vec < f32 > = self . data . iter () . map (| x | x . atan ()) . collect () ; Ok (Vector { data : atan_data , backend : self . backend , }) } # [doc = " Computes the hyperbolic sine (sinh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " sinh(x) = (e^x - e^(-x)) / 2"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: (-∞, +∞)"] # [doc = " - Odd function: sinh(-x) = -sinh(x)"] # [doc = " - sinh(0) = 0"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.sinh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " ```"] pub fn sinh (& self) -> Result < Vector < f32 > > { let sinh_data : Vec < f32 > = self . data . iter () . map (| x | x . sinh ()) . collect () ; Ok (Vector { data : sinh_data , backend : self . backend , }) } # [doc = " Computes the hyperbolic cosine (cosh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " cosh(x) = (e^x + e^(-x)) / 2"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: [1, +∞)"] # [doc = " - Even function: cosh(-x) = cosh(x)"] # [doc = " - cosh(0) = 1"] # [doc = " - Always positive: cosh(x) ≥ 1 for all x"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.cosh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 1.0).abs() < 1e-5);"] # [doc = " ```"] pub fn cosh (& self) -> Result < Vector < f32 > > { let cosh_data : Vec < f32 > = self . data . iter () . map (| x | x . cosh ()) . collect () ; Ok (Vector { data : cosh_data , backend : self . backend , }) } # [doc = " Computes the hyperbolic tangent (tanh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " tanh(x) = sinh(x) / cosh(x) = (e^x - e^(-x)) / (e^x + e^(-x))"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: (-1, 1)"] # [doc = " - Odd function: tanh(-x) = -tanh(x)"] # [doc = " - tanh(0) = 0"] # [doc = " - Bounded: -1 < tanh(x) < 1 for all x"] # [doc = " - Commonly used as activation function in neural networks"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.tanh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " // All values are in range (-1, 1)"] # [doc = " assert!(result.as_slice().iter().all(|&x| x > -1.0 && x < 1.0));"] # [doc = " ```"] pub fn tanh (& self) -> Result < Vector < f32 > > { if self . data . is_empty () { return Err (TruenoError :: EmptyVector) ; } # [cfg (feature = "gpu")] const GPU_THRESHOLD : usize = usize :: MAX ; # [cfg (feature = "gpu")] { if self . data . len () >= GPU_THRESHOLD { use crate :: backends :: gpu :: GpuDevice ; if GpuDevice :: is_available () { let gpu = GpuDevice :: new () . map_err (TruenoError :: InvalidInput) ? ; let mut result = vec ! [0.0 ; self . data . len ()] ; if gpu . tanh (& self . data , & mut result) . is_ok () { return Ok (Vector :: from_slice (& result)) ; } } } } let mut result = vec ! [0.0 ; self . len ()] ; unsafe { match self . backend { Backend :: Scalar => { ScalarBackend :: tanh (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: SSE2 | Backend :: AVX => { Sse2Backend :: tanh (& self . data , & mut result) ; } # [cfg (target_arch = "x86_64")] Backend :: AVX2 | Backend :: AVX512 => { Avx2Backend :: tanh (& self . data , & mut result) ; } # [cfg (not (target_arch = "x86_64"))] Backend :: SSE2 | Backend :: AVX | Backend :: AVX2 | Backend :: AVX512 => { ScalarBackend :: tanh (& self . data , & mut result) ; } # [cfg (any (target_arch = "aarch64" , target_arch = "arm"))] Backend :: NEON => { NeonBackend :: tanh (& self . data , & mut result) ; } # [cfg (not (any (target_arch = "aarch64" , target_arch = "arm")))] Backend :: NEON => { ScalarBackend :: tanh (& self . data , & mut result) ; } # [cfg (target_arch = "wasm32")] Backend :: WasmSIMD => { WasmBackend :: tanh (& self . data , & mut result) ; } # [cfg (not (target_arch = "wasm32"))] Backend :: WasmSIMD => { ScalarBackend :: tanh (& self . data , & mut result) ; } Backend :: GPU | Backend :: Auto => { # [cfg (target_arch = "x86_64")] { if is_x86_feature_detected ! ("avx2") { Avx2Backend :: tanh (& self . data , & mut result) ; } else { Sse2Backend :: tanh (& self . data , & mut result) ; } } # [cfg (not (target_arch = "x86_64"))] { ScalarBackend :: tanh (& self . data , & mut result) ; } } } } Ok (Vector { data : result , backend : self . backend , }) } # [doc = " Computes the inverse hyperbolic sine (asinh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " asinh(x) = ln(x + sqrt(x² + 1))"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: (-∞, +∞)"] # [doc = " - Range: (-∞, +∞)"] # [doc = " - Odd function: asinh(-x) = -asinh(x)"] # [doc = " - asinh(0) = 0"] # [doc = " - Inverse of sinh: asinh(sinh(x)) = x"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 1.0, -1.0]);"] # [doc = " let result = v.asinh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " ```"] pub fn asinh (& self) -> Result < Vector < f32 > > { let asinh_data : Vec < f32 > = self . data . iter () . map (| x | x . asinh ()) . collect () ; Ok (Vector { data : asinh_data , backend : self . backend , }) } # [doc = " Computes the inverse hyperbolic cosine (acosh) of each element."] # [doc = ""] # [doc = " # Mathematical Definition"] # [doc = ""] # [doc = " acosh(x) = ln(x + sqrt(x² - 1))"] # [doc = ""] # [doc = " # Properties"] # [doc = ""] # [doc = " - Domain: [1, +∞)"] # [doc = " - Range: [0, +∞)"] # [doc = " - acosh(1) = 0"] # [doc = " - Inverse of cosh: acosh(cosh(x)) = x for x >= 0"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[1.0, 2.0, 3.0]);"] # [doc = " let result = v.acosh().unwrap();"] # [doc = " assert!((result.as_slice()[0] - 0.0).abs() < 1e-5);"] # [doc = " ```"] pub fn acosh (& self) -> Result < Vector < f32 > > { let acosh_data : Vec < f32 > = self . data . iter () . map (| x | x . acosh ()) . collect () ; Ok (Vector { data : acosh_data , backend : self . backend , }) } # [doc = " Computes the inverse hyperbolic tangent (atanh) of each element."] # [doc = ""] # [doc = " Domain: (-1, 1)"] # [doc = " Range: (-∞, +∞)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[0.0, 0.5, -0.5]);"] # [doc = " let result = v.atanh().unwrap();"] # [doc = " // atanh(0) = 0, atanh(0.5) ≈ 0.549, atanh(-0.5) ≈ -0.549"] # [doc = " ```"] pub fn atanh (& self) -> Result < Vector < f32 > > { let atanh_data : Vec < f32 > = self . data . iter () . map (| x | x . atanh ()) . collect () ; Ok (Vector { data : atanh_data , backend : self . backend , }) } # [doc = " Computes the floor (round down to nearest integer) of each element."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.7, -2.3, 5.0]);"] # [doc = " let result = v.floor().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[3.0, -3.0, 5.0]);"] # [doc = " ```"] pub fn floor (& self) -> Result < Vector < f32 > > { let floor_data : Vec < f32 > = self . data . iter () . map (| x | x . floor ()) . collect () ; Ok (Vector { data : floor_data , backend : self . backend , }) } # [doc = " Computes the ceiling (round up to nearest integer) of each element."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.2, -2.7, 5.0]);"] # [doc = " let result = v.ceil().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[4.0, -2.0, 5.0]);"] # [doc = " ```"] pub fn ceil (& self) -> Result < Vector < f32 > > { let ceil_data : Vec < f32 > = self . data . iter () . map (| x | x . ceil ()) . collect () ; Ok (Vector { data : ceil_data , backend : self . backend , }) } # [doc = " Rounds each element to the nearest integer."] # [doc = ""] # [doc = " Uses \"round half away from zero\" strategy:"] # [doc = " - 0.5 rounds to 1.0, 1.5 rounds to 2.0, -1.5 rounds to -2.0, etc."] # [doc = " - Positive halfway cases round up, negative halfway cases round down."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.2, 3.7, -2.3, -2.8]);"] # [doc = " let result = v.round().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[3.0, 4.0, -2.0, -3.0]);"] # [doc = " ```"] pub fn round (& self) -> Result < Vector < f32 > > { let round_data : Vec < f32 > = self . data . iter () . map (| x | x . round ()) . collect () ; Ok (Vector { data : round_data , backend : self . backend , }) } # [doc = " Truncates each element toward zero (removes fractional part)."] # [doc = ""] # [doc = " Truncation always moves toward zero:"] # [doc = " - Positive values: equivalent to floor() (e.g., 3.7 → 3.0)"] # [doc = " - Negative values: equivalent to ceil() (e.g., -3.7 → -3.0)"] # [doc = " - This differs from floor() which always rounds down"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.7, -2.7, 5.0]);"] # [doc = " let result = v.trunc().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[3.0, -2.0, 5.0]);"] # [doc = " ```"] pub fn trunc (& self) -> Result < Vector < f32 > > { let trunc_data : Vec < f32 > = self . data . iter () . map (| x | x . trunc ()) . collect () ; Ok (Vector { data : trunc_data , backend : self . backend , }) } # [doc = " Returns the fractional part of each element."] # [doc = ""] # [doc = " The fractional part has the same sign as the original value:"] # [doc = " - Positive: fract(3.7) = 0.7"] # [doc = " - Negative: fract(-3.7) = -0.7"] # [doc = " - Decomposition property: x = trunc(x) + fract(x)"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[3.7, -2.3, 5.0]);"] # [doc = " let result = v.fract().unwrap();"] # [doc = " // Fractional parts: 0.7, -0.3, 0.0"] # [doc = " assert!((result.as_slice()[0] - 0.7).abs() < 1e-5);"] # [doc = " assert!((result.as_slice()[1] - (-0.3)).abs() < 1e-5);"] # [doc = " ```"] pub fn fract (& self) -> Result < Vector < f32 > > { let fract_data : Vec < f32 > = self . data . iter () . map (| x | x . fract ()) . collect () ; Ok (Vector { data : fract_data , backend : self . backend , }) } # [doc = " Returns the sign of each element."] # [doc = ""] # [doc = " Returns:"] # [doc = " - `1.0` if the value is positive (including +0.0 and +∞)"] # [doc = " - `-1.0` if the value is negative (including -0.0 and -∞)"] # [doc = " - `NaN` if the value is NaN"] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let v = Vector::from_slice(&[5.0, -3.0, 0.0, -0.0]);"] # [doc = " let result = v.signum().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[1.0, -1.0, 1.0, -1.0]);"] # [doc = " ```"] pub fn signum (& self) -> Result < Vector < f32 > > { let signum_data : Vec < f32 > = self . data . iter () . map (| x | x . signum ()) . collect () ; Ok (Vector { data : signum_data , backend : self . backend , }) } # [doc = " Returns a vector with the magnitude of `self` and the sign of `sign`."] # [doc = ""] # [doc = " For each element pair, takes the magnitude from `self` and the sign from `sign`."] # [doc = " Equivalent to `abs(self\\[i\\])` with the sign of `sign\\[i\\]`."] # [doc = ""] # [doc = " # Arguments"] # [doc = ""] # [doc = " * `sign` - Vector providing the sign for each element"] # [doc = ""] # [doc = " # Errors"] # [doc = ""] # [doc = " Returns `TruenoError::SizeMismatch` if vectors have different lengths."] # [doc = ""] # [doc = " # Examples"] # [doc = ""] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = ""] # [doc = " let magnitude = Vector::from_slice(&[5.0, 3.0, 2.0]);"] # [doc = " let sign = Vector::from_slice(&[-1.0, 1.0, -1.0]);"] # [doc = " let result = magnitude.copysign(&sign).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-5.0, 3.0, -2.0]);"] # [doc = " ```"] pub fn copysign (& self , sign : & Self) -> Result < Vector < f32 > > { if self . len () != sign . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : sign . len () , }) ; } let copysign_data : Vec < f32 > = self . data . iter () . zip (sign . data . iter ()) . map (| (mag , sgn) | mag . copysign (* sgn)) . collect () ; Ok (Vector { data : copysign_data , backend : self . backend , }) } # [doc = " Element-wise minimum of two vectors."] # [doc = ""] # [doc = " Returns a new vector where each element is the minimum of the corresponding"] # [doc = " elements from self and other."] # [doc = ""] # [doc = " NaN handling: Prefers non-NaN values (NAN.min(x) = x)."] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " let a = Vector::from_slice(&[1.0, 5.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let result = a.minimum(&b).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[1.0, 3.0, 3.0]);"] # [doc = " ```"] pub fn minimum (& self , other : & Self) -> Result < Vector < f32 > > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let minimum_data : Vec < f32 > = self . data . iter () . zip (other . data . iter ()) . map (| (a , b) | a . min (* b)) . collect () ; Ok (Vector { data : minimum_data , backend : self . backend , }) } # [doc = " Element-wise maximum of two vectors."] # [doc = ""] # [doc = " Returns a new vector where each element is the maximum of the corresponding"] # [doc = " elements from self and other."] # [doc = ""] # [doc = " NaN handling: Prefers non-NaN values (NAN.max(x) = x)."] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " let a = Vector::from_slice(&[1.0, 5.0, 3.0]);"] # [doc = " let b = Vector::from_slice(&[2.0, 3.0, 4.0]);"] # [doc = " let result = a.maximum(&b).unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[2.0, 5.0, 4.0]);"] # [doc = " ```"] pub fn maximum (& self , other : & Self) -> Result < Vector < f32 > > { if self . len () != other . len () { return Err (TruenoError :: SizeMismatch { expected : self . len () , actual : other . len () , }) ; } let maximum_data : Vec < f32 > = self . data . iter () . zip (other . data . iter ()) . map (| (a , b) | a . max (* b)) . collect () ; Ok (Vector { data : maximum_data , backend : self . backend , }) } # [doc = " Element-wise negation (unary minus)."] # [doc = ""] # [doc = " Returns a new vector where each element is the negation of the corresponding"] # [doc = " element from self."] # [doc = ""] # [doc = " Properties: Double negation is identity: -(-x) = x"] # [doc = ""] # [doc = " # Examples"] # [doc = " ```"] # [doc = " use trueno::Vector;"] # [doc = " let a = Vector::from_slice(&[1.0, -2.0, 3.0]);"] # [doc = " let result = a.neg().unwrap();"] # [doc = " assert_eq!(result.as_slice(), &[-1.0, 2.0, -3.0]);"] # [doc = " ```"] pub fn neg (& self) -> Result < Vector < f32 > > { let neg_data : Vec < f32 > = self . data . iter () . map (| x | - x) . collect () ; Ok (Vector { data : neg_data , backend : self . backend , }) } } . self_ty`
- **Function**: `tests::test_from_slice` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_from_slice_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_from_slice_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_from_slice_with_backend` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_auto_backend_resolution` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_add_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sub_negative_result` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mul` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mul_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mul_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_by_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_div_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_dot` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_dot_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_dot_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_kahan_numerical_stability` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_max_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_min_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmax_first_occurrence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_argmin_first_occurrence` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_unit_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l2_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize_already_unit` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_normalize_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_l1_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_zero_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_norm_linf_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_mixed` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_with_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_abs_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_by_fraction` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_scale_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_all_within_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_all_below_min` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_all_above_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_negative_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_same_min_max` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clamp_invalid_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_at_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_at_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_extrapolate_above` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_extrapolate_below` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_lerp_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_ones` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_negatives` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_size_mismatch_b` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_size_mismatch_c` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fma_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_zeros` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sqrt_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_ones` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_negatives` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_recip_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_cube` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_zero_exponent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_one_exponent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_negative_exponent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_pow_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_exp_backend_auto_unsupported` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_small_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_inverse_exp` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ln_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_non_powers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log2_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_fractional` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_non_powers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log10_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_quarter_circle` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_periodicity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sin_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_quarter_circle` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_sin_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cos_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_quarter_circle` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_sin_cos_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tan_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_sin_inverse` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asin_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_symmetry` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_cos_inverse` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acos_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_tan_inverse` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atan_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_odd_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sinh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_even_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_cosh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_sinh_cosh_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_tanh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_odd_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_asinh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_one` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_large` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_cosh_relation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_acosh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_odd_function` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_atanh_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_integers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_floor_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_integers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_ceil_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_halfway` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_round_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_toward_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_trunc_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_integers` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_fract_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_mixed` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_zero_handling` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_signum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_negative_magnitude` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_copysign_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_nan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minimum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_nan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_maximum_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_double_negation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_nan` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_infinity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_neg_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_pythagorean` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sum_of_squares_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_mixed` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_all_same` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mean_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_constant` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_symmetric` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_two_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_variance_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_constant` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_single` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_symmetric` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_two_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_stddev_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_self` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_covariance_empty` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_perfect_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_perfect_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_self` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_constant_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_correlation_size_mismatch` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_constant_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_zscore_already_normalized` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_constant_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_minmax_normalize_already_normalized` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_no_change` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_all_below` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_all_above` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_invalid_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_clip_equal_bounds` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_uniform` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_softmax_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_uniform` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_negative_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_log_softmax_single_element` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_all_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_all_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_zero_boundary` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_relu_sparsity` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_range` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_symmetry` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_extreme_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_sigmoid_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_different_slopes` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_reduces_to_relu` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_preserves_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_leaky_relu_invalid_slope` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_different_alphas` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_saturation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_preserves_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_elu_invalid_alpha` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_smoothness` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_gelu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_minimum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_swish_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_boundary_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_large_values` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_transition_region` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_hardswish_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_large_positive` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_large_negative` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_minimum` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_mish_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_basic` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_positive_scaling` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_negative_asymptote` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_continuity_at_zero` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_selu_empty_vector` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_aligned_vector_creation` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
- **Function**: `tests::test_aligned_vector_operations` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: high(104)] [tdg: 2.5]
### ./tests/chaos_tests.rs
**File Complexity**: 1 | **Functions**: 5
- **Function**: `test_gentle_preset_properties` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_aggressive_preset_properties` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_chaos_error_display_messages` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_default_is_permissive` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `test_presets_are_distinct` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
### ./tests/integration_test.rs
**File Complexity**: 1 | **Functions**: 4
- **Function**: `integration_error_handling` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `integration_backend_selection` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `integration_smoke_test_all_operations` [complexity: 1] [cognitive: 0] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
- **Function**: `integration_performance_gate` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(4)] [tdg: 2.5]
### ./xtask/src/main.rs
**File Complexity**: 3 | **Functions**: 1
- **Function**: `main` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(1)] [tdg: 2.5]
### ./xtask/src/validate_examples.rs
**File Complexity**: 5 | **Functions**: 13
- **Function**: `run` [complexity: 5] [cognitive: 4] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `get_project_root` [complexity: 5] [cognitive: 10] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `collect_examples` [complexity: 6] [cognitive: 7] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_compile_examples` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_clippy_examples` [complexity: 3] [cognitive: 2] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_module_docs` [complexity: 5] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `has_module_doc` [complexity: 6] [cognitive: 14] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_runnable` [complexity: 7] [cognitive: 13] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `has_main_function` [complexity: 2] [cognitive: 1] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `run_example_with_timeout` [complexity: 8] [cognitive: 19] [big-o: O(n log n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_book_references` [complexity: 10] [cognitive: 16] [big-o: O(n log n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `find_markdown_files` [complexity: 3] [cognitive: 3] [big-o: O(1)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `step_check_naming_conventions` [complexity: 5] [cognitive: 6] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Struct**: `ValidationResults` [fields: 1]
- **Struct**: `StepResult` [fields: 4]
- **Impl**: `impl ValidationResults { fn new () -> Self { Self { steps : Vec :: new () } } fn add_step < F > (& mut self , number : usize , name : & str , f : F) where F : FnOnce () -> Result < () > , { print ! ("Step {}/6: {}... " , number , name) ; match f () { Ok (_) => { println ! ("{}" , "✓" . green ()) ; self . steps . push (StepResult { number , name : name . to_string () , success : true , error : None , }) ; } Err (e) => { println ! ("{}" , "✗" . red ()) ; eprintln ! (" {}" , format ! ("{}" , e) . red ()) ; self . steps . push (StepResult { number , name : name . to_string () , success : false , error : Some (format ! ("{}" , e)) , }) ; } } } fn has_failures (& self) -> bool { self . steps . iter () . any (| s | ! s . success) } fn print_summary (& self) { println ! () ; println ! ("{}" , "═══════════════════════════════════" . bold ()) ; println ! ("{}" , "Summary" . bold ()) ; println ! ("{}" , "═══════════════════════════════════" . bold ()) ; let total = self . steps . len () ; let passed = self . steps . iter () . filter (| s | s . success) . count () ; let failed = total - passed ; for step in & self . steps { let status = if step . success { "✓" . green () } else { "✗" . red () } ; println ! ("{} Step {}: {}" , status , step . number , step . name) ; } println ! () ; println ! ("Total: {}, Passed: {}, Failed: {}" , total , format ! ("{}" , passed) . green () , if failed > 0 { format ! ("{}" , failed) . red () } else { format ! ("{}" , failed) . green () }) ; if failed == 0 { println ! () ; println ! ("{}" , "✅ All validation checks passed!" . green () . bold ()) ; } } } . self_ty`
- **Function**: `tests::test_has_module_doc_with_doc` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_module_doc_without_doc` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_module_doc_empty_file` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_main_function_present` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_main_function_absent` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_has_main_function_with_result` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_snake_case_validation_valid` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_snake_case_validation_invalid` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_collect_examples_empty_dir` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_collect_examples_with_files` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_collect_examples_nonexistent_dir` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_find_markdown_files` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_validation_results_all_pass` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]
- **Function**: `tests::test_validation_results_with_failure` [complexity: 3] [cognitive: 2] [big-o: O(n)] [provability: 43%] [satd: 0] [churn: low(2)] [tdg: 2.5]