## Coverage Report

#### Created: 2026-01-25 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/noah/src/trueno/src/backends/sse2/ops/reductions.rs

    Line
    Count
    Source
    1
    //! SSE2 reduction operations (dot, sum, max, min, argmax, argmin).
    2
    3
    #[cfg(target_arch = "x86_64")]
    4
    use std::arch::x86_64::*;
    5
    6
    use crate::backends::VectorBackend;
    7
    8
    /// SSE2 dot product.
    9
    #[inline]
    10
    #[target_feature(enable = "sse2")]
    11
    0
    pub unsafe fn dot(a: &[f32], b: &[f32]) -> f32 {
    12
    0
        let len = a.len();
    13
    0
        let mut i = 0;
    14
    0
        let mut acc = _mm_setzero_ps();
    15
    16
    0
        while i + 4 <= len {
    17
    0
            let va = _mm_loadu_ps(a.as_ptr().add(i));
    18
    0
            let vb = _mm_loadu_ps(b.as_ptr().add(i));
    19
    0
            acc = _mm_add_ps(acc, _mm_mul_ps(va, vb));
    20
    0
            i += 4;
    21
    0
        }
    22
    23
    0
        let mut result = horizontal_sum_ps(acc);
    24
    0
        result += a[i..].iter().zip(&b[i..]).map(|(x, y)| x * y).sum::<f32>();
    25
    0
        result
    26
    0
    }
    27
    28
    /// SSE2 vector sum.
    29
    #[inline]
    30
    #[target_feature(enable = "sse2")]
    31
    0
    pub unsafe fn sum(a: &[f32]) -> f32 {
    32
    0
        let len = a.len();
    33
    0
        let mut i = 0;
    34
    0
        let mut acc = _mm_setzero_ps();
    35
    36
    0
        while i + 4 <= len {
    37
    0
            acc = _mm_add_ps(acc, _mm_loadu_ps(a.as_ptr().add(i)));
    38
    0
            i += 4;
    39
    0
        }
    40
    41
    0
        let mut result = horizontal_sum_ps(acc);
    42
    0
        result += a[i..].iter().sum::<f32>();
    43
    0
        result
    44
    0
    }
    45
    46
    /// SSE2 vector max.
    47
    #[inline]
    48
    #[target_feature(enable = "sse2")]
    49
    0
    pub unsafe fn max(a: &[f32]) -> f32 {
    50
    0
        let len = a.len();
    51
    0
        let mut i = 0;
    52
    0
        let mut vmax = _mm_set1_ps(a[0]);
    53
    54
    0
        while i + 4 <= len {
    55
    0
            vmax = _mm_max_ps(vmax, _mm_loadu_ps(a.as_ptr().add(i)));
    56
    0
            i += 4;
    57
    0
        }
    58
    59
    0
        let mut result = horizontal_max_ps(vmax);
    60
    0
        for &val in &a[i..] { if val > result { result = val; } }
    61
    0
        result
    62
    0
    }
    63
    64
    /// SSE2 vector min.
    65
    #[inline]
    66
    #[target_feature(enable = "sse2")]
    67
    0
    pub unsafe fn min(a: &[f32]) -> f32 {
    68
    0
        let len = a.len();
    69
    0
        let mut i = 0;
    70
    0
        let mut vmin = _mm_set1_ps(a[0]);
    71
    72
    0
        while i + 4 <= len {
    73
    0
            vmin = _mm_min_ps(vmin, _mm_loadu_ps(a.as_ptr().add(i)));
    74
    0
            i += 4;
    75
    0
        }
    76
    77
    0
        let mut result = horizontal_min_ps(vmin);
    78
    0
        for &val in &a[i..] { if val < result { result = val; } }
    79
    0
        result
    80
    0
    }
    81
    82
    /// SSE2 argmax.
    83
    #[inline]
    84
    #[target_feature(enable = "sse2")]
    85
    0
    pub unsafe fn argmax(a: &[f32]) -> usize {
    86
    0
        let _len = a.len();
    87
    0
        let mut max_idx: usize = 0;
    88
    0
        let mut max_val = a[0];
    89
    90
    0
        for (i, &val) in a.iter().enumerate() {
    91
    0
            if val > max_val {
    92
    0
                max_val = val;
    93
    0
                max_idx = i;
    94
    0
            }
    95
        }
    96
    0
        max_idx
    97
    0
    }
    98
    99
    /// SSE2 argmin.
    100
    #[inline]
    101
    #[target_feature(enable = "sse2")]
    102
    0
    pub unsafe fn argmin(a: &[f32]) -> usize {
    103
    0
        let _len = a.len();
    104
    0
        let mut min_idx: usize = 0;
    105
    0
        let mut min_val = a[0];
    106
    107
    0
        for (i, &val) in a.iter().enumerate() {
    108
    0
            if val < min_val {
    109
    0
                min_val = val;
    110
    0
                min_idx = i;
    111
    0
            }
    112
        }
    113
    0
        min_idx
    114
    0
    }
    115
    116
    /// Kahan sum (delegates to scalar).
    117
    #[inline]
    118
    0
    pub unsafe fn sum_kahan(a: &[f32]) -> f32 {
    119
    0
        crate::backends::scalar::ScalarBackend::sum_kahan(a)
    120
    0
    }
    121
    122
    // Helper: horizontal sum of 4 floats
    123
    #[inline]
    124
    #[target_feature(enable = "sse2")]
    125
    0
    unsafe fn horizontal_sum_ps(v: __m128) -> f32 {
    126
    0
        let temp = _mm_add_ps(v, _mm_movehl_ps(v, v));
    127
    0
        let temp = _mm_add_ss(temp, _mm_shuffle_ps(temp, temp, 1));
    128
    0
        _mm_cvtss_f32(temp)
    129
    0
    }
    130
    131
    // Helper: horizontal max of 4 floats
    132
    #[inline]
    133
    #[target_feature(enable = "sse2")]
    134
    0
    unsafe fn horizontal_max_ps(v: __m128) -> f32 {
    135
    0
        let temp = _mm_max_ps(v, _mm_movehl_ps(v, v));
    136
    0
        let temp = _mm_max_ss(temp, _mm_shuffle_ps(temp, temp, 1));
    137
    0
        _mm_cvtss_f32(temp)
    138
    0
    }
    139
    140
    // Helper: horizontal min of 4 floats
    141
    #[inline]
    142
    #[target_feature(enable = "sse2")]
    143
    0
    unsafe fn horizontal_min_ps(v: __m128) -> f32 {
    144
    0
        let temp = _mm_min_ps(v, _mm_movehl_ps(v, v));
    145
    0
        let temp = _mm_min_ss(temp, _mm_shuffle_ps(temp, temp, 1));
    146
    0
        _mm_cvtss_f32(temp)
    147
    0
    }