siege_math/vector/
mod.rs

1
2
3pub mod point;
4pub use self::point::{Point2, Point3};
5
6pub mod direction;
7pub use self::direction::{Direction2, Direction3,
8                          X_AXIS_F32, Y_AXIS_F32, Z_AXIS_F32,
9                          X_AXIS_F64, Y_AXIS_F64, Z_AXIS_F64};
10
11use std::ops::{Index, IndexMut, Mul, MulAssign, Div, DivAssign, Neg,
12               Add, AddAssign, Sub, SubAssign};
13use std::default::Default;
14use num_traits::NumCast;
15use float_cmp::{Ulps, ApproxEq};
16use FullFloat;
17
18/// A 2-element vector
19#[repr(C)]
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21#[derive(Serialize, Deserialize)]
22pub struct Vec2<F> {
23    pub x: F,
24    pub y: F,
25}
26
27/// A 3-element vector
28#[repr(C)]
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30#[derive(Serialize, Deserialize)]
31pub struct Vec3<F> {
32    pub x: F,
33    pub y: F,
34    pub z: F,
35}
36
37/// A 4-element vector
38#[repr(C)]
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40#[derive(Serialize, Deserialize)]
41pub struct Vec4<F> {
42    pub x: F,
43    pub y: F,
44    pub z: F,
45    pub w: F,
46}
47
48// -- indexing ----------------------------------------------------------------
49
50impl<F: FullFloat> Index<usize> for Vec2<F> {
51    type Output = F;
52
53    #[inline]
54    fn index(&self, i: usize) -> &F {
55        match i {
56            0 => &self.x,
57            1 => &self.y,
58            _ => panic!("Index out of bounds for Vec2"),
59        }
60    }
61}
62
63impl<F: FullFloat> Index<usize> for Vec3<F> {
64    type Output = F;
65
66    #[inline]
67    fn index(&self, i: usize) -> &F {
68        match i {
69            0 => &self.x,
70            1 => &self.y,
71            2 => &self.z,
72            _ => panic!("Index out of bounds for Vec3"),
73        }
74    }
75}
76
77impl<F: FullFloat> Index<usize> for Vec4<F> {
78    type Output = F;
79
80    #[inline]
81    fn index(&self, i: usize) -> &F {
82        match i {
83            0 => &self.x,
84            1 => &self.y,
85            2 => &self.z,
86            3 => &self.w,
87            _ => panic!("Index out of bounds for Vec4"),
88        }
89    }
90}
91
92impl<F: FullFloat> IndexMut<usize> for Vec2<F> {
93    #[inline]
94    fn index_mut(&mut self, i: usize) -> &mut F {
95        match i {
96            0 => &mut self.x,
97            1 => &mut self.y,
98            _ => panic!("Index out of bounds for Vec2"),
99        }
100    }
101}
102
103impl<F: FullFloat> IndexMut<usize> for Vec3<F> {
104    #[inline]
105    fn index_mut(&mut self, i: usize) -> &mut F {
106        match i {
107            0 => &mut self.x,
108            1 => &mut self.y,
109            2 => &mut self.z,
110            _ => panic!("Index out of bounds for Vec3"),
111        }
112    }
113}
114
115impl<F: FullFloat> IndexMut<usize> for Vec4<F> {
116    #[inline]
117    fn index_mut(&mut self, i: usize) -> &mut F {
118        match i {
119            0 => &mut self.x,
120            1 => &mut self.y,
121            2 => &mut self.z,
122            3 => &mut self.w,
123            _ => panic!("Index out of bounds for Vec4"),
124        }
125    }
126}
127
128// -- dropping a dimension ----------------------------------------------------
129
130impl<F: FullFloat> Vec3<F> {
131    #[inline]
132    pub fn truncate_n(&self, n: usize) -> Vec2<F> {
133        match n {
134            0 => Vec2::new(self.y, self.z),
135            1 => Vec2::new(self.x, self.z),
136            2 => Vec2::new(self.x, self.y),
137            _ => panic!("Index out of bounds for Vec3"),
138        }
139    }
140}
141
142impl<F: FullFloat> Vec3<F> {
143    #[inline]
144    pub fn truncate_x(&self) -> Vec2<F> {
145        Vec2::new(self.y, self.z)
146    }
147    #[inline]
148    pub fn truncate_y(&self) -> Vec2<F> {
149        Vec2::new(self.x, self.z)
150    }
151    #[inline]
152    pub fn truncate_z(&self) -> Vec2<F> {
153        Vec2::new(self.x, self.y)
154    }
155}
156
157impl<F: FullFloat> Vec4<F> {
158    #[inline]
159    pub fn truncate_n(&self, n: usize) -> Vec3<F> {
160        match n {
161            0 => Vec3::new(self.y, self.z, self.w),
162            1 => Vec3::new(self.x, self.z, self.w),
163            2 => Vec3::new(self.x, self.y, self.w),
164            3 => Vec3::new(self.x, self.y, self.z),
165            _ => panic!("Index out of bounds for Vec4"),
166        }
167    }
168}
169
170impl<F: FullFloat> Vec4<F> {
171    #[inline]
172    pub fn truncate_x(&self) -> Vec3<F> {
173        Vec3::new(self.y, self.z, self.w)
174    }
175    #[inline]
176    pub fn truncate_y(&self) -> Vec3<F> {
177        Vec3::new(self.x, self.z, self.w)
178    }
179    #[inline]
180    pub fn truncate_z(&self) -> Vec3<F> {
181        Vec3::new(self.x, self.y, self.w)
182    }
183    #[inline]
184    pub fn truncate_w(&self) -> Vec3<F> {
185        Vec3::new(self.x, self.y, self.z)
186    }
187}
188
189// ----------------------------------------------------------------------------
190
191macro_rules! impl_vector {
192    ($VecN:ident { $first:ident, $($field:ident),* }) => {
193        impl<F: FullFloat> $VecN<F> {
194            /// Construct a new vector
195            #[inline]
196            pub fn new($first: F, $($field: F),*) -> $VecN<F> {
197                $VecN { $first: $first, $($field: $field),* }
198            }
199        }
200
201        impl<F: FullFloat> $VecN<F> {
202            #[inline]
203            pub fn zero() -> $VecN<F> {
204                $VecN { $first: F::zero(), $($field: F::zero()),* }
205            }
206        }
207
208        impl<F: FullFloat> Default for $VecN<F> {
209            #[inline]
210            fn default() -> $VecN<F> {
211                $VecN { $first: F::default(), $($field: F::default()),* }
212            }
213        }
214
215        impl<F: FullFloat> $VecN<F>{
216            #[inline]
217            pub fn squared_magnitude(&self) -> F {
218                self.$first * self.$first $(+ self.$field * self.$field)*
219            }
220        }
221
222        impl<F: FullFloat> $VecN<F> {
223            #[inline]
224            pub fn magnitude(&self) -> F {
225                self.squared_magnitude().sqrt()
226                // FIXME: once simd is part of std and stable, use it
227                // rsqrt is faster than sqrt (but is approximate)
228                // self.squared_magnitude().rsqrt()
229            }
230        }
231
232        impl<F: FullFloat> $VecN<F> {
233            pub fn is_normal(&self) -> bool {
234                self.magnitude().approx_eq(
235                    &F::one(),
236                    <F as NumCast>::from(10.0_f32).unwrap() * F::epsilon(),
237                    NumCast::from(10_u32).unwrap()
238                )
239            }
240        }
241
242        impl<F: FullFloat> Mul<F> for $VecN<F> {
243            type Output = $VecN<F>;
244
245            #[inline]
246            fn mul(self, rhs: F) -> $VecN<F> {
247                $VecN {
248                    $first: self.$first * rhs,
249                    $($field: self.$field * rhs),*
250                }
251            }
252        }
253
254        impl<F: FullFloat> Mul<$VecN<F>> for $VecN<F> {
255            type Output = $VecN<F>;
256
257            #[inline]
258            fn mul(self, rhs: $VecN<F>) -> $VecN<F> {
259                $VecN {
260                    $first: self.$first * rhs.$first,
261                    $($field: self.$field * rhs.$field),*
262                }
263            }
264        }
265
266        impl<F: FullFloat> MulAssign<F> for $VecN<F> {
267            #[inline]
268            fn mul_assign(&mut self, rhs: F) {
269                self.$first *= rhs;
270                $(self.$field *= rhs);*
271            }
272        }
273
274        impl<F: FullFloat> Div<F> for $VecN<F> {
275            type Output = $VecN<F>;
276
277            #[inline]
278            fn div(self, rhs: F) -> $VecN<F> {
279                $VecN {
280                    $first: self.$first / rhs,
281                    $($field: self.$field / rhs),*
282                }
283            }
284        }
285
286        impl<F: FullFloat> DivAssign<F> for $VecN<F> {
287            #[inline]
288            fn div_assign(&mut self, rhs: F) {
289                self.$first /= rhs;
290                $(self.$field /= rhs);*
291            }
292        }
293
294        impl<F: FullFloat> Neg for $VecN<F> {
295            type Output = $VecN<F>;
296
297            #[inline]
298            fn neg(self) -> $VecN<F> {
299                $VecN {
300                    $first: -self.$first,
301                    $($field: -self.$field),*
302                }
303            }
304        }
305
306        impl<F: FullFloat> Add for $VecN<F> {
307            type Output = $VecN<F>;
308
309            #[inline]
310            fn add(self, other: $VecN<F>) -> $VecN<F> {
311                $VecN {
312                    $first: self.$first + other.$first,
313                    $($field: self.$field + other.$field),*
314                }
315            }
316        }
317
318        impl<F: FullFloat> AddAssign<$VecN<F>> for $VecN<F> {
319            #[inline]
320            fn add_assign(&mut self, other: $VecN<F>) {
321                self.$first += other.$first;
322                $(self.$field += other.$field);*
323            }
324        }
325
326        impl<F: FullFloat> Sub for $VecN<F> {
327            type Output = $VecN<F>;
328
329            #[inline]
330            fn sub(self, other: $VecN<F>) -> $VecN<F> {
331                $VecN {
332                    $first: self.$first - other.$first,
333                    $($field: self.$field - other.$field),*
334                }
335            }
336        }
337
338        impl<F: FullFloat> SubAssign<$VecN<F>> for $VecN<F> {
339            #[inline]
340            fn sub_assign(&mut self, other: $VecN<F>) {
341                self.$first -= other.$first;
342                $(self.$field -= other.$field);*
343            }
344        }
345
346        impl<F: FullFloat> $VecN<F> {
347            #[inline]
348            pub fn dot(&self, rhs: $VecN<F>) -> F {
349                self.$first * rhs.$first
350                    $(+ self.$field * rhs.$field)*
351            }
352        }
353
354        impl<F: FullFloat> $VecN<F> {
355            #[inline]
356            pub fn project_onto(&self, axis: $VecN<F>) -> $VecN<F> {
357                axis * (self.dot(axis) / axis.dot(axis))
358            }
359        }
360
361        impl<F: FullFloat> $VecN<F>
362        {
363            #[inline]
364            pub fn reject_onto(&self, axis: $VecN<F>) -> $VecN<F> {
365                *self - self.project_onto(axis)
366            }
367        }
368
369        impl<F: FullFloat> $VecN<F>
370        {
371            #[inline]
372            pub fn exp(&self) -> $VecN<F> {
373                $VecN {
374                    $first: self.$first.exp(),
375                    $($field: self.$field.exp()),*
376                }
377            }
378        }
379    }
380}
381
382impl_vector!(Vec2 { x, y });
383impl_vector!(Vec3 { x, y, z });
384impl_vector!(Vec4 { x, y, z, w });
385
386// ----------------------------------------------------------------------------
387
388impl<F: FullFloat> Vec3<F> {
389    #[inline]
390    pub fn cross(&self, rhs: Vec3<F>) -> Vec3<F> {
391        Vec3::new(
392            self.y*rhs.z - self.z*rhs.y,
393            self.z*rhs.x - self.x*rhs.z,
394            self.x*rhs.y - self.y*rhs.x
395        )
396    }
397}
398
399impl<F: FullFloat> Vec3<F> {
400    #[inline]
401    pub fn triple_product(&self, b: Vec3<F>, c: Vec3<F>) -> F {
402        self.cross(b).dot(c)
403    }
404}
405
406// ----------------------------------------------------------------------------
407// Shortening
408
409impl<F: FullFloat> From<Vec4<F>> for Vec3<F> {
410    fn from(v: Vec4<F>) -> Vec3<F> {
411        Vec3 { x: v.x, y: v.y, z: v.z }
412    }
413}
414
415impl<F: FullFloat> From<Vec3<F>> for Vec2<F> {
416    fn from(v: Vec3<F>) -> Vec2<F> {
417        Vec2 { x: v.x, y: v.y }
418    }
419}
420
421// -- adding a dimension ------------------------------------------------------
422
423impl<F: FullFloat> Vec3<F> {
424    pub fn to_vec4(&self, w: F) -> Vec4<F> {
425        Vec4 { x: self.x, y: self.y, z: self.z, w: w }
426    }
427}
428
429// ----------------------------------------------------------------------------
430// casting between float types
431
432/*
433Unfortunately I cant get these to work because F and G could be the same type
434and that collides with an impl in the standard library.  I have not figured
435out how to tell rust that F and G are not the same type.
436
437impl<F: FullFloat, G: FullFloat> From<Vec2<F>> for Vec2<G>
438{
439    fn from(v: Vec2<F>) -> Vec2<G> {
440        Vec2 { x: v.x.as_(), y: v.y.as_() }
441    }
442}
443
444impl<F: FullFloat, G: FullFloat> From<Vec3<F>> for Vec3<G> {
445    fn from(v: Vec3<F>) -> Vec3<G> {
446        Vec3 { x: v.x.as_(), y: v.y.as_(), z: v.z.as_() }
447    }
448}
449
450impl<F: FullFloat, G: FullFloat> From<Vec4<F>> for Vec4<G> {
451    fn from(v: Vec4<F>) -> Vec4<G> {
452        Vec4 { x: v.x.as_(), y: v.y.as_(), z: v.z.as_(), w: v.w.as_() }
453    }
454}
455*/
456
457impl From<Vec2<f64>> for Vec2<f32> {
458    fn from(v: Vec2<f64>) -> Vec2<f32> {
459        Vec2 { x: v.x as f32, y: v.y as f32 }
460    }
461}
462
463impl From<Vec2<f32>> for Vec2<f64> {
464    fn from(v: Vec2<f32>) -> Vec2<f64> {
465        Vec2 { x: v.x as f64, y: v.y as f64 }
466    }
467}
468
469impl From<Vec3<f64>> for Vec3<f32> {
470    fn from(v: Vec3<f64>) -> Vec3<f32> {
471        Vec3 { x: v.x as f32, y: v.y as f32, z: v.z as f32 }
472    }
473}
474
475impl From<Vec3<f32>> for Vec3<f64> {
476    fn from(v: Vec3<f32>) -> Vec3<f64> {
477        Vec3 { x: v.x as f64, y: v.y as f64, z: v.z as f64 }
478    }
479}
480
481impl From<Vec4<f64>> for Vec4<f32> {
482    fn from(v: Vec4<f64>) -> Vec4<f32> {
483        Vec4 { x: v.x as f32, y: v.y as f32, z: v.z as f32, w: v.w as f32 }
484    }
485}
486
487impl From<Vec4<f32>> for Vec4<f64> {
488    fn from(v: Vec4<f32>) -> Vec4<f64> {
489        Vec4 { x: v.x as f64, y: v.y as f64, z: v.z as f64, w: v.w as f64 }
490    }
491}
492
493// ----------------------------------------------------------------------------
494// Approx Eq
495
496impl<F: FullFloat> ApproxEq for Vec2<F> {
497    type Flt = F;
498
499    fn approx_eq(&self, other: &Self,
500                 epsilon: <F as ApproxEq>::Flt,
501                 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
502    {
503        self.x.approx_eq(&other.x, epsilon, ulps)
504            && self.y.approx_eq(&other.y, epsilon, ulps)
505    }
506}
507
508impl<F: FullFloat> ApproxEq for Vec3<F> {
509    type Flt = F;
510
511    fn approx_eq(&self, other: &Self,
512                 epsilon: <F as ApproxEq>::Flt,
513                 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
514    {
515        self.x.approx_eq(&other.x, epsilon, ulps)
516            && self.y.approx_eq(&other.y, epsilon, ulps)
517            && self.z.approx_eq(&other.z, epsilon, ulps)
518    }
519}
520
521impl<F: FullFloat> ApproxEq for Vec4<F> {
522    type Flt = F;
523
524    fn approx_eq(&self, other: &Self,
525                 epsilon: <F as ApproxEq>::Flt,
526                 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
527    {
528        self.x.approx_eq(&other.x, epsilon, ulps)
529            && self.y.approx_eq(&other.y, epsilon, ulps)
530            && self.z.approx_eq(&other.z, epsilon, ulps)
531            && self.w.approx_eq(&other.w, epsilon, ulps)
532    }
533}
534
535// ----------------------------------------------------------------------------
536
537#[cfg(test)]
538mod tests {
539    use float_cmp:: ApproxEq;
540    use super::Vec2;
541    const VEC2: Vec2<f32> = Vec2 { x: 1.0, y: 2.0 };
542
543    #[test]
544    fn test_new() {
545        assert_eq!(Vec2::new(1.0_f32, 2.0_f32), VEC2);
546    }
547
548    #[test]
549    fn test_zero() {
550        assert_eq!(Vec2::new(0.0_f32, 0.0_f32), Vec2::zero());
551        let z: Vec2<f32> = Vec2::zero();
552        assert_eq!(z[0], 0.0_f32);
553        assert_eq!(z[1], 0.0_f32);
554    }
555
556    #[test]
557    fn test_squared_magnitude() {
558        assert!(VEC2.squared_magnitude().approx_eq(&5.0, ::std::f32::EPSILON, 1));
559    }
560
561    #[test]
562    fn test_index() {
563        assert_eq!(VEC2[0], VEC2.x);
564        assert_eq!(VEC2[1], VEC2.y);
565    }
566
567    #[test]
568    fn test_index_mut() {
569        let mut v: Vec2<f32> = Vec2::new(3.0, 5.0);
570        v[1] = 6.0;
571        assert_eq!(v.y, 6.0);
572    }
573}