## 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/vector/mod.rs

    Line
    Count
    Source
    1
    //! Vector type with multi-backend support
    2
    //!
    3
    //! This module provides the core `Vector<T>` type with SIMD-optimized operations
    4
    //! across multiple backends (Scalar, SSE2, AVX2, AVX-512, NEON, WASM SIMD).
    5
    //!
    6
    //! GPU thresholds intentionally set to usize::MAX to disable GPU for element-wise ops.
    7
    //! See docs/performance-analysis.md - GPU is 2-65,000x SLOWER than scalar for these ops.
    8
    9
    #![allow(clippy::absurd_extreme_comparisons)]
    10
    11
    // Submodules
    12
    pub mod dispatch;
    13
    mod ops;
    14
    15
    // Tests (~10K lines extracted for TDG compliance)
    16
    #[cfg(test)]
    17
    mod tests;
    18
    19
    use crate::{Backend, Result, TruenoError};
    20
    21
    /// High-performance vector with multi-backend support
    22
    ///
    23
    /// # Examples
    24
    ///
    25
    /// ```
    26
    /// use trueno::Vector;
    27
    ///
    28
    /// let a = Vector::from_slice(&[1.0, 2.0, 3.0]);
    29
    /// let b = Vector::from_slice(&[4.0, 5.0, 6.0]);
    30
    /// let result = a.add(&b).unwrap();
    31
    ///
    32
    /// assert_eq!(result.as_slice(), &[5.0, 7.0, 9.0]);
    33
    /// ```
    34
    #[derive(Debug, Clone, PartialEq)]
    35
    pub struct Vector<T> {
    36
        data: Vec<T>,
    37
        backend: Backend,
    38
    }
    39
    40
    impl<T> Vector<T>
    41
    where
    42
        T: Clone,
    43
    {
    44
        /// Create vector from slice using auto-selected optimal backend
    45
        ///
    46
        /// # Performance
    47
        ///
    48
        /// Auto-selects the best available backend at creation time based on:
    49
        /// - CPU feature detection (AVX-512 > AVX2 > AVX > SSE2)
    50
        /// - Vector size (GPU for large workloads)
    51
        /// - Platform availability (NEON on ARM, WASM SIMD in browser)
    52
        ///
    53
        /// # Examples
    54
        ///
    55
        /// ```
    56
        /// use trueno::Vector;
    57
        ///
    58
        /// let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0]);
    59
        /// assert_eq!(v.len(), 4);
    60
        /// ```
    61
    247k
        pub fn from_slice(data: &[T]) -> Self {
    62
    247k
            Self {
    63
    247k
                data: data.to_vec(),
    64
    247k
                backend: crate::select_best_available_backend(),
    65
    247k
            }
    66
    247k
        }
    67
    68
        /// Create vector from an existing Vec (takes ownership, no copy)
    69
        ///
    70
        /// This is more efficient than `from_slice` when you already have a Vec
    71
        /// and don't need to keep it, as it avoids an extra allocation and copy.
    72
        ///
    73
        /// # Examples
    74
        ///
    75
        /// ```
    76
        /// use trueno::Vector;
    77
        ///
    78
        /// let data = vec![1.0, 2.0, 3.0];
    79
        /// let v = Vector::from_vec(data);
    80
        /// assert_eq!(v.len(), 3);
    81
        /// ```
    82
    10.7k
        pub fn from_vec(data: Vec<T>) -> Self {
    83
    10.7k
            Self {
    84
    10.7k
                data,
    85
    10.7k
                backend: crate::select_best_available_backend(),
    86
    10.7k
            }
    87
    10.7k
        }
    88
    89
        /// Create vector with specific backend (for benchmarking or testing)
    90
        ///
    91
        /// # Examples
    92
        ///
    93
        /// ```
    94
        /// use trueno::{Vector, Backend};
    95
        ///
    96
        /// let v = Vector::from_slice_with_backend(&[1.0, 2.0], Backend::Scalar);
    97
        /// assert_eq!(v.len(), 2);
    98
        /// ```
    99
    0
        pub fn from_slice_with_backend(data: &[T], backend: Backend) -> Self {
    100
    0
            let resolved_backend = match backend {
    101
    0
                Backend::Auto => crate::select_best_available_backend(),
    102
    0
                _ => backend,
    103
            };
    104
    105
    0
            Self {
    106
    0
                data: data.to_vec(),
    107
    0
                backend: resolved_backend,
    108
    0
            }
    109
    0
        }
    110
    }
    111
    112
    impl Vector<f32> {
    113
        /// Create vector with specified alignment for optimal SIMD performance
    114
        ///
    115
        /// This method attempts to create a vector with memory aligned to the specified byte boundary.
    116
        /// Note: Rust's Vec allocator may already provide sufficient alignment for most use cases.
    117
        /// This method validates the alignment requirement but uses standard Vec allocation.
    118
        ///
    119
        /// # Arguments
    120
        ///
    121
        /// * `size` - Number of elements to allocate
    122
        /// * `backend` - Backend to use for operations
    123
        /// * `alignment` - Requested alignment in bytes (must be power of 2: 16, 32, 64)
    124
        ///
    125
        /// # Recommended Alignments
    126
        ///
    127
        /// - SSE2: 16 bytes (128-bit)
    128
        /// - AVX2: 32 bytes (256-bit)
    129
        /// - AVX-512: 64 bytes (512-bit)
    130
        ///
    131
        /// # Note on Implementation
    132
        ///
    133
        /// Currently uses Rust's default Vec allocator, which typically provides 16-byte alignment
    134
        /// on modern systems. Custom allocators for specific alignments will be added in future versions.
    135
        ///
    136
        /// # Examples
    137
        ///
    138
        /// ```
    139
        /// use trueno::{Vector, Backend};
    140
        ///
    141
        /// // Create vector with requested 16-byte alignment
    142
        /// let v = Vector::with_alignment(100, Backend::SSE2, 16).unwrap();
    143
        /// assert_eq!(v.len(), 100);
    144
        /// ```
    145
        ///
    146
        /// # Errors
    147
        ///
    148
        /// Returns `TruenoError::InvalidInput` if alignment is not a power of 2.
    149
    0
        pub fn with_alignment(size: usize, backend: Backend, alignment: usize) -> Result<Self> {
    150
            // Validate alignment is power of 2
    151
    0
            if alignment == 0 || (alignment & (alignment - 1)) != 0 {
    152
    0
                return Err(TruenoError::InvalidInput(format!(
    153
    0
                    "Alignment must be power of 2, got {}",
    154
    0
                    alignment
    155
    0
                )));
    156
    0
            }
    157
    158
            // Resolve backend
    159
    0
            let resolved_backend = match backend {
    160
    0
                Backend::Auto => crate::select_best_available_backend(),
    161
    0
                _ => backend,
    162
            };
    163
    164
            // For now, use standard Vec allocation which typically provides good alignment
    165
            // Future enhancement: use custom allocator for guaranteed alignment > 16 bytes
    166
    0
            let data = vec![0.0f32; size];
    167
    168
            // Verify actual alignment (for informational purposes)
    169
    0
            let ptr = data.as_ptr() as usize;
    170
    0
            let actual_alignment = ptr & !(ptr - 1); // Find lowest set bit
    171
    172
            // Log warning if alignment requirement not met (for future enhancement)
    173
    0
            if alignment > actual_alignment {
    174
    0
                // Note: This is not an error, just informational
    175
    0
                // The unaligned loads in SSE2 (_mm_loadu_ps) will still work correctly
    176
    0
                eprintln!(
    177
    0
                    "Note: Requested {}-byte alignment, got {}-byte alignment. Using unaligned loads.",
    178
    0
                    alignment, actual_alignment
    179
    0
                );
    180
    0
            }
    181
    182
    0
            Ok(Self {
    183
    0
                data,
    184
    0
                backend: resolved_backend,
    185
    0
            })
    186
    0
        }
    187
    }
    188
    189
    impl<T> Vector<T>
    190
    where
    191
        T: Clone,
    192
    {
    193
        /// Get underlying data as slice
    194
        ///
    195
        /// # Examples
    196
        ///
    197
        /// ```
    198
        /// use trueno::Vector;
    199
        ///
    200
        /// let v = Vector::from_slice(&[1.0, 2.0, 3.0]);
    201
        /// assert_eq!(v.as_slice(), &[1.0, 2.0, 3.0]);
    202
        /// ```
    203
    10.6k
        pub fn as_slice(&self) -> &[T] {
    204
    10.6k
            &self.data
    205
    10.6k
        }
    206
    207
        /// Get vector length
    208
        ///
    209
        /// # Examples
    210
        ///
    211
        /// ```
    212
        /// use trueno::Vector;
    213
        ///
    214
        /// let v = Vector::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);
    215
        /// assert_eq!(v.len(), 5);
    216
        /// ```
    217
    452k
        pub fn len(&self) -> usize {
    218
    452k
            self.data.len()
    219
    452k
        }
    220
    221
        /// Check if vector is empty
    222
        ///
    223
        /// # Examples
    224
        ///
    225
        /// ```
    226
        /// use trueno::Vector;
    227
        ///
    228
        /// let v1: Vector<f32> = Vector::from_slice(&[]);
    229
        /// assert!(v1.is_empty());
    230
        ///
    231
        /// let v2 = Vector::from_slice(&[1.0]);
    232
        /// assert!(!v2.is_empty());
    233
        /// ```
    234
    0
        pub fn is_empty(&self) -> bool {
    235
    0
            self.data.is_empty()
    236
    0
        }
    237
    238
        /// Get the backend being used
    239
    0
        pub fn backend(&self) -> Backend {
    240
    0
            self.backend
    241
    0
        }
    242
    }
    243
    244
    // Note: Vector<f32> operations have been moved to submodules in ops/:
    245
    // - ops/normalization.rs: zscore, minmax_normalize, layer_norm, layer_norm_simple, normalize
    246
    // - ops/norms.rs: norm_l1, norm_l2, norm_linf
    247
    // - ops/transforms.rs: abs, clamp, clip, lerp, sqrt, recip, pow
    248
    // - ops/arithmetic.rs: add, sub, mul, div, scale, fma
    249
    // - ops/reductions.rs: dot, sum, max, min, argmax, argmin, mean, variance, stddev, covariance, correlation
    250
    // - ops/activations.rs: relu, sigmoid, gelu, etc.
    251
    // - ops/transcendental.rs: exp, log, sin, cos, etc.
    252
    // - ops/rounding.rs: floor, ceil, round, trunc, etc.
    253