1use {
2 crate::num::Real,
3 alloc::vec::Vec,
4 core::ops::{Add, Div, Mul, Sub},
5};
6
7pub trait Vector<F: Field>:
8 Mul<F, Output = Self> + Add<Self, Output = Self> + Sized + Copy
9{
10 fn len(self) -> F;
11 fn dot(self, rhs: Self) -> F;
12 fn norm(self) -> Self;
13 fn cross(self, rhs: Self) -> Self;
14}
15
16pub trait Field: Add + Sub + Div + Mul + Sized {}
17
18impl<F: Add<F> + Sub<F> + Mul<F> + Div<F> + Sized> Field for F {}
19
20#[derive(Clone, Copy)]
21pub struct R3(pub [f32; 3]);
22
23impl Vector<f32> for R3 {
24 fn len(self) -> f32 {
25 self.dot(self).sqrt()
26 }
27
28 fn dot(self, rhs: Self) -> f32 {
29 let a = self.0;
30 let b = rhs.0;
31
32 a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
33 }
34
35 fn norm(self) -> Self {
36 self / self.len()
37 }
38
39 fn cross(self, rhs: Self) -> Self {
40 let a = self.0;
41 let b = rhs.0;
42
43 [
44 a[1] * b[2] - a[2] * b[1],
45 a[2] * b[0] - a[0] * b[2],
46 a[0] * b[1] - a[1] * b[0],
47 ]
48 .into()
49 }
50}
51
52pub fn span<V: Vector<f32>>(basis: [V; 2], range: u32) -> Vec<V> {
53 let range = range as i32;
54
55 let mut span = Vec::new();
56 for y in -range..=range {
57 for x in -range..=range {
58 span.push(basis[0] * x as f32 + basis[1] * y as f32)
59 }
60 }
61
62 span
63}
64
65impl core::ops::Add for R3 {
66 type Output = Self;
67
68 fn add(self, rhs: R3) -> Self {
69 let a = self.0;
70 let b = rhs.0;
71
72 [a[0] + b[0], a[1] + b[1], a[2] + b[2]].into()
73 }
74}
75
76impl core::ops::Neg for R3 {
77 type Output = Self;
78
79 fn neg(self) -> R3 {
80 let a = self.0;
81 [-a[0], -a[1], -a[2]].into()
82 }
83}
84
85impl core::ops::Sub for R3 {
86 type Output = Self;
87
88 fn sub(self, rhs: R3) -> R3 {
89 self + -rhs
90 }
91}
92
93impl core::ops::Div<f32> for R3 {
94 type Output = Self;
95
96 fn div(self, rhs: f32) -> Self {
97 let a = self.0;
98
99 [a[0] / rhs, a[1] / rhs, a[2] / rhs].into()
100 }
101}
102
103impl core::ops::Mul<f32> for R3 {
104 type Output = Self;
105
106 fn mul(self, rhs: f32) -> Self {
107 let a = self.0;
108
109 [a[0] * rhs, a[1] * rhs, a[2] * rhs].into()
110 }
111}
112
113impl core::ops::Index<u8> for R3 {
114 type Output = f32;
115
116 fn index(&self, idx: u8) -> &Self::Output {
117 &self.0[idx as usize]
118 }
119}
120
121impl From<[f32; 3]> for R3 {
122 fn from(r3: [f32; 3]) -> Self {
123 Self(r3)
124 }
125}
126
127#[cfg(test)]
128mod test {
129 use super::*;
130
131 #[test]
132 fn add() {
133 let x: R3 = [1.0, 2.0, 3.0].into();
134 let y: R3 = [4.0, 5.0, 6.0].into();
135
136 assert_eq!(x + y, [5.0, 7.0, 9.0].into())
137 }
138
139 #[test]
140 fn sub() {
141 let x: R3 = [1.0, 0.0, 0.0].into();
142 let y: R3 = [1.0, 0.0, 0.0].into();
143
144 assert_eq!(x - y, [0.0, 0.0, 0.0].into())
145 }
146
147 #[test]
148 fn orthogonal_dot_product() {
149 let x: R3 = [1.0, 0.0, 0.0].into();
150 let y: R3 = [0.0, 1.0, 0.0].into();
151
152 assert_eq!(x.dot(y), 0.0)
153 }
154
155 #[test]
156 fn unit_len() {
157 let x: R3 = [1.0, 0.0, 0.0].into();
158 assert_eq!(x.len(), 1.0)
159 }
160
161 #[test]
162 fn norm() {
163 let x: R3 = [2.0, 0.0, 0.0].into();
164 assert_eq!(x.norm(), [1.0, 0.0, 0.0].into())
165 }
166}