bb_geometry/linear_algebra/vector4/
mod.rs

1use std::ops::{Add, Index, IndexMut, Mul, Neg, Sub};
2use crate::linear_algebra::EPSILON;
3use super::matrix4x4::Matrix4x4;
4
5/// Represents a 4-dimensional vector with f32 components.
6#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct Vector4 {
8    /// The vector data stored as an array.
9    data: [f32; 4],
10}
11
12impl Vector4 {
13    /// Creates a new 4-vector from the provided array data.
14    ///
15    /// # Example
16    /// ```
17    /// # use crate::bb_geometry::linear_algebra::vector4::*;
18    /// let v = Vector4::new([1.0, 2.0, 3.0, 4.0]);
19    /// assert_eq!(v.get(0), 1.0);
20    /// ```
21    pub fn new(data: [f32; 4]) -> Self {
22        Self { data }
23    }
24
25    /// Creates a zero vector (all components are 0.0).
26    ///
27    /// # Example
28    /// ```
29    /// use crate::bb_geometry::linear_algebra::vector4::*;
30    /// let zero = Vector4::zero();
31    /// assert_eq!(zero.get(2), 0.0);
32    /// ```
33    pub fn zero() -> Self {
34        Self { data: [0.0; 4] }
35    }
36
37    /// Gets the value at the specified index using a method call.
38    ///
39    /// Prefer using the index operator `vector[index]` for more idiomatic access.
40    ///
41    /// # Panics
42    /// Panics if `index` is out of bounds (>= 4).
43    ///
44    /// # Example
45    /// ```
46    /// use crate::bb_geometry::linear_algebra::vector4::*;
47    /// let v = Vector4::new([1.0, 2.0, 3.0, 4.0]);
48    /// assert_eq!(v.get(1), 2.0);
49    /// ```
50    #[inline]
51    pub fn get(&self, index: usize) -> f32 {
52        assert!(index < 4, "Index out of bounds: {}", index);
53        self.data[index]
54    }
55
56    /// Sets the value at the specified index using a method call.
57    ///
58    /// Prefer using the mutable index operator `vector[index] = value`
59    /// for more idiomatic modification.
60    ///
61    /// # Panics
62    /// Panics if `index` is out of bounds (>= 4).
63    ///
64    /// # Example
65    /// ```
66    /// use crate::bb_geometry::linear_algebra::vector4::*;
67    /// let mut v = Vector4::zero();
68    /// v.set(3, 5.0);
69    /// assert_eq!(v.get(3), 5.0);
70    /// ```
71    #[inline]
72    pub fn set(&mut self, index: usize, value: f32) {
73        assert!(index < 4, "Index out of bounds: {}", index);
74        self.data[index] = value;
75    }
76
77    /// Calculates the dot (inner) product of this vector with another vector.
78    ///
79    /// result = self[0]*other[0] + self[1]*other[1] + self[2]*other[2] + self[3]*other[3]
80    ///
81    /// # Example
82    /// ```
83    /// use crate::bb_geometry::linear_algebra::vector4::*;
84    /// let v1 = Vector4::new([1.0, 2.0, 3.0, 4.0]);
85    /// let v2 = Vector4::new([5.0, 6.0, 7.0, 8.0]);
86    /// // 1*5 + 2*6 + 3*7 + 4*8 = 5 + 12 + 21 + 32 = 70
87    /// assert_eq!(v1.dot(&v2), 70.0);
88    /// ```
89    pub fn dot(&self, other: &Self) -> f32 {
90        let mut sum = 0.0;
91        for i in 0..4 {
92            sum += self.data[i] * other.data[i];
93        }
94        sum
95    }
96
97    pub fn l2_norm(&self) -> f32 {
98        let mut sum = 0.0;
99        for i in 0..4 {
100            sum += self.data[i] * self.data[i];
101        }
102        sum.sqrt()
103    }
104
105    pub fn l1_norm(&self) -> f32 {
106        let mut sum = 0.0;
107        for i in 0..4 {
108            let inc = self.data[i].abs();
109            if inc > sum { sum = inc; }
110        }
111        sum
112    }
113
114    pub fn is_almost_zero(&self) -> bool {
115        self.l1_norm() < EPSILON
116    }
117
118    /// Calculates the wedge product (antisymmetric outer product) of two vectors.
119    ///
120    /// Returns a 4x4 antisymmetric linear_algebra `M` where `M[i][j] = self[i]*other[j] - self[j]*other[i]`.
121    /// This represents the bivector formed by the two vectors.
122    ///
123    /// # Example
124    /// ```
125    /// use crate::bb_geometry::linear_algebra::vector4::*;
126    /// use crate::bb_geometry::linear_algebra::matrix4x4::*;
127    /// let u = Vector4::new([1.0, 2.0, 0.0, 0.0]);
128    /// let v = Vector4::new([0.0, 3.0, 4.0, 0.0]);
129    /// let wedge_matrix = u.wedge_product(&v);
130    ///
131    /// // M[0][1] = u[0]*v[1] - u[1]*v[0] = 1*3 - 2*0 = 3.0
132    /// assert_eq!(wedge_matrix[(0, 1)], 3.0);
133    /// // M[1][0] = u[1]*v[0] - u[0]*v[1] = 2*0 - 1*3 = -3.0
134    /// assert_eq!(wedge_matrix[(1, 0)], -3.0);
135    /// // M[0][2] = u[0]*v[2] - u[2]*v[0] = 1*4 - 0*0 = 4.0
136    /// assert_eq!(wedge_matrix[(0, 2)], 4.0);
137    /// // M[1][2] = u[1]*v[2] - u[2]*v[1] = 2*4 - 0*3 = 8.0
138    /// assert_eq!(wedge_matrix[(1, 2)], 8.0);
139    /// // M[0][0] should be 0
140    /// assert_eq!(wedge_matrix[(0, 0)], 0.0);
141    /// // M[3][x] should be 0 as u[3] and v[3] are 0
142    /// assert_eq!(wedge_matrix[(3, 0)], 0.0);
143    /// assert_eq!(wedge_matrix[(0, 3)], 0.0);
144    /// ```
145    pub fn wedge_product(&self, other: &Self) -> Matrix4x4 {
146        let mut wedge_data = [[0.0f32; 4]; 4];
147        for i in 0..4 {
148            for j in 0..4 {
149                wedge_data[i][j] = self.data[i] * other.data[j] - self.data[j] * other.data[i];
150            }
151        }
152        Matrix4x4::new(wedge_data)
153    }
154}
155
156// --- Trait Implementations ---
157
158/// Allows accessing vector components using index `vector[index]`.
159///
160/// # Panics
161/// Panics if `index` is out of bounds (>= 4).
162impl Index<usize> for Vector4 {
163    type Output = f32;
164
165    #[inline]
166    fn index(&self, index: usize) -> &Self::Output {
167        assert!(index < 4, "Index out of bounds: {}", index);
168        &self.data[index]
169    }
170}
171
172/// Allows mutating vector components using index `vector[index] = value`.
173///
174/// # Panics
175/// Panics if `index` is out of bounds (>= 4).
176impl IndexMut<usize> for Vector4 {
177    #[inline]
178    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
179        assert!(index < 4, "Index out of bounds: {}", index);
180        &mut self.data[index]
181    }
182}
183
184/// Implements vector addition using the `+` operator (`&Vector4 + &Vector4`).
185impl Add<&Vector4> for &Vector4 {
186    type Output = Vector4;
187
188    fn add(self, rhs: &Vector4) -> Self::Output {
189        let mut result_data = [0.0f32; 4];
190        for i in 0..4 {
191            result_data[i] = self.data[i] + rhs.data[i];
192        }
193        Vector4 { data: result_data }
194    }
195}
196
197// Delegate owned + owned, owned + ref, ref + owned to ref + ref
198impl Add<Vector4> for Vector4 { type Output = Vector4; #[inline] fn add(self, rhs: Vector4) -> Self::Output { &self + &rhs }}
199impl Add<&Vector4> for Vector4 { type Output = Vector4; #[inline] fn add(self, rhs: &Vector4) -> Self::Output { &self + rhs }}
200impl Add<Vector4> for &Vector4 { type Output = Vector4; #[inline] fn add(self, rhs: Vector4) -> Self::Output { self + &rhs }}
201
202
203/// Implements vector subtraction using the `-` operator (`&Vector4 - &Vector4`).
204impl Sub<&Vector4> for &Vector4 {
205    type Output = Vector4;
206
207    fn sub(self, rhs: &Vector4) -> Self::Output {
208        let mut result_data = [0.0f32; 4];
209        for i in 0..4 {
210            result_data[i] = self.data[i] - rhs.data[i];
211        }
212        Vector4 { data: result_data }
213    }
214}
215
216// Delegate owned - owned, owned - ref, ref - owned to ref - ref
217impl Sub<Vector4> for Vector4 { type Output = Vector4; #[inline] fn sub(self, rhs: Vector4) -> Self::Output { &self - &rhs }}
218impl Sub<&Vector4> for Vector4 { type Output = Vector4; #[inline] fn sub(self, rhs: &Vector4) -> Self::Output { &self - rhs }}
219impl Sub<Vector4> for &Vector4 { type Output = Vector4; #[inline] fn sub(self, rhs: Vector4) -> Self::Output { self - &rhs }}
220
221
222/// Implements vector negation using the unary `-` operator (`-vector`).
223impl Neg for Vector4 {
224    type Output = Self;
225
226    fn neg(self) -> Self::Output {
227        let mut result_data = [0.0f32; 4];
228        for i in 0..4 {
229            result_data[i] = -self.data[i];
230        }
231        Vector4 { data: result_data }
232    }
233}
234// Implement negation for reference as well
235impl Neg for &Vector4 {
236    type Output = Vector4;
237
238    fn neg(self) -> Self::Output {
239        -(*self)
240    }
241}
242
243
244/// Implements scalar multiplication (`&Vector4 * f32`).
245impl Mul<f32> for &Vector4 {
246    type Output = Vector4;
247
248    fn mul(self, rhs: f32) -> Self::Output {
249        let mut result_data = [0.0f32; 4];
250        for i in 0..4 {
251            result_data[i] = self.data[i] * rhs;
252        }
253        Vector4 { data: result_data }
254    }
255}
256// Delegate owned * scalar to ref * scalar
257impl Mul<f32> for Vector4 { type Output = Vector4; #[inline] fn mul(self, rhs: f32) -> Self::Output { &self * rhs }}
258
259
260/// Implements scalar multiplication (`f32 * &Vector4`).
261impl Mul<&Vector4> for f32 {
262    type Output = Vector4;
263
264    fn mul(self, rhs: &Vector4) -> Self::Output {
265        // Reuse the Vector * scalar implementation
266        rhs * self
267    }
268}
269// Delegate scalar * owned to scalar * ref
270impl Mul<Vector4> for f32 { type Output = Vector4; #[inline] fn mul(self, rhs: Vector4) -> Self::Output { self * &rhs }}
271
272
273/// Implements Matrix * Vector multiplication (`&Matrix4x4 * &Vector4`).
274/// Treats the vector as a column vector.
275impl Mul<&Vector4> for &Matrix4x4 {
276    type Output = Vector4;
277
278    fn mul(self, rhs: &Vector4) -> Self::Output {
279        let mut result_data = [0.0f32; 4];
280        for i in 0..4 { // Row of linear_algebra / element of result vector
281            let mut sum = 0.0;
282            for k in 0..4 { // Column of linear_algebra / element of input vector
283                sum += self[(i, k)] * rhs[k];
284            }
285            result_data[i] = sum;
286        }
287        Vector4 { data: result_data }
288    }
289}
290
291// Delegate other Matrix * Vector combinations if needed
292impl Mul<Vector4> for Matrix4x4 { type Output = Vector4; #[inline] fn mul(self, rhs: Vector4) -> Self::Output { &self * &rhs }}
293impl Mul<&Vector4> for Matrix4x4 { type Output = Vector4; #[inline] fn mul(self, rhs: &Vector4) -> Self::Output { &self * rhs }}
294impl Mul<Vector4> for &Matrix4x4 { type Output = Vector4; #[inline] fn mul(self, rhs: Vector4) -> Self::Output { self * &rhs }}
295
296pub const E_X: Vector4 = Vector4 { data: [1.0, 0.0, 0.0, 0.0] };
297pub const E_Y: Vector4 = Vector4 { data: [0.0, 1.0, 0.0, 0.0] };
298pub const E_Z: Vector4 = Vector4 { data: [0.0, 0.0, 1.0, 0.0] };
299pub const E_W: Vector4 = Vector4 { data: [0.0, 0.0, 0.0, 1.0] };