## Coverage Report

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

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

    /home/noah/src/realizar/src/apr/helpers.rs

    Line
    Count
    Source
    1
    //! APR inference helper functions (PMAT-802)
    2
    //!
    3
    //! Extracted from apr/mod.rs - Pure Rust inference primitives.
    4
    //!
    5
    //! ## Contents
    6
    //! - RMS normalization
    7
    //! - Matrix multiplication with SIMD
    8
    //! - Transpose operations
    9
    //! - Simple attention computation
    10
    //! - Format detection utilities
    11
    12
    use std::path::Path;
    13
    use std::fs;
    14
    use super::MAGIC;
    15
    16
    /// RMS normalization
    17
    10
    pub(crate) fn rms_norm(x: &[f32], weight: &[f32], eps: f32) -> Vec<f32> {
    18
    10
        let hidden_dim = weight.len();
    19
    10
        let seq_len = x.len() / hidden_dim;
    20
    10
        let mut output = Vec::with_capacity(x.len());
    21
    22
    13
        for s in 0..seq_len10 {
    23
    13
            let start = s * hidden_dim;
    24
    13
            let slice = &x[start..start + hidden_dim];
    25
    26
            // Compute RMS
    27
    104
            let sum_sq13: f3213 = slice13.iter13().map13(|&v| v * v).sum13();
    28
    13
            let rms = (sum_sq / hidden_dim as f32 + eps).sqrt();
    29
    30
            // Normalize and scale
    31
    104
            for (i, &v) in slice13.iter13().enumerate13() {
    32
    104
                output.push((v / rms) * weight.get(i).copied().unwrap_or(1.0));
    33
    104
            }
    34
        }
    35
    10
        output
    36
    10
    }
    37
    38
    /// Matrix multiplication with SIMD dot products
    39
    /// [seq, in_dim] @ [out_dim, in_dim]^T -> [seq, out_dim]
    40
    10
    pub(crate) fn matmul(x: &[f32], w: &[f32], seq_len: usize, in_dim: usize, out_dim: usize) -> Vec<f32> {
    41
    10
        let mut output = vec![0.0; seq_len * out_dim];
    42
    43
    15
        for s in 0..seq_len10 {
    44
    15
            let x_start = s * in_dim;
    45
    15
            let x_end = x_start + in_dim;
    46
    15
            if x_end > x.len() {
    47
    1
                continue; // Skip if out of bounds
    48
    14
            }
    49
    14
            let x_row = &x[x_start..x_end];
    50
    51
    277
            for o in 0..out_dim14 {
    52
    277
                let w_start = o * in_dim;
    53
    277
                let w_end = w_start + in_dim;
    54
    277
                if w_end > w.len() {
    55
    2
                    continue; // Skip if out of bounds
    56
    275
                }
    57
    275
                let w_row = &w[w_start..w_end];
    58
                // SIMD dot product
    59
    275
                output[s * out_dim + o] = simd_dot(x_row, w_row);
    60
            }
    61
        }
    62
    10
        output
    63
    10
    }
    64
    65
    /// Transpose a matrix from [rows, cols] to [cols, rows] for GEMM compatibility.
    66
    /// Weight matrices are stored as [out_dim, in_dim] but GEMM needs [in_dim, out_dim].
    67
    #[cfg(feature = "cuda")]
    68
    pub(crate) fn transpose_matrix(m: &[f32], rows: usize, cols: usize) -> Vec<f32> {
    69
        let mut transposed = vec![0.0f32; rows * cols];
    70
        for r in 0..rows {
    71
            for c in 0..cols {
    72
                // m[r, c] -> transposed[c, r]
    73
                let src_idx = r * cols + c;
    74
                let dst_idx = c * rows + r;
    75
                if src_idx < m.len() && dst_idx < transposed.len() {
    76
                    transposed[dst_idx] = m[src_idx];
    77
                }
    78
            }
    79
        }
    80
        transposed
    81
    }
    82
    83
    /// SIMD-accelerated dot product
    84
    #[inline]
    85
    286
    pub fn simd_dot(a: &[f32], b: &[f32]) -> f32 {
    86
        #[cfg(target_arch = "x86_64")]
    87
        {
    88
    286
            if is_x86_feature_detected!("avx2") {
    89
                // SAFETY: AVX2 feature is runtime-checked above, simd_dot_avx2 requires AVX2
    90
    286
                return unsafe { simd_dot_avx2(a, b) };
    91
    0
            }
    92
        }
    93
        // Scalar fallback
    94
    0
        a.iter().zip(b.iter()).map(|(x, y)| x * y).sum()
    95
    286
    }
    96
    97
    #[cfg(target_arch = "x86_64")]
    98
    #[target_feature(enable = "avx2", enable = "fma")]
    99
    286
    unsafe fn simd_dot_avx2(a: &[f32], b: &[f32]) -> f32 {
    100
        use std::arch::x86_64::{
    101
            _mm256_castps256_ps128, _mm256_extractf128_ps, _mm256_fmadd_ps, _mm256_loadu_ps,
    102
            _mm256_setzero_ps, _mm_add_ps, _mm_add_ss, _mm_cvtss_f32, _mm_movehl_ps, _mm_shuffle_ps,
    103
        };
    104
    105
    286
        let n = a.len().min(b.len());
    106
    286
        let chunks = n / 8;
    107
    108
        // SAFETY: This entire fn is unsafe with target_feature(avx2, fma)
    109
        // All intrinsics are safe to call given the target_feature guarantee
    110
        // The unsafe block is required for Rust 2024 edition compliance
    111
        unsafe {
    112
    286
            let mut sum = _mm256_setzero_ps();
    113
    114
    2.08k
            for i in 0..chunks286 {
    115
    2.08k
                let av = _mm256_loadu_ps(a.as_ptr().add(i * 8));
    116
    2.08k
                let bv = _mm256_loadu_ps(b.as_ptr().add(i * 8));
    117
    2.08k
                sum = _mm256_fmadd_ps(av, bv, sum);
    118
    2.08k
            }
    119
    120
            // Horizontal sum
    121
    286
            let hi = _mm256_extractf128_ps(sum, 1);
    122
    286
            let lo = _mm256_castps256_ps128(sum);
    123
    286
            let sum128 = _mm_add_ps(lo, hi);
    124
    286
            let sum64 = _mm_add_ps(sum128, _mm_movehl_ps(sum128, sum128));
    125
    286
            let sum32 = _mm_add_ss(sum64, _mm_shuffle_ps(sum64, sum64, 1));
    126
    286
            let mut result = _mm_cvtss_f32(sum32);
    127
    128
            // Handle remainder (scalar)
    129
    286
            for i67 in (chunks * 8)..n {
    130
    67
                result += a.get(i).copied().unwrap_or(0.0) * b.get(i).copied().unwrap_or(0.0);
    131
    67
            }
    132
    133
    286
            result
    134
        }
    135
    286
    }
    136
    137
    /// Simplified multi-head attention (no RoPE, causal mask)
    138
    7
    pub(crate) fn simple_attention(
    139
    7
        q: &[f32],
    140
    7
        k: &[f32],
    141
    7
        v: &[f32],
    142
    7
        seq_len: usize,
    143
    7
        num_heads: usize,
    144
    7
        num_kv_heads: usize,
    145
    7
        head_dim: usize,
    146
    7
    ) -> Vec<f32> {
    147
    7
        let hidden_dim = num_heads * head_dim;
    148
    7
        let kv_dim = num_kv_heads * head_dim;
    149
    7
        let heads_per_kv = num_heads / num_kv_heads;
    150
    7
        let scale = 1.0 / (head_dim as f32).sqrt();
    151
    152
    7
        let mut output = vec![0.0; seq_len * hidden_dim];
    153
    154
    10
        for s in 0..seq_len7 {
    155
    21
            for h in 0..num_heads10 {
    156
    21
                let kv_h = h / heads_per_kv;
    157
    158
                // Compute attention scores for this head
    159
    21
                let mut scores = vec![0.0; seq_len];
    160
    30
                for t in 0..=s21 {
    161
                    // Causal: only attend to past
    162
    30
                    let mut score = 0.0;
    163
    96
                    for d in 0..head_dim30 {
    164
    96
                        let q_val = q
    165
    96
                            .get(s * hidden_dim + h * head_dim + d)
    166
    96
                            .copied()
    167
    96
                            .unwrap_or(0.0);
    168
    96
                        let k_val = k
    169
    96
                            .get(t * kv_dim + kv_h * head_dim + d)
    170
    96
                            .copied()
    171
    96
                            .unwrap_or(0.0);
    172
    96
                        score += q_val * k_val;
    173
    96
                    }
    174
    30
                    scores[t] = score * scale;
    175
                }
    176
    177
                // Softmax
    178
    21
                let max_score = scores[..=s]
    179
    21
                    .iter()
    180
    21
                    .cloned()
    181
    21
                    .fold(f32::NEG_INFINITY, f32::max);
    182
    21
                let mut sum = 0.0;
    183
    30
                for score in &mut scores[..=s]21 {
    184
    30
                    *score = (*score - max_score).exp();
    185
    30
                    sum += *score;
    186
    30
                }
    187
    30
                for score in &mut scores[..=s]21 {
    188
    30
                    *score /= sum;
    189
    30
                }
    190
    191
                // Weighted sum of values
    192
    62
                for d in 0..head_dim21 {
    193
    62
                    let mut val = 0.0;
    194
    96
                    for t in 0..=s62 {
    195
    96
                        let v_val = v
    196
    96
                            .get(t * kv_dim + kv_h * head_dim + d)
    197
    96
                            .copied()
    198
    96
                            .unwrap_or(0.0);
    199
    96
                        val += scores[t] * v_val;
    200
    96
                    }
    201
    62
                    output[s * hidden_dim + h * head_dim + d] = val;
    202
                }
    203
            }
    204
        }
    205
    206
    7
        output
    207
    7
    }
    208
    209
    /// Check if a file is a valid .apr v2 file
    210
    13
    pub fn is_apr_file<P: AsRef<Path>>(path: P) -> bool {
    211
    13
        fs::read(path.as_ref()).is_ok_and(|data| data.len() >= 45 && data[0..4] == MAGIC5)
    212
    13
    }
    213
    214
    /// Detect model format from magic bytes
    215
    15
    pub fn detect_format<P: AsRef<Path>>(path: P) -> &'static str {
    216
    15
        let path = path.as_ref();
    217
    218
    15
        if let Some(ext10) = path.extension() {
    219
    10
            let ext = ext.to_string_lossy().to_lowercase();
    220
    10
            match ext.as_str() {
    221
    10
                "apr" => return "apr"2,
    222
    8
                "gguf" => return "gguf"2,
    223
    6
                "safetensors" => return "safetensors"2,
    224
    4
                _ => {},
    225
            }
    226
    5
        }
    227
    228
    9
        if let Ok(data3) = fs::read(path) {
    229
    3
            if data.len() >= 4 {
    230
    3
                if data[0..4] == MAGIC {
    231
    1
                    return "apr";
    232
    2
                }
    233
    2
                if data[0..4] == [0x47, 0x47, 0x55, 0x46] {
    234
    1
                    return "gguf";
    235
    1
                }
    236
    1
                if data[0] == b'{' {
    237
    1
                    return "safetensors";
    238
    0
                }
    239
    0
            }
    240
    6
        }
    241
    242
    6
        "unknown"
    243
    15
    }