Skip to main content

trueno/vector/ops/norms/
mod.rs

1//! Vector norm operations
2//!
3//! This module provides vector norm calculations:
4//! - `norm_l1()` - L1 norm (Manhattan norm)
5//! - `norm_l2()` - L2 norm (Euclidean norm)
6//! - `norm_linf()` - L∞ norm (infinity norm / max norm)
7//!
8//! All three norms share the same `unsafe fn(&[f32]) -> f32` backend
9//! signature, so dispatch is handled by the crate-level
10//! [`dispatch_reduction!`] macro -- no per-module dispatch struct needed.
11
12use crate::backends::VectorBackend;
13use crate::{dispatch_reduction, Result, Vector};
14
15impl Vector<f32> {
16    /// L2 norm (Euclidean norm)
17    ///
18    /// Computes the Euclidean length of the vector: sqrt(sum(a\[i\]^2)).
19    /// This is mathematically equivalent to sqrt(dot(self, self)).
20    ///
21    /// # Performance
22    ///
23    /// Uses optimized SIMD implementations via the dot product operation.
24    ///
25    /// # Examples
26    ///
27    /// ```
28    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
29    /// use trueno::Vector;
30    ///
31    /// let v = Vector::from_slice(&[3.0, 4.0]);
32    /// let norm = v.norm_l2()?;
33    /// assert!((norm - 5.0).abs() < 1e-5); // sqrt(3^2 + 4^2) = 5
34    /// # Ok(())
35    /// # }
36    /// ```
37    ///
38    /// # Empty vectors
39    ///
40    /// Returns 0.0 for empty vectors (consistent with the mathematical definition).
41    ///
42    /// ```
43    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
44    /// use trueno::Vector;
45    ///
46    /// let v: Vector<f32> = Vector::from_slice(&[]);
47    /// assert_eq!(v.norm_l2()?, 0.0);
48    /// # Ok(())
49    /// # }
50    /// ```
51    pub fn norm_l2(&self) -> Result<f32> {
52        if self.data.is_empty() {
53            return Ok(0.0);
54        }
55        Ok(dispatch_reduction!(self.backend, norm_l2, &self.data))
56    }
57
58    /// Compute the L1 norm (Manhattan norm) of the vector
59    ///
60    /// Returns the sum of absolute values: ||v||₁ = sum(|v\[i\]|)
61    ///
62    /// The L1 norm is used in:
63    /// - Machine learning (L1 regularization, Lasso regression)
64    /// - Distance metrics (Manhattan distance)
65    /// - Sparse modeling and feature selection
66    /// - Signal processing
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use trueno::Vector;
72    ///
73    /// let v = Vector::from_slice(&[3.0, -4.0, 5.0]);
74    /// let norm = v.norm_l1().unwrap();
75    ///
76    /// // |3| + |-4| + |5| = 12
77    /// assert!((norm - 12.0).abs() < 1e-5);
78    /// ```
79    ///
80    /// # Empty Vector
81    ///
82    /// ```
83    /// use trueno::Vector;
84    ///
85    /// let v: Vector<f32> = Vector::from_slice(&[]);
86    /// assert_eq!(v.norm_l1().unwrap(), 0.0);
87    /// ```
88    pub fn norm_l1(&self) -> Result<f32> {
89        if self.data.is_empty() {
90            return Ok(0.0);
91        }
92        Ok(dispatch_reduction!(self.backend, norm_l1, &self.data))
93    }
94
95    /// Compute the L∞ norm (infinity norm / max norm) of the vector
96    ///
97    /// Returns the maximum absolute value: ||v||∞ = max(|v\[i\]|)
98    ///
99    /// The L∞ norm is used in:
100    /// - Numerical analysis (error bounds, stability analysis)
101    /// - Optimization (Chebyshev approximation)
102    /// - Signal processing (peak detection)
103    /// - Distance metrics (Chebyshev distance)
104    ///
105    /// # Examples
106    ///
107    /// ```
108    /// use trueno::Vector;
109    ///
110    /// let v = Vector::from_slice(&[3.0, -7.0, 5.0, -2.0]);
111    /// let norm = v.norm_linf().unwrap();
112    ///
113    /// // max(|3|, |-7|, |5|, |-2|) = 7
114    /// assert!((norm - 7.0).abs() < 1e-5);
115    /// ```
116    ///
117    /// # Empty Vector
118    ///
119    /// ```
120    /// use trueno::Vector;
121    ///
122    /// let v: Vector<f32> = Vector::from_slice(&[]);
123    /// assert_eq!(v.norm_linf().unwrap(), 0.0);
124    /// ```
125    pub fn norm_linf(&self) -> Result<f32> {
126        if self.data.is_empty() {
127            return Ok(0.0);
128        }
129        Ok(dispatch_reduction!(self.backend, norm_linf, &self.data))
130    }
131}
132
133#[cfg(test)]
134mod tests;