1use core::f64;
2use std::ops::{Add, Mul, Sub};
3
4pub mod vector2d;
5pub mod vector3d;
6
7pub trait VectorTrait<Rhs = Self>: Add + Sub + Mul + Sized + Copy {
9 fn scale(&self, other: f64) -> Self;
11 fn length(&self) -> f64;
13 fn abs(&self) -> f64 {
15 self.length()
16 }
17 fn normalize(&self) -> Self;
19 fn is_colinear_to(&self, rhs: Rhs) -> bool;
21
22 type WedgeProductOutput: BivectorTrait;
25 fn wedge_product(&self, rhs: Rhs) -> Self::WedgeProductOutput;
27
28 type CrossProductOutput;
30 fn cross_product(&self, rhs: Rhs) -> Self::CrossProductOutput;
32
33 fn dot_product(&self, rhs: Rhs) -> f64;
35}
36
37pub trait BivectorTrait {
39 fn scale(&self, p: f64) -> Self;
41 fn magnitude(&self) -> f64;
43}
44
45pub fn check_colinearity<T>(a: &T, b: &T) -> bool
47where
48 T: VectorTrait,
49{
50 a.is_colinear_to(*b)
51}
52
53pub fn cross_product<T>(a: T, b: T) -> <T as VectorTrait>::CrossProductOutput
55where
56 T: VectorTrait,
57{
58 a.cross_product(b)
59}
60
61pub fn wedge_product<T>(a: T, b: T) -> <T as VectorTrait>::WedgeProductOutput
63where
64 T: VectorTrait,
65{
66 a.wedge_product(b)
67}
68
69pub 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}