1use num_traits::{Float, One, Zero};
8use std::marker::PhantomData;
9
10#[cfg(feature = "formal-verification")]
11use creusot_contracts::macros::{ensures, requires};
12
13pub struct Signature<const P: usize, const Q: usize, const R: usize>;
18
19pub struct Grade<const G: usize>;
21
22pub struct Dim<const D: usize>;
24
25#[derive(Debug, Clone)]
32pub struct VerifiedMultivector<T, const P: usize, const Q: usize, const R: usize>
33where
34 T: Float + Zero + One,
35{
36 pub(crate) coefficients: Vec<T>,
38 _signature: PhantomData<Signature<P, Q, R>>,
40}
41
42impl<T, const P: usize, const Q: usize, const R: usize> VerifiedMultivector<T, P, Q, R>
43where
44 T: Float + Zero + One,
45{
46 pub const DIM: usize = P + Q + R;
48
49 pub const BASIS_SIZE: usize = 1 << (P + Q + R);
51
52 #[cfg_attr(feature = "formal-verification",
58 requires(coefficients.len() == Self::BASIS_SIZE))]
59 pub fn new(coefficients: Vec<T>) -> Result<Self, &'static str> {
60 if coefficients.len() != Self::BASIS_SIZE {
61 return Err("Coefficient array size must equal 2^(P+Q+R)");
62 }
63
64 Ok(Self {
65 coefficients,
66 _signature: PhantomData,
67 })
68 }
69
70 #[cfg_attr(feature = "formal-verification",
72 ensures(result.is_scalar()),
73 ensures(result.coefficients[0] == value),
74 ensures(result.coefficients.len() == Self::BASIS_SIZE))]
75 pub fn scalar(value: T) -> Self {
76 let mut coefficients = vec![T::zero(); Self::BASIS_SIZE];
77 coefficients[0] = value;
78
79 Self {
80 coefficients,
81 _signature: PhantomData,
82 }
83 }
84
85 #[cfg_attr(feature = "formal-verification",
90 requires(index < Self::DIM),
91 ensures(result.grade() == 1))]
92 pub fn basis_vector(index: usize) -> Result<Self, &'static str> {
93 if index >= Self::DIM {
94 return Err("Basis vector index exceeds dimension");
95 }
96
97 let mut coefficients = vec![T::zero(); Self::BASIS_SIZE];
98 coefficients[1 << index] = T::one();
99
100 Ok(Self {
101 coefficients,
102 _signature: PhantomData,
103 })
104 }
105
106 #[cfg_attr(feature = "formal-verification",
108 ensures(result == (self.coefficients[1..].iter().all(|c| c.is_zero()))))]
109 pub fn is_scalar(&self) -> bool {
110 self.coefficients[1..].iter().all(|c| c.is_zero())
111 }
112
113 #[cfg_attr(feature = "formal-verification",
115 ensures(result <= Self::DIM))]
116 pub fn grade(&self) -> usize {
117 for (i, coeff) in self.coefficients.iter().enumerate().rev() {
119 if !coeff.is_zero() {
120 return i.count_ones() as usize;
121 }
122 }
123 0
124 }
125
126 #[cfg_attr(feature = "formal-verification",
128 ensures(result.coefficients.len() == self.coefficients.len()))]
129 pub fn add(&self, other: &Self) -> Self {
130 let coefficients: Vec<T> = self
131 .coefficients
132 .iter()
133 .zip(&other.coefficients)
134 .map(|(a, b)| *a + *b)
135 .collect();
136
137 Self {
138 coefficients,
139 _signature: PhantomData,
140 }
141 }
142
143 #[cfg_attr(feature = "formal-verification",
150 requires(self.coefficients.len() == Self::BASIS_SIZE),
151 requires(other.coefficients.len() == Self::BASIS_SIZE),
152 ensures(result.coefficients.len() == Self::BASIS_SIZE))]
153 pub fn geometric_product(&self, other: &Self) -> Self {
154 let mut result = vec![T::zero(); Self::BASIS_SIZE];
157
158 for i in 0..Self::BASIS_SIZE {
159 for j in 0..Self::BASIS_SIZE {
160 let sign = self.compute_product_sign(i, j);
161 let target_index = i ^ j; result[target_index] = result[target_index]
163 + self.coefficients[i] * other.coefficients[j] * T::from(sign).unwrap();
164 }
165 }
166
167 Self {
168 coefficients: result,
169 _signature: PhantomData,
170 }
171 }
172
173 fn compute_product_sign(&self, blade1: usize, blade2: usize) -> i32 {
180 let swaps = self.count_swaps(blade1, blade2);
182 let mut sign: i32 = if swaps.is_multiple_of(2) { 1 } else { -1 };
183
184 let shared = blade1 & blade2;
187 for i in 0..Self::DIM {
188 if shared & (1 << i) != 0 {
189 if i >= P + Q {
190 return 0;
192 } else if i >= P {
193 sign = -sign;
195 }
196 }
198 }
199
200 sign
201 }
202
203 fn count_swaps(&self, blade1: usize, blade2: usize) -> usize {
205 let mut count = 0;
207 for i in 0..Self::DIM {
208 if blade1 & (1 << i) != 0 {
209 for j in 0..i {
210 if blade2 & (1 << j) != 0 {
211 count += 1;
212 }
213 }
214 }
215 }
216 count
217 }
218}
219
220pub struct KVector<T, const K: usize, const P: usize, const Q: usize, const R: usize>
225where
226 T: Float + Zero + One,
227{
228 multivector: VerifiedMultivector<T, P, Q, R>,
229 _grade: PhantomData<Grade<K>>,
230}
231
232impl<T, const K: usize, const P: usize, const Q: usize, const R: usize> KVector<T, K, P, Q, R>
233where
234 T: Float + Zero + One,
235{
236 #[cfg_attr(feature = "formal-verification",
238 requires(K <= P + Q + R),
239 ensures(result.grade() == K))]
240 pub fn from_multivector(mv: VerifiedMultivector<T, P, Q, R>) -> Self {
241 let mut coefficients = vec![T::zero(); VerifiedMultivector::<T, P, Q, R>::BASIS_SIZE];
242
243 for (i, coeff) in mv.coefficients.iter().enumerate() {
245 if i.count_ones() as usize == K {
246 coefficients[i] = *coeff;
247 }
248 }
249
250 Self {
251 multivector: VerifiedMultivector {
252 coefficients,
253 _signature: PhantomData,
254 },
255 _grade: PhantomData,
256 }
257 }
258
259 pub const fn grade(&self) -> usize {
261 K
262 }
263
264 pub fn inner_product(&self, other: &Self) -> T {
266 self.multivector
268 .coefficients
269 .iter()
270 .zip(&other.multivector.coefficients)
271 .map(|(a, b)| *a * *b)
272 .fold(T::zero(), |acc, x| acc + x)
273 }
274}
275
276pub trait OuterProduct<T, const J: usize, const P: usize, const Q: usize, const R: usize>
279where
280 T: Float + Zero + One,
281{
282 type Output;
283 fn outer_product(&self, other: &KVector<T, J, P, Q, R>) -> Self::Output;
284}
285
286impl<T, const P: usize, const Q: usize, const R: usize> OuterProduct<T, 1, P, Q, R>
289 for KVector<T, 1, P, Q, R>
290where
291 T: Float + Zero + One,
292{
293 type Output = KVector<T, 2, P, Q, R>;
294
295 fn outer_product(&self, other: &KVector<T, 1, P, Q, R>) -> Self::Output {
296 let mut coefficients = vec![T::zero(); VerifiedMultivector::<T, P, Q, R>::BASIS_SIZE];
297
298 for i in 0..VerifiedMultivector::<T, P, Q, R>::DIM {
300 for j in i + 1..VerifiedMultivector::<T, P, Q, R>::DIM {
301 let blade_i = 1 << i;
302 let blade_j = 1 << j;
303 let blade_ij = blade_i | blade_j;
304
305 coefficients[blade_ij] = self.multivector.coefficients[blade_i]
306 * other.multivector.coefficients[blade_j]
307 - self.multivector.coefficients[blade_j]
308 * other.multivector.coefficients[blade_i];
309 }
310 }
311
312 KVector {
313 multivector: VerifiedMultivector {
314 coefficients,
315 _signature: PhantomData,
316 },
317 _grade: PhantomData,
318 }
319 }
320}
321
322impl<T, const P: usize, const Q: usize, const R: usize> OuterProduct<T, 2, P, Q, R>
324 for KVector<T, 1, P, Q, R>
325where
326 T: Float + Zero + One,
327{
328 type Output = KVector<T, 3, P, Q, R>;
329
330 fn outer_product(&self, other: &KVector<T, 2, P, Q, R>) -> Self::Output {
331 let dim = VerifiedMultivector::<T, P, Q, R>::DIM;
332 let basis_size = VerifiedMultivector::<T, P, Q, R>::BASIS_SIZE;
333 let mut coefficients = vec![T::zero(); basis_size];
334
335 for i in 0..dim {
338 let blade_i = 1usize << i;
339 for j in 0..basis_size {
340 if j.count_ones() != 2 {
341 continue;
342 }
343 if blade_i & j == 0 {
345 let target = blade_i | j;
346 let mut swaps = 0;
348 for k in 0..i {
349 if j & (1 << k) != 0 {
350 swaps += 1;
351 }
352 }
353 let sign = if swaps % 2 == 0 { T::one() } else { -T::one() };
354 coefficients[target] = coefficients[target]
355 + sign
356 * self.multivector.coefficients[blade_i]
357 * other.multivector.coefficients[j];
358 }
359 }
360 }
361
362 KVector {
363 multivector: VerifiedMultivector {
364 coefficients,
365 _signature: PhantomData,
366 },
367 _grade: PhantomData,
368 }
369 }
370}
371
372impl<T, const P: usize, const Q: usize, const R: usize> OuterProduct<T, 1, P, Q, R>
374 for KVector<T, 2, P, Q, R>
375where
376 T: Float + Zero + One,
377{
378 type Output = KVector<T, 3, P, Q, R>;
379
380 fn outer_product(&self, other: &KVector<T, 1, P, Q, R>) -> Self::Output {
381 let dim = VerifiedMultivector::<T, P, Q, R>::DIM;
382 let basis_size = VerifiedMultivector::<T, P, Q, R>::BASIS_SIZE;
383 let mut coefficients = vec![T::zero(); basis_size];
384
385 for i in 0..basis_size {
388 if i.count_ones() != 2 {
389 continue;
390 }
391 for j in 0..dim {
392 let blade_j = 1usize << j;
393 if i & blade_j == 0 {
395 let target = i | blade_j;
396 let mut swaps = 0;
398 for k in (j + 1)..dim {
399 if i & (1 << k) != 0 {
400 swaps += 1;
401 }
402 }
403 let sign = if swaps % 2 == 0 { T::one() } else { -T::one() };
404 coefficients[target] = coefficients[target]
405 + sign
406 * self.multivector.coefficients[i]
407 * other.multivector.coefficients[blade_j];
408 }
409 }
410 }
411
412 KVector {
413 multivector: VerifiedMultivector {
414 coefficients,
415 _signature: PhantomData,
416 },
417 _grade: PhantomData,
418 }
419 }
420}
421
422pub struct VerifiedRotor<T, const P: usize, const Q: usize, const R: usize>
427where
428 T: Float + Zero + One,
429{
430 multivector: VerifiedMultivector<T, P, Q, R>,
431 _rotor_invariant: PhantomData<()>,
433}
434
435impl<T, const P: usize, const Q: usize, const R: usize> VerifiedRotor<T, P, Q, R>
436where
437 T: Float + Zero + One,
438{
439 #[cfg_attr(feature = "formal-verification",
445 requires(mv.is_even_grade()),
446 requires((mv.norm() - T::one()).abs() < T::from(0.0001).unwrap()),
447 ensures(result.is_ok()))]
448 pub fn new(mv: VerifiedMultivector<T, P, Q, R>) -> Result<Self, &'static str> {
449 if !Self::is_even_grade(&mv) {
450 return Err("Rotor must have even grade");
451 }
452
453 let norm = Self::compute_norm(&mv);
454 if (norm - T::one()).abs() > T::from(0.0001).unwrap() {
455 return Err("Rotor must have unit norm");
456 }
457
458 Ok(Self {
459 multivector: mv,
460 _rotor_invariant: PhantomData,
461 })
462 }
463
464 fn is_even_grade(mv: &VerifiedMultivector<T, P, Q, R>) -> bool {
466 for (i, coeff) in mv.coefficients.iter().enumerate() {
467 let grade = i.count_ones() as usize;
468 if !grade.is_multiple_of(2) && !coeff.is_zero() {
469 return false;
470 }
471 }
472 true
473 }
474
475 fn compute_norm(mv: &VerifiedMultivector<T, P, Q, R>) -> T {
477 mv.coefficients
478 .iter()
479 .map(|c| *c * *c)
480 .fold(T::zero(), |acc, x| acc + x)
481 .sqrt()
482 }
483
484 #[cfg_attr(feature = "formal-verification",
490 ensures(Self::compute_norm(&result.multivector) == T::one()))]
491 pub fn compose(&self, other: &Self) -> Self {
492 let composed = self.multivector.geometric_product(&other.multivector);
493
494 let norm = Self::compute_norm(&composed);
496 let normalized = VerifiedMultivector {
497 coefficients: composed.coefficients.iter().map(|c| *c / norm).collect(),
498 _signature: PhantomData,
499 };
500
501 Self {
502 multivector: normalized,
503 _rotor_invariant: PhantomData,
504 }
505 }
506
507 pub fn apply_to_multivector(
511 &self,
512 v: &VerifiedMultivector<T, P, Q, R>,
513 ) -> VerifiedMultivector<T, P, Q, R> {
514 let mut rev_coeffs = self.multivector.coefficients.clone();
516 for (i, coeff) in rev_coeffs.iter_mut().enumerate() {
517 let grade = i.count_ones() as usize;
518 if grade >= 2 && (grade * (grade - 1) / 2) % 2 == 1 {
519 *coeff = -*coeff;
520 }
521 }
522 let r_rev = VerifiedMultivector::<T, P, Q, R> {
523 coefficients: rev_coeffs,
524 _signature: PhantomData,
525 };
526
527 let rv = self.multivector.geometric_product(v);
529 rv.geometric_product(&r_rev)
530 }
531}
532
533pub struct Vector<T, const D: usize>
535where
536 T: Float + Zero + One,
537{
538 pub(crate) data: Vec<T>,
539 _dim: PhantomData<Dim<D>>,
540}
541
542impl<T, const D: usize> Vector<T, D>
543where
544 T: Float + Zero + One,
545{
546 #[cfg_attr(feature = "formal-verification",
548 requires(data.len() == D),
549 ensures(result.dimension() == D))]
550 pub fn new(data: Vec<T>) -> Result<Self, &'static str> {
551 if data.len() != D {
552 return Err("Vector data length must match dimension");
553 }
554
555 Ok(Self {
556 data,
557 _dim: PhantomData,
558 })
559 }
560
561 pub const fn dimension(&self) -> usize {
563 D
564 }
565
566 #[cfg_attr(feature = "formal-verification",
568 ensures(result >= T::zero()))] pub fn dot(&self, other: &Self) -> T {
570 self.data
571 .iter()
572 .zip(&other.data)
573 .map(|(a, b)| *a * *b)
574 .fold(T::zero(), |acc, x| acc + x)
575 }
576
577 pub fn add(&self, other: &Self) -> Self {
579 Self {
580 data: self
581 .data
582 .iter()
583 .zip(&other.data)
584 .map(|(a, b)| *a + *b)
585 .collect(),
586 _dim: PhantomData,
587 }
588 }
589}
590
591#[cfg(test)]
592mod tests {
593 use super::*;
594
595 #[test]
596 fn test_phantom_type_dimension_safety() {
597 let v1 = Vector::<f64, 3>::new(vec![1.0, 2.0, 3.0]).unwrap();
599 let v2 = Vector::<f64, 3>::new(vec![4.0, 5.0, 6.0]).unwrap();
600 let _v3 = v1.add(&v2); }
606
607 #[test]
608 fn test_signature_type_safety() {
609 let mv1 = VerifiedMultivector::<f64, 3, 0, 0>::scalar(2.0);
611 let mv2 = VerifiedMultivector::<f64, 3, 0, 0>::scalar(3.0);
612 let _mv3 = mv1.add(&mv2); }
618
619 #[test]
620 fn test_grade_preservation() {
621 let bivector =
623 KVector::<f64, 2, 3, 0, 0>::from_multivector(VerifiedMultivector::scalar(1.0));
624
625 assert_eq!(bivector.grade(), 2);
626 }
628
629 #[test]
630 fn test_outer_product_type_safety() {
631 use super::OuterProduct;
632
633 let v1 = KVector::<f64, 1, 3, 0, 0>::from_multivector(
635 VerifiedMultivector::basis_vector(0).unwrap(),
636 );
637 let v2 = KVector::<f64, 1, 3, 0, 0>::from_multivector(
638 VerifiedMultivector::basis_vector(1).unwrap(),
639 );
640
641 let bivector: KVector<f64, 2, 3, 0, 0> = v1.outer_product(&v2);
643
644 assert_eq!(bivector.grade(), 2);
646
647 }
651}