## 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/ops/transforms.rs

    Line
    Count
    Source
    1
    //! Vector transformation operations
    2
    //!
    3
    //! This module provides element-wise transformation methods:
    4
    //! - `abs()` - Element-wise absolute value
    5
    //! - `clamp()` / `clip()` - Clamp values to a range
    6
    //! - `lerp()` - Linear interpolation between two vectors
    7
    //! - `sqrt()` - Element-wise square root
    8
    //! - `recip()` - Element-wise reciprocal (1/x)
    9
    //! - `pow()` - Element-wise power
    10
    11
    #[cfg(target_arch = "x86_64")]
    12
    use crate::backends::avx2::Avx2Backend;
    13
    #[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
    14
    use crate::backends::neon::NeonBackend;
    15
    use crate::backends::scalar::ScalarBackend;
    16
    #[cfg(target_arch = "x86_64")]
    17
    use crate::backends::sse2::Sse2Backend;
    18
    #[cfg(target_arch = "wasm32")]
    19
    use crate::backends::wasm::WasmBackend;
    20
    use crate::backends::VectorBackend;
    21
    use crate::dispatch_unary_op;
    22
    use crate::{Backend, Result, TruenoError, Vector};
    23
    24
    impl Vector<f32> {
    25
        /// Compute element-wise absolute value
    26
        ///
    27
        /// Returns a new vector where each element is the absolute value of the corresponding input element.
    28
        ///
    29
        /// # Examples
    30
        ///
    31
        /// ```
    32
        /// use trueno::Vector;
    33
        ///
    34
        /// let v = Vector::from_slice(&[3.0, -4.0, 5.0, -2.0]);
    35
        /// let result = v.abs().unwrap();
    36
        ///
    37
        /// assert_eq!(result.as_slice(), &[3.0, 4.0, 5.0, 2.0]);
    38
        /// ```
    39
        ///
    40
        /// # Empty Vector
    41
        ///
    42
        /// ```
    43
        /// use trueno::Vector;
    44
        ///
    45
        /// let v: Vector<f32> = Vector::from_slice(&[]);
    46
        /// let result = v.abs().unwrap();
    47
        /// assert_eq!(result.len(), 0);
    48
        /// ```
    49
    0
        pub fn abs(&self) -> Result<Vector<f32>> {
    50
    0
            let mut result_data = vec![0.0; self.len()];
    51
    52
    0
            if !self.as_slice().is_empty() {
    53
                // SAFETY: Unsafe block delegates to backend implementation which maintains safety invariants
    54
                unsafe {
    55
    0
                    match self.backend() {
    56
    0
                        Backend::Scalar => ScalarBackend::abs(self.as_slice(), &mut result_data),
    57
                        #[cfg(target_arch = "x86_64")]
    58
                        Backend::SSE2 | Backend::AVX => {
    59
    0
                            Sse2Backend::abs(self.as_slice(), &mut result_data)
    60
                        }
    61
                        #[cfg(target_arch = "x86_64")]
    62
                        Backend::AVX2 | Backend::AVX512 => {
    63
    0
                            Avx2Backend::abs(self.as_slice(), &mut result_data)
    64
                        }
    65
                        #[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
    66
                        Backend::NEON => NeonBackend::abs(self.as_slice(), &mut result_data),
    67
                        #[cfg(target_arch = "wasm32")]
    68
                        Backend::WasmSIMD => WasmBackend::abs(self.as_slice(), &mut result_data),
    69
    0
                        Backend::GPU => return Err(TruenoError::UnsupportedBackend(Backend::GPU)),
    70
                        Backend::Auto => {
    71
    0
                            return Err(TruenoError::UnsupportedBackend(Backend::Auto));
    72
                        }
    73
                        #[allow(unreachable_patterns)]
    74
    0
                        _ => ScalarBackend::abs(self.as_slice(), &mut result_data),
    75
                    }
    76
                }
    77
    0
            }
    78
    79
    0
            Ok(Vector::from_slice_with_backend(&result_data, self.backend()))
    80
    0
        }
    81
    82
        /// Clip values to a specified range [min_val, max_val]
    83
        ///
    84
        /// Constrains each element to be within the specified range:
    85
        /// - Values below min_val become min_val
    86
        /// - Values above max_val become max_val
    87
        /// - Values within range stay unchanged
    88
        ///
    89
        /// This is useful for outlier handling, gradient clipping in neural networks,
    90
        /// and ensuring values stay within valid bounds.
    91
        ///
    92
        /// # Examples
    93
        ///
    94
        /// ```
    95
        /// use trueno::Vector;
    96
        ///
    97
        /// let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);
    98
        /// let clipped = v.clip(0.0, 10.0).unwrap();
    99
        ///
    100
        /// // Values: [-5, 0, 5, 10, 15] → [0, 0, 5, 10, 10]
    101
        /// assert_eq!(clipped.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);
    102
        /// ```
    103
        ///
    104
        /// # Invalid range
    105
        ///
    106
        /// Returns InvalidInput error if min_val > max_val.
    107
        ///
    108
        /// ```
    109
        /// use trueno::{Vector, TruenoError};
    110
        ///
    111
        /// let v = Vector::from_slice(&[1.0, 2.0, 3.0]);
    112
        /// let result = v.clip(10.0, 5.0); // min > max
    113
        /// assert!(matches!(result, Err(TruenoError::InvalidInput(_))));
    114
        /// ```
    115
    0
        pub fn clip(&self, min_val: f32, max_val: f32) -> Result<Self> {
    116
    0
            if min_val > max_val {
    117
    0
                return Err(TruenoError::InvalidInput(format!(
    118
    0
                    "min_val ({}) must be <= max_val ({})",
    119
    0
                    min_val, max_val
    120
    0
                )));
    121
    0
            }
    122
    123
            // Scalar fallback: Element-wise clamp
    124
    0
            let data: Vec<f32> = self
    125
    0
                .as_slice()
    126
    0
                .iter()
    127
    0
                .map(|&x| x.max(min_val).min(max_val))
    128
    0
                .collect();
    129
    130
    0
            Ok(Vector::from_vec(data))
    131
    0
        }
    132
    133
        /// Clamp elements to range [min_val, max_val]
    134
        ///
    135
        /// Returns a new vector where each element is constrained to the specified range.
    136
        /// Elements below min_val become min_val, elements above max_val become max_val.
    137
        ///
    138
        /// # Examples
    139
        ///
    140
        /// ```
    141
        /// use trueno::Vector;
    142
        ///
    143
        /// let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);
    144
        /// let result = v.clamp(0.0, 10.0).unwrap();
    145
        ///
    146
        /// assert_eq!(result.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);
    147
        /// ```
    148
        ///
    149
        /// # Negative Range
    150
        ///
    151
        /// ```
    152
        /// use trueno::Vector;
    153
        ///
    154
        /// let v = Vector::from_slice(&[-10.0, -5.0, 0.0, 5.0]);
    155
        /// let result = v.clamp(-8.0, -2.0).unwrap();
    156
        /// assert_eq!(result.as_slice(), &[-8.0, -5.0, -2.0, -2.0]);
    157
        /// ```
    158
        ///
    159
        /// # Errors
    160
        ///
    161
        /// Returns `InvalidInput` if min_val > max_val.
    162
    0
        pub fn clamp(&self, min_val: f32, max_val: f32) -> Result<Vector<f32>> {
    163
            // Validate range
    164
    0
            if min_val > max_val {
    165
    0
                return Err(TruenoError::InvalidInput(format!(
    166
    0
                    "Invalid clamp range: min ({}) > max ({})",
    167
    0
                    min_val, max_val
    168
    0
                )));
    169
    0
            }
    170
    171
    0
            let mut result_data = vec![0.0; self.len()];
    172
    173
    0
            if !self.as_slice().is_empty() {
    174
                // SAFETY: Unsafe block delegates to backend implementation which maintains safety invariants
    175
                unsafe {
    176
    0
                    match self.backend() {
    177
                        Backend::Scalar => {
    178
    0
                            ScalarBackend::clamp(self.as_slice(), min_val, max_val, &mut result_data)
    179
                        }
    180
                        #[cfg(target_arch = "x86_64")]
    181
                        Backend::SSE2 | Backend::AVX => {
    182
    0
                            Sse2Backend::clamp(self.as_slice(), min_val, max_val, &mut result_data)
    183
                        }
    184
                        #[cfg(target_arch = "x86_64")]
    185
                        Backend::AVX2 | Backend::AVX512 => {
    186
    0
                            Avx2Backend::clamp(self.as_slice(), min_val, max_val, &mut result_data)
    187
                        }
    188
                        #[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
    189
                        Backend::NEON => {
    190
                            NeonBackend::clamp(self.as_slice(), min_val, max_val, &mut result_data)
    191
                        }
    192
                        #[cfg(target_arch = "wasm32")]
    193
                        Backend::WasmSIMD => {
    194
                            WasmBackend::clamp(self.as_slice(), min_val, max_val, &mut result_data)
    195
                        }
    196
    0
                        Backend::GPU => return Err(TruenoError::UnsupportedBackend(Backend::GPU)),
    197
                        Backend::Auto => {
    198
    0
                            return Err(TruenoError::UnsupportedBackend(Backend::Auto));
    199
                        }
    200
                        #[allow(unreachable_patterns)]
    201
                        _ => {
    202
    0
                            ScalarBackend::clamp(self.as_slice(), min_val, max_val, &mut result_data)
    203
                        }
    204
                    }
    205
                }
    206
    0
            }
    207
    208
    0
            Ok(Vector::from_slice_with_backend(&result_data, self.backend()))
    209
    0
        }
    210
    211
        /// Linear interpolation between two vectors
    212
        ///
    213
        /// Computes element-wise linear interpolation: `result\[i\] = a\[i\] + t * (b\[i\] - a\[i\])`
    214
        ///
    215
        /// - When `t = 0.0`, returns `self`
    216
        /// - When `t = 1.0`, returns `other`
    217
        /// - Values outside `[0, 1]` perform extrapolation
    218
        ///
    219
        /// # Examples
    220
        ///
    221
        /// ```
    222
        /// use trueno::Vector;
    223
        ///
    224
        /// let a = Vector::from_slice(&[0.0, 10.0, 20.0]);
    225
        /// let b = Vector::from_slice(&[100.0, 110.0, 120.0]);
    226
        /// let result = a.lerp(&b, 0.5).unwrap();
    227
        ///
    228
        /// assert_eq!(result.as_slice(), &[50.0, 60.0, 70.0]);
    229
        /// ```
    230
        ///
    231
        /// # Extrapolation
    232
        ///
    233
        /// ```
    234
        /// use trueno::Vector;
    235
        ///
    236
        /// let a = Vector::from_slice(&[0.0, 10.0]);
    237
        /// let b = Vector::from_slice(&[10.0, 20.0]);
    238
        ///
    239
        /// // t > 1.0 extrapolates beyond b
    240
        /// let result = a.lerp(&b, 2.0).unwrap();
    241
        /// assert_eq!(result.as_slice(), &[20.0, 30.0]);
    242
        /// ```
    243
        ///
    244
        /// # Errors
    245
        ///
    246
        /// Returns `SizeMismatch` if vectors have different lengths.
    247
    0
        pub fn lerp(&self, other: &Vector<f32>, t: f32) -> Result<Vector<f32>> {
    248
    0
            if self.len() != other.len() {
    249
    0
                return Err(TruenoError::SizeMismatch {
    250
    0
                    expected: self.len(),
    251
    0
                    actual: other.len(),
    252
    0
                });
    253
    0
            }
    254
    255
    0
            let mut result_data = vec![0.0; self.len()];
    256
    257
    0
            if !self.as_slice().is_empty() {
    258
                // SAFETY: Unsafe block delegates to backend implementation which maintains safety invariants
    259
                unsafe {
    260
    0
                    match self.backend() {
    261
                        Backend::Scalar => {
    262
    0
                            ScalarBackend::lerp(self.as_slice(), other.as_slice(), t, &mut result_data)
    263
                        }
    264
                        #[cfg(target_arch = "x86_64")]
    265
                        Backend::SSE2 | Backend::AVX => {
    266
    0
                            Sse2Backend::lerp(self.as_slice(), other.as_slice(), t, &mut result_data)
    267
                        }
    268
                        #[cfg(target_arch = "x86_64")]
    269
                        Backend::AVX2 | Backend::AVX512 => {
    270
    0
                            Avx2Backend::lerp(self.as_slice(), other.as_slice(), t, &mut result_data)
    271
                        }
    272
                        #[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
    273
                        Backend::NEON => {
    274
                            NeonBackend::lerp(self.as_slice(), other.as_slice(), t, &mut result_data)
    275
                        }
    276
                        #[cfg(target_arch = "wasm32")]
    277
                        Backend::WasmSIMD => {
    278
                            WasmBackend::lerp(self.as_slice(), other.as_slice(), t, &mut result_data)
    279
                        }
    280
    0
                        Backend::GPU => return Err(TruenoError::UnsupportedBackend(Backend::GPU)),
    281
                        Backend::Auto => {
    282
    0
                            return Err(TruenoError::UnsupportedBackend(Backend::Auto));
    283
                        }
    284
                        #[allow(unreachable_patterns)]
    285
                        _ => {
    286
    0
                            ScalarBackend::lerp(self.as_slice(), other.as_slice(), t, &mut result_data)
    287
                        }
    288
                    }
    289
                }
    290
    0
            }
    291
    292
    0
            Ok(Vector::from_slice_with_backend(&result_data, self.backend()))
    293
    0
        }
    294
    295
        /// Element-wise square root: result\[i\] = sqrt(self\[i\])
    296
        ///
    297
        /// Computes the square root of each element. For negative values, returns NaN
    298
        /// following IEEE 754 floating-point semantics.
    299
        ///
    300
        /// # Returns
    301
        ///
    302
        /// A new vector where each element is the square root of the corresponding input element
    303
        ///
    304
        /// # Examples
    305
        ///
    306
        /// ```
    307
        /// use trueno::Vector;
    308
        ///
    309
        /// let a = Vector::from_slice(&[4.0, 9.0, 16.0, 25.0]);
    310
        /// let result = a.sqrt().unwrap();
    311
        /// assert_eq!(result.as_slice(), &[2.0, 3.0, 4.0, 5.0]);
    312
        /// ```
    313
        ///
    314
        /// Negative values produce NaN:
    315
        /// ```
    316
        /// use trueno::Vector;
    317
        ///
    318
        /// let a = Vector::from_slice(&[-1.0, 4.0]);
    319
        /// let result = a.sqrt().unwrap();
    320
        /// assert!(result.as_slice()[0].is_nan());
    321
        /// assert_eq!(result.as_slice()[1], 2.0);
    322
        /// ```
    323
        ///
    324
        /// # Use Cases
    325
        ///
    326
        /// - Distance calculations: Euclidean distance computation
    327
        /// - Statistics: Standard deviation, RMS (root mean square)
    328
        /// - Machine learning: Normalization, gradient descent with adaptive learning rates
    329
        /// - Signal processing: Amplitude calculations, power spectrum analysis
    330
        /// - Physics simulations: Velocity from kinetic energy, wave propagation
    331
    0
        pub fn sqrt(&self) -> Result<Vector<f32>> {
    332
    0
            let mut result_data = vec![0.0; self.len()];
    333
    334
    0
            if !self.as_slice().is_empty() {
    335
                // Use parallel processing for large arrays
    336
                #[cfg(feature = "parallel")]
    337
                {
    338
                    const PARALLEL_THRESHOLD: usize = 100_000;
    339
                    const CHUNK_SIZE: usize = 65536;
    340
    341
                    if self.len() >= PARALLEL_THRESHOLD {
    342
                        use rayon::prelude::*;
    343
    344
                        self.as_slice()
    345
                            .par_chunks(CHUNK_SIZE)
    346
                            .zip(result_data.par_chunks_mut(CHUNK_SIZE))
    347
                            .for_each(|(chunk_in, chunk_out)| {
    348
                                dispatch_unary_op!(self.backend(), sqrt, chunk_in, chunk_out);
    349
                            });
    350
    351
                        return Ok(Vector::from_slice_with_backend(&result_data, self.backend()));
    352
                    }
    353
                }
    354
    355
    0
                dispatch_unary_op!(self.backend(), sqrt, self.as_slice(), &mut result_data);
    356
    0
            }
    357
    358
    0
            Ok(Vector::from_slice_with_backend(&result_data, self.backend()))
    359
    0
        }
    360
    361
        /// Element-wise reciprocal: result\[i\] = 1 / self\[i\]
    362
        ///
    363
        /// Computes the reciprocal (multiplicative inverse) of each element.
    364
        /// For zero values, returns infinity following IEEE 754 floating-point semantics.
    365
        ///
    366
        /// # Returns
    367
        ///
    368
        /// A new vector where each element is the reciprocal of the corresponding input element
    369
        ///
    370
        /// # Examples
    371
        ///
    372
        /// ```
    373
        /// use trueno::Vector;
    374
        ///
    375
        /// let a = Vector::from_slice(&[2.0, 4.0, 5.0, 10.0]);
    376
        /// let result = a.recip().unwrap();
    377
        /// assert_eq!(result.as_slice(), &[0.5, 0.25, 0.2, 0.1]);
    378
        /// ```
    379
        ///
    380
        /// Zero values produce infinity:
    381
        /// ```
    382
        /// use trueno::Vector;
    383
        ///
    384
        /// let a = Vector::from_slice(&[0.0, 2.0]);
    385
        /// let result = a.recip().unwrap();
    386
        /// assert!(result.as_slice()[0].is_infinite());
    387
        /// assert_eq!(result.as_slice()[1], 0.5);
    388
        /// ```
    389
        ///
    390
        /// # Use Cases
    391
        ///
    392
        /// - Division optimization: `a / b` → `a * recip(b)` (multiplication is faster)
    393
        /// - Neural networks: Learning rate schedules, weight normalization
    394
        /// - Statistics: Harmonic mean calculations, inverse transformations
    395
        /// - Physics: Resistance (R = 1/G), optical power (P = 1/f)
    396
        /// - Signal processing: Frequency to period conversion, filter design
    397
    0
        pub fn recip(&self) -> Result<Vector<f32>> {
    398
    0
            let mut result_data = vec![0.0; self.len()];
    399
    400
    0
            if !self.as_slice().is_empty() {
    401
    0
                dispatch_unary_op!(self.backend(), recip, self.as_slice(), &mut result_data);
    402
    0
            }
    403
    404
    0
            Ok(Vector::from_slice_with_backend(&result_data, self.backend()))
    405
    0
        }
    406
    407
        /// Element-wise power: result\[i\] = base\[i\]^n
    408
        ///
    409
        /// Raises each element to the given power `n`.
    410
        /// Uses Rust's optimized f32::powf() method.
    411
        ///
    412
        /// # Examples
    413
        ///
    414
        /// ```
    415
        /// use trueno::Vector;
    416
        ///
    417
        /// let v = Vector::from_slice(&[2.0, 3.0, 4.0]);
    418
        /// let squared = v.pow(2.0).unwrap();
    419
        /// assert_eq!(squared.as_slice(), &[4.0, 9.0, 16.0]);
    420
        ///
    421
        /// let sqrt = v.pow(0.5).unwrap();  // Fractional power = root
    422
        /// ```
    423
        ///
    424
        /// # Special Cases
    425
        ///
    426
        /// - `x.pow(0.0)` returns 1.0 for all x (even x=0)
    427
        /// - `x.pow(1.0)` returns x (identity)
    428
        /// - `x.pow(-1.0)` returns 1/x (reciprocal)
    429
        /// - `x.pow(0.5)` returns sqrt(x) (square root)
    430
        ///
    431
        /// # Applications
    432
        ///
    433
        /// - Statistics: Power transformations (Box-Cox, Yeo-Johnson)
    434
        /// - Machine learning: Polynomial features, activation functions
    435
        /// - Physics: Inverse square law (1/r²), power laws
    436
        /// - Signal processing: Power spectral density, root mean square
    437
    0
        pub fn pow(&self, n: f32) -> Result<Vector<f32>> {
    438
    0
            let pow_data: Vec<f32> = self.as_slice().iter().map(|x| x.powf(n)).collect();
    439
    0
            Ok(Vector::from_vec(pow_data))
    440
    0
        }
    441
    }
    442
    443
    #[cfg(test)]
    444
    mod tests {
    445
        use super::*;
    446
    447
        #[test]
    448
        fn test_abs_basic() {
    449
            let v = Vector::from_slice(&[3.0, -4.0, 5.0, -2.0]);
    450
            let result = v.abs().unwrap();
    451
            assert_eq!(result.as_slice(), &[3.0, 4.0, 5.0, 2.0]);
    452
        }
    453
    454
        #[test]
    455
        fn test_abs_empty() {
    456
            let v: Vector<f32> = Vector::from_slice(&[]);
    457
            let result = v.abs().unwrap();
    458
            assert_eq!(result.len(), 0);
    459
        }
    460
    461
        #[test]
    462
        fn test_clip_basic() {
    463
            let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);
    464
            let clipped = v.clip(0.0, 10.0).unwrap();
    465
            assert_eq!(clipped.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);
    466
        }
    467
    468
        #[test]
    469
        fn test_clip_invalid_range() {
    470
            let v = Vector::from_slice(&[1.0, 2.0, 3.0]);
    471
            let result = v.clip(10.0, 5.0);
    472
            assert!(matches!(result, Err(TruenoError::InvalidInput(_))));
    473
        }
    474
    475
        #[test]
    476
        fn test_clamp_basic() {
    477
            let v = Vector::from_slice(&[-5.0, 0.0, 5.0, 10.0, 15.0]);
    478
            let result = v.clamp(0.0, 10.0).unwrap();
    479
            assert_eq!(result.as_slice(), &[0.0, 0.0, 5.0, 10.0, 10.0]);
    480
        }
    481
    482
        #[test]
    483
        fn test_clamp_negative_range() {
    484
            let v = Vector::from_slice(&[-10.0, -5.0, 0.0, 5.0]);
    485
            let result = v.clamp(-8.0, -2.0).unwrap();
    486
            assert_eq!(result.as_slice(), &[-8.0, -5.0, -2.0, -2.0]);
    487
        }
    488
    489
        #[test]
    490
        fn test_lerp_midpoint() {
    491
            let a = Vector::from_slice(&[0.0, 10.0, 20.0]);
    492
            let b = Vector::from_slice(&[100.0, 110.0, 120.0]);
    493
            let result = a.lerp(&b, 0.5).unwrap();
    494
            assert_eq!(result.as_slice(), &[50.0, 60.0, 70.0]);
    495
        }
    496
    497
        #[test]
    498
        fn test_lerp_extrapolation() {
    499
            let a = Vector::from_slice(&[0.0, 10.0]);
    500
            let b = Vector::from_slice(&[10.0, 20.0]);
    501
            let result = a.lerp(&b, 2.0).unwrap();
    502
            assert_eq!(result.as_slice(), &[20.0, 30.0]);
    503
        }
    504
    505
        #[test]
    506
        fn test_lerp_size_mismatch() {
    507
            let a = Vector::from_slice(&[0.0, 10.0]);
    508
            let b = Vector::from_slice(&[10.0, 20.0, 30.0]);
    509
            let result = a.lerp(&b, 0.5);
    510
            assert!(matches!(result, Err(TruenoError::SizeMismatch { .. })));
    511
        }
    512
    513
        #[test]
    514
        fn test_sqrt_basic() {
    515
            let a = Vector::from_slice(&[4.0, 9.0, 16.0, 25.0]);
    516
            let result = a.sqrt().unwrap();
    517
            assert_eq!(result.as_slice(), &[2.0, 3.0, 4.0, 5.0]);
    518
        }
    519
    520
        #[test]
    521
        fn test_sqrt_negative() {
    522
            let a = Vector::from_slice(&[-1.0, 4.0]);
    523
            let result = a.sqrt().unwrap();
    524
            assert!(result.as_slice()[0].is_nan());
    525
            assert_eq!(result.as_slice()[1], 2.0);
    526
        }
    527
    528
        #[test]
    529
        fn test_recip_basic() {
    530
            let a = Vector::from_slice(&[2.0, 4.0, 5.0, 10.0]);
    531
            let result = a.recip().unwrap();
    532
            assert_eq!(result.as_slice(), &[0.5, 0.25, 0.2, 0.1]);
    533
        }
    534
    535
        #[test]
    536
        fn test_recip_zero() {
    537
            let a = Vector::from_slice(&[0.0, 2.0]);
    538
            let result = a.recip().unwrap();
    539
            assert!(result.as_slice()[0].is_infinite());
    540
            assert_eq!(result.as_slice()[1], 0.5);
    541
        }
    542
    543
        #[test]
    544
        fn test_pow_squared() {
    545
            let v = Vector::from_slice(&[2.0, 3.0, 4.0]);
    546
            let squared = v.pow(2.0).unwrap();
    547
            assert_eq!(squared.as_slice(), &[4.0, 9.0, 16.0]);
    548
        }
    549
    550
        #[test]
    551
        fn test_pow_square_root() {
    552
            let v = Vector::from_slice(&[4.0, 9.0, 16.0]);
    553
            let sqrt = v.pow(0.5).unwrap();
    554
            assert!((sqrt.as_slice()[0] - 2.0).abs() < 1e-5);
    555
            assert!((sqrt.as_slice()[1] - 3.0).abs() < 1e-5);
    556
            assert!((sqrt.as_slice()[2] - 4.0).abs() < 1e-5);
    557
        }
    558
    }