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