1use num_traits::{Float, One, Zero};
8use std::marker::PhantomData;
9
10#[cfg(feature = "formal-verification")]
11use creusot_contracts::{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 {
175 let swaps = self.count_swaps(blade1, blade2);
178 if swaps.is_multiple_of(2) {
179 1
180 } else {
181 -1
182 }
183 }
184
185 fn count_swaps(&self, blade1: usize, blade2: usize) -> usize {
187 let mut count = 0;
189 for i in 0..Self::DIM {
190 if blade1 & (1 << i) != 0 {
191 for j in 0..i {
192 if blade2 & (1 << j) != 0 {
193 count += 1;
194 }
195 }
196 }
197 }
198 count
199 }
200}
201
202pub struct KVector<T, const K: usize, const P: usize, const Q: usize, const R: usize>
207where
208 T: Float + Zero + One,
209{
210 multivector: VerifiedMultivector<T, P, Q, R>,
211 _grade: PhantomData<Grade<K>>,
212}
213
214impl<T, const K: usize, const P: usize, const Q: usize, const R: usize> KVector<T, K, P, Q, R>
215where
216 T: Float + Zero + One,
217{
218 #[cfg_attr(feature = "formal-verification",
220 requires(K <= P + Q + R),
221 ensures(result.grade() == K))]
222 pub fn from_multivector(mv: VerifiedMultivector<T, P, Q, R>) -> Self {
223 let mut coefficients = vec![T::zero(); VerifiedMultivector::<T, P, Q, R>::BASIS_SIZE];
224
225 for (i, coeff) in mv.coefficients.iter().enumerate() {
227 if i.count_ones() as usize == K {
228 coefficients[i] = *coeff;
229 }
230 }
231
232 Self {
233 multivector: VerifiedMultivector {
234 coefficients,
235 _signature: PhantomData,
236 },
237 _grade: PhantomData,
238 }
239 }
240
241 pub const fn grade(&self) -> usize {
243 K
244 }
245
246 pub fn inner_product(&self, other: &Self) -> T {
248 self.multivector
250 .coefficients
251 .iter()
252 .zip(&other.multivector.coefficients)
253 .map(|(a, b)| *a * *b)
254 .fold(T::zero(), |acc, x| acc + x)
255 }
256}
257
258pub trait OuterProduct<T, const J: usize, const P: usize, const Q: usize, const R: usize>
261where
262 T: Float + Zero + One,
263{
264 type Output;
265 fn outer_product(&self, other: &KVector<T, J, P, Q, R>) -> Self::Output;
266}
267
268impl<T, const P: usize, const Q: usize, const R: usize> OuterProduct<T, 1, P, Q, R>
271 for KVector<T, 1, P, Q, R>
272where
273 T: Float + Zero + One,
274{
275 type Output = KVector<T, 2, P, Q, R>;
276
277 fn outer_product(&self, other: &KVector<T, 1, P, Q, R>) -> Self::Output {
278 let mut coefficients = vec![T::zero(); VerifiedMultivector::<T, P, Q, R>::BASIS_SIZE];
279
280 for i in 0..VerifiedMultivector::<T, P, Q, R>::DIM {
282 for j in i + 1..VerifiedMultivector::<T, P, Q, R>::DIM {
283 let blade_i = 1 << i;
284 let blade_j = 1 << j;
285 let blade_ij = blade_i | blade_j;
286
287 coefficients[blade_ij] = self.multivector.coefficients[blade_i]
288 * other.multivector.coefficients[blade_j]
289 - self.multivector.coefficients[blade_j]
290 * other.multivector.coefficients[blade_i];
291 }
292 }
293
294 KVector {
295 multivector: VerifiedMultivector {
296 coefficients,
297 _signature: PhantomData,
298 },
299 _grade: PhantomData,
300 }
301 }
302}
303
304impl<T, const P: usize, const Q: usize, const R: usize> OuterProduct<T, 2, P, Q, R>
306 for KVector<T, 1, P, Q, R>
307where
308 T: Float + Zero + One,
309{
310 type Output = KVector<T, 3, P, Q, R>;
311
312 fn outer_product(&self, _other: &KVector<T, 2, P, Q, R>) -> Self::Output {
313 todo!("Implement grade 1 ∧ grade 2")
315 }
316}
317
318impl<T, const P: usize, const Q: usize, const R: usize> OuterProduct<T, 1, P, Q, R>
320 for KVector<T, 2, P, Q, R>
321where
322 T: Float + Zero + One,
323{
324 type Output = KVector<T, 3, P, Q, R>;
325
326 fn outer_product(&self, _other: &KVector<T, 1, P, Q, R>) -> Self::Output {
327 todo!("Implement grade 2 ∧ grade 1")
329 }
330}
331
332pub struct VerifiedRotor<T, const P: usize, const Q: usize, const R: usize>
337where
338 T: Float + Zero + One,
339{
340 multivector: VerifiedMultivector<T, P, Q, R>,
341 _rotor_invariant: PhantomData<()>,
343}
344
345impl<T, const P: usize, const Q: usize, const R: usize> VerifiedRotor<T, P, Q, R>
346where
347 T: Float + Zero + One,
348{
349 #[cfg_attr(feature = "formal-verification",
355 requires(mv.is_even_grade()),
356 requires((mv.norm() - T::one()).abs() < T::from(0.0001).unwrap()),
357 ensures(result.is_ok()))]
358 pub fn new(mv: VerifiedMultivector<T, P, Q, R>) -> Result<Self, &'static str> {
359 if !Self::is_even_grade(&mv) {
360 return Err("Rotor must have even grade");
361 }
362
363 let norm = Self::compute_norm(&mv);
364 if (norm - T::one()).abs() > T::from(0.0001).unwrap() {
365 return Err("Rotor must have unit norm");
366 }
367
368 Ok(Self {
369 multivector: mv,
370 _rotor_invariant: PhantomData,
371 })
372 }
373
374 fn is_even_grade(mv: &VerifiedMultivector<T, P, Q, R>) -> bool {
376 for (i, coeff) in mv.coefficients.iter().enumerate() {
377 let grade = i.count_ones() as usize;
378 if !grade.is_multiple_of(2) && !coeff.is_zero() {
379 return false;
380 }
381 }
382 true
383 }
384
385 fn compute_norm(mv: &VerifiedMultivector<T, P, Q, R>) -> T {
387 mv.coefficients
388 .iter()
389 .map(|c| *c * *c)
390 .fold(T::zero(), |acc, x| acc + x)
391 .sqrt()
392 }
393
394 #[cfg_attr(feature = "formal-verification",
400 ensures(Self::compute_norm(&result.multivector) == T::one()))]
401 pub fn compose(&self, other: &Self) -> Self {
402 let composed = self.multivector.geometric_product(&other.multivector);
403
404 let norm = Self::compute_norm(&composed);
406 let normalized = VerifiedMultivector {
407 coefficients: composed.coefficients.iter().map(|c| *c / norm).collect(),
408 _signature: PhantomData,
409 };
410
411 Self {
412 multivector: normalized,
413 _rotor_invariant: PhantomData,
414 }
415 }
416
417 pub fn apply<const D: usize>(&self, _v: &Vector<T, D>) -> Vector<T, D>
419 where
420 [(); D]: Sized,
421 {
422 todo!("Rotor application")
424 }
425}
426
427pub struct Vector<T, const D: usize>
429where
430 T: Float + Zero + One,
431{
432 pub(crate) data: Vec<T>,
433 _dim: PhantomData<Dim<D>>,
434}
435
436impl<T, const D: usize> Vector<T, D>
437where
438 T: Float + Zero + One,
439{
440 #[cfg_attr(feature = "formal-verification",
442 requires(data.len() == D),
443 ensures(result.dimension() == D))]
444 pub fn new(data: Vec<T>) -> Result<Self, &'static str> {
445 if data.len() != D {
446 return Err("Vector data length must match dimension");
447 }
448
449 Ok(Self {
450 data,
451 _dim: PhantomData,
452 })
453 }
454
455 pub const fn dimension(&self) -> usize {
457 D
458 }
459
460 #[cfg_attr(feature = "formal-verification",
462 ensures(result >= T::zero()))] pub fn dot(&self, other: &Self) -> T {
464 self.data
465 .iter()
466 .zip(&other.data)
467 .map(|(a, b)| *a * *b)
468 .fold(T::zero(), |acc, x| acc + x)
469 }
470
471 pub fn add(&self, other: &Self) -> Self {
473 Self {
474 data: self
475 .data
476 .iter()
477 .zip(&other.data)
478 .map(|(a, b)| *a + *b)
479 .collect(),
480 _dim: PhantomData,
481 }
482 }
483}
484
485#[cfg(test)]
486mod tests {
487 use super::*;
488
489 #[test]
490 fn test_phantom_type_dimension_safety() {
491 let v1 = Vector::<f64, 3>::new(vec![1.0, 2.0, 3.0]).unwrap();
493 let v2 = Vector::<f64, 3>::new(vec![4.0, 5.0, 6.0]).unwrap();
494 let _v3 = v1.add(&v2); }
500
501 #[test]
502 fn test_signature_type_safety() {
503 let mv1 = VerifiedMultivector::<f64, 3, 0, 0>::scalar(2.0);
505 let mv2 = VerifiedMultivector::<f64, 3, 0, 0>::scalar(3.0);
506 let _mv3 = mv1.add(&mv2); }
512
513 #[test]
514 fn test_grade_preservation() {
515 let bivector =
517 KVector::<f64, 2, 3, 0, 0>::from_multivector(VerifiedMultivector::scalar(1.0));
518
519 assert_eq!(bivector.grade(), 2);
520 }
522
523 #[test]
524 fn test_outer_product_type_safety() {
525 use super::OuterProduct;
526
527 let v1 = KVector::<f64, 1, 3, 0, 0>::from_multivector(
529 VerifiedMultivector::basis_vector(0).unwrap(),
530 );
531 let v2 = KVector::<f64, 1, 3, 0, 0>::from_multivector(
532 VerifiedMultivector::basis_vector(1).unwrap(),
533 );
534
535 let bivector: KVector<f64, 2, 3, 0, 0> = v1.outer_product(&v2);
537
538 assert_eq!(bivector.grade(), 2);
540
541 }
545}