vg_algebra/
vectors.rs

1use core::f64;
2use std::ops::{Add, Mul, Sub};
3
4pub mod vector2d;
5pub mod vector3d;
6
7/// Trait for common operations a Vector needs to be able to do
8pub trait VectorTrait<Rhs = Self>: Add + Sub + Mul + Sized + Copy {
9    /// provides scaling with scalar as f64
10    fn scale(&self, other: f64) -> Self;
11    /// provides the length or magnitude of vector as f64
12    fn length(&self) -> f64;
13    /// wrapper for length
14    fn abs(&self) -> f64 {
15        self.length()
16    }
17    /// returns the norm of the vector, i.e scale the vector to length 1
18    fn normalize(&self) -> Self;
19    /// checks if vector is colinear with other vector
20    fn is_colinear_to(&self, rhs: Rhs) -> bool;
21
22    /// Output type for wedge product
23    /// Needs to act as bivector
24    type WedgeProductOutput: BivectorTrait;
25    /// Returns the wedge product of vector with other vector
26    fn wedge_product(&self, rhs: Rhs) -> Self::WedgeProductOutput;
27
28    /// Output type for cross product
29    type CrossProductOutput;
30    /// Returns cross product of self with other vector
31    fn cross_product(&self, rhs: Rhs) -> Self::CrossProductOutput;
32
33    ///Returns dot product of self with other vector
34    fn dot_product(&self, rhs: Rhs) -> f64;
35}
36
37/// Trait for common operations a bivector needs to be able to do
38pub trait BivectorTrait {
39    ///scales a bivector with p
40    fn scale(&self, p: f64) -> Self;
41    /// returns the magnitude or area of the bivector
42    fn magnitude(&self) -> f64;
43}
44
45/// Checks if a pair of two vectors of same vector type is colinear
46pub fn check_colinearity<T>(a: &T, b: &T) -> bool
47where
48    T: VectorTrait,
49{
50    a.is_colinear_to(*b)
51}
52
53/// Returns the Cross product of a pair of vectors of same vector type
54pub fn cross_product<T>(a: T, b: T) -> <T as VectorTrait>::CrossProductOutput
55where
56    T: VectorTrait,
57{
58    a.cross_product(b)
59}
60
61/// Returns the wedge product of a pair of vectors of same vector type
62pub fn wedge_product<T>(a: T, b: T) -> <T as VectorTrait>::WedgeProductOutput
63where
64    T: VectorTrait,
65{
66    a.wedge_product(b)
67}
68
69/// Returns the dot product of a a pair of vectors of same vector type
70pub fn dot_product<T>(a: T, b: T) -> f64
71where
72    T: VectorTrait,
73{
74    a.dot_product(b)
75}
76
77#[cfg(test)]
78mod test_vectors {
79    use crate::vectors::{check_colinearity, dot_product, wedge_product, VectorTrait};
80
81    use super::{cross_product, vector2d, vector3d};
82
83    #[test]
84    fn test_check_colinearity() {
85        let a = vector3d::Vector::new(0.1, 0.3, 0.6);
86        let b = vector3d::Vector::new(2.0, 0.3, 0.0);
87        let c = vector3d::Vector::new(0.2, 0.6, 1.2);
88
89        assert_eq!(check_colinearity(&a, &b), check_colinearity(&b, &c));
90        assert!(check_colinearity(&a, &c));
91        assert!(check_colinearity(&a, &a))
92    }
93
94    #[test]
95    fn test_cross_product_2d() {
96        let a = vector2d::Vector::new(1.0, 2.0);
97        let b = vector2d::Vector::new(0.5, 1.0);
98
99        let expected = 0.0;
100        let result = cross_product(a, b);
101
102        assert_eq!(expected, result)
103    }
104
105    #[test]
106    fn test_cross_product_3d() {
107        let a = vector3d::Vector::new(1.0, 2.0, 0.5);
108        let b = vector3d::Vector::new(0.5, 1.0, 2.0);
109
110        let expected = vector3d::Vector::new(3.5, -1.75, 0.0);
111        let result = cross_product(a, b);
112
113        assert_eq!(expected, result)
114    }
115
116    #[test]
117    fn test_wedge_product_2d() {
118        let a = vector2d::Vector::new(1.0, 2.0);
119        let b = vector2d::Vector::new(0.5, 1.0);
120
121        let expected = vector2d::Bivector(0.0);
122        let result = wedge_product(a, b);
123
124        assert_eq!(expected, result)
125    }
126
127    #[test]
128    fn test_wedge_product_3d() {
129        let a = vector3d::Vector::new(1.0, 2.0, 0.5);
130        let b = vector3d::Vector::new(0.5, 1.0, 2.0);
131
132        let expected = vector3d::Bivector::new(3.5, -1.75, 0.0);
133        let result = wedge_product(a, b);
134
135        assert_eq!(expected, result)
136    }
137
138    #[test]
139    fn test_dot_product_3d() {
140        let a = vector3d::Vector::new(1.0, 2.0, 0.5);
141        let b = vector3d::Vector::new(0.5, 1.0, 2.0);
142
143        let expected = 3.5;
144        let result = dot_product(a, b);
145
146        assert_eq!(expected, result)
147    }
148
149    #[test]
150    fn test_dot_product_2d() {
151        let a = vector2d::Vector::new(1.0, 2.0);
152        let b = vector2d::Vector::new(0.5, 1.0);
153
154        let expected = 2.5;
155        let result = dot_product(a, b);
156
157        assert_eq!(expected, result)
158    }
159
160    #[test]
161    fn test_default_abs_implementation() {
162        let a = vector2d::Vector::new(3.0, 4.0);
163
164        let expected = 5.0;
165        let result = a.abs();
166
167        assert_eq!(expected, result);
168
169        let b = vector3d::Vector::new(0.5, 1.0, 2.0);
170
171        assert_eq!(b.length(), b.abs());
172    }
173}