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] };