1use crate::Multivector;
4use alloc::string::{String, ToString};
5use alloc::vec;
6use alloc::vec::Vec;
7
8#[inline(always)]
10pub fn blade_grade(blade_index: usize) -> usize {
11 blade_index.count_ones() as usize
12}
13
14pub fn blade_name(blade_index: usize, dim: usize) -> String {
16 if blade_index == 0 {
17 return String::from("1"); }
19
20 let mut name = String::new();
21 name.push('e');
22
23 for i in 0..dim {
24 if (blade_index >> i) & 1 == 1 {
25 if name.len() > 1 {
26 name.push('_');
27 }
28 name.push_str(&(i + 1).to_string());
29 }
30 }
31
32 name
33}
34
35pub struct MultivectorBuilder<const P: usize, const Q: usize, const R: usize> {
37 coefficients: Vec<f64>,
38}
39
40impl<const P: usize, const Q: usize, const R: usize> Default for MultivectorBuilder<P, Q, R> {
41 fn default() -> Self {
42 Self::new()
43 }
44}
45
46impl<const P: usize, const Q: usize, const R: usize> MultivectorBuilder<P, Q, R> {
47 pub fn new() -> Self {
48 Self {
49 coefficients: vec![0.0; Multivector::<P, Q, R>::BASIS_COUNT],
50 }
51 }
52
53 pub fn scalar(mut self, value: f64) -> Self {
55 self.coefficients[0] = value;
56 self
57 }
58
59 pub fn e(mut self, i: usize, value: f64) -> Self {
61 assert!(i >= 1 && i <= P + Q + R, "Basis vector index out of range");
62 self.coefficients[1 << (i - 1)] = value;
63 self
64 }
65
66 pub fn e_wedge(mut self, i: usize, j: usize, value: f64) -> Self {
68 assert!(i != j, "Cannot wedge a vector with itself");
69 assert!(i >= 1 && i <= P + Q + R, "Basis vector i out of range");
70 assert!(j >= 1 && j <= P + Q + R, "Basis vector j out of range");
71
72 let index = (1 << (i - 1)) | (1 << (j - 1));
73 let sign = if i < j { 1.0 } else { -1.0 };
74 self.coefficients[index] = sign * value;
75 self
76 }
77
78 pub fn build(self) -> Multivector<P, Q, R> {
80 Multivector::from_coefficients(self.coefficients)
81 }
82}
83
84pub struct Basis;
86
87impl Basis {
88 pub fn e1<const P: usize, const Q: usize, const R: usize>() -> Multivector<P, Q, R> {
90 Multivector::basis_vector(0)
91 }
92
93 pub fn e2<const P: usize, const Q: usize, const R: usize>() -> Multivector<P, Q, R> {
95 Multivector::basis_vector(1)
96 }
97
98 pub fn e3<const P: usize, const Q: usize, const R: usize>() -> Multivector<P, Q, R> {
100 Multivector::basis_vector(2)
101 }
102
103 pub fn e12<const P: usize, const Q: usize, const R: usize>() -> Multivector<P, Q, R> {
105 let e1 = Self::e1();
106 let e2 = Self::e2();
107 e1.outer_product(&e2)
108 }
109
110 pub fn e23<const P: usize, const Q: usize, const R: usize>() -> Multivector<P, Q, R> {
112 let e2 = Self::e2();
113 let e3 = Self::e3();
114 e2.outer_product(&e3)
115 }
116
117 pub fn e31<const P: usize, const Q: usize, const R: usize>() -> Multivector<P, Q, R> {
119 let e3 = Self::e3();
120 let e1 = Self::e1();
121 e3.outer_product(&e1)
122 }
123
124 pub fn e123<const P: usize, const Q: usize, const R: usize>() -> Multivector<P, Q, R> {
126 let e1 = Self::e1();
127 let e2 = Self::e2();
128 let e3 = Self::e3();
129 e1.outer_product(&e2).outer_product(&e3)
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 type Cl3 = Multivector<3, 0, 0>;
138
139 #[test]
140 fn test_blade_names() {
141 assert_eq!(blade_name(0, 3), "1");
142 assert_eq!(blade_name(1, 3), "e1");
143 assert_eq!(blade_name(2, 3), "e2");
144 assert_eq!(blade_name(3, 3), "e1_2");
145 assert_eq!(blade_name(7, 3), "e1_2_3");
146 }
147
148 #[test]
149 fn test_builder() {
150 let mv = MultivectorBuilder::<3, 0, 0>::new()
151 .scalar(2.0)
152 .e(1, 3.0)
153 .e(2, 4.0)
154 .e_wedge(1, 2, 5.0)
155 .build();
156
157 assert_eq!(mv.get(0), 2.0); assert_eq!(mv.get(1), 3.0); assert_eq!(mv.get(2), 4.0); assert_eq!(mv.get(3), 5.0); }
162
163 #[test]
164 fn test_basis_helpers() {
165 let e1: Cl3 = Basis::e1();
166 let e2: Cl3 = Basis::e2();
167 let e12: Cl3 = Basis::e12();
168
169 assert_eq!(e1.get(1), 1.0);
170 assert_eq!(e2.get(2), 1.0);
171 assert_eq!(e12.get(3), 1.0);
172
173 let computed_e12 = e1.outer_product(&e2);
175 assert_eq!(computed_e12.get(3), e12.get(3));
176 }
177}