1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use crate::clifford::{Graded, Involution, Mask};
use abstalg::{BooleanAlgebra, BoundedOrder, DistributiveLattice, Domain, Lattice, PartialOrder};
use std::ops::BitXor;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Metric<U: Mask> {
/// dimensions of the frame
pub dimensions: usize,
/// number of basis elements with positive square
pub positive: usize,
/// number of basis elements with negative square
pub negative: usize,
/// bitmask representing all basis elements
pub supremum: U,
/// bitmask representing the basis elements with positive square
pub hypermum: U,
/// bitmask representing the basis elements with negative square
pub imagimum: U,
/// bitmask representing the empty basis element
pub infinum: U,
}
impl<U: Mask> PartialOrder for Metric<U> {
fn leq(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
(*elem1 & *elem2) == *elem1
}
fn less_than(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
let meet = *elem1 & *elem2;
meet == *elem1 && meet != *elem2
}
fn comparable(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
let meet = *elem1 & *elem2;
meet == *elem1 || meet == *elem2
}
}
impl<U: Mask> BoundedOrder for Metric<U> {
fn max(&self) -> Self::Elem {
self.supremum
}
fn min(&self) -> Self::Elem {
self.infinum
}
}
impl<U: Mask> Lattice for Metric<U> {
#[inline]
fn meet(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
*elem1 & *elem2
}
#[inline]
fn join(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
*elem1 | *elem2
}
}
impl<U: Mask> DistributiveLattice for Metric<U> {}
impl<U: Mask> BooleanAlgebra for Metric<U> {
fn not(&self, elem: &Self::Elem) -> Self::Elem {
*elem ^ self.supremum
}
}
impl<U: Mask> Metric<U> {
#[inline]
/// Return the scalar (grade-0) blade for this metric.
pub fn one(&self) -> U {
self.infinum
}
}
impl<U: Mask> Domain for Metric<U> {
type Elem = U;
fn equals(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
elem1 == elem2
}
fn contains(&self, elem: &Self::Elem) -> bool {
self.supremum & *elem == *elem
}
}
impl<U: Mask> Metric<U> {
/// Create a new FrameMetric given the count of positive and negative basis elements.
#[inline]
pub fn new(positive: usize, negative: usize) -> Self {
Self {
dimensions: positive + negative,
positive,
negative,
supremum: U::ones(positive + negative, 0),
hypermum: U::ones(positive, 0),
imagimum: U::ones(negative, positive),
infinum: U::ZERO,
}
}
// /// Determine the swap parity between two basis elements. Does not account for metric.
// #[inline]
// #[must_use]
// fn swap_parity(&self, lhs: U, mut rhs: U) -> bool {
// let mut parity = false;
// while !rhs.is_zero() {
// let rhs_bit = rhs & (!rhs + 1); // least significant bit of rhs
// rhs ^= rhs_bit; // clear least significant bit
// let mask_lower = rhs_bit - 1; // masks for bits below rhs_bit
// let mask_upper = !mask_lower ^ rhs_bit; // masks for bits above
// let lhs_upper = lhs & mask_upper; // bits rhs_bit needs to move past
// let swaps = lhs_upper.count_ones(); // how many swaps needed
// parity ^= swaps & 1 != 0; // flip parity if odd number of swaps
// }
// parity
// }
// /// Determine the metric parity of a basis element. Does not account for swaps.
// #[inline]
// #[must_use]
// pub fn metric_parity(&self, basis: U) -> bool {
// // the metric is determined by the oddness of the number of negative basis elements
// (basis & self.imagimum).count_ones() & 1 != 0
// }
#[inline]
/// Compute the sign introduced by multiplying `lhs` and `rhs` under the metric.
pub fn mul_parity(&self, lhs: U, rhs: U) -> bool {
// self.swap_parity(lhs, rhs) ^ self.metric_parity(lhs & rhs)
// but faster
// todo: could be even faster!
(0..self.dimensions)
.map(|k| (lhs >> k) & rhs)
.fold(self.hypermum & lhs & rhs, BitXor::bitxor)
.parity()
}
#[inline]
/// Compute the symmetric difference between two basis masks.
pub fn sym_diff(&self, lhs: U, rhs: U) -> U {
lhs ^ rhs
}
}
impl<U: Mask> Graded for Metric<U> {
type Grade = u32;
type Output = Option<Self::Elem>;
fn grade_of(&self, elem: &Self::Elem) -> Self::Grade {
elem.count_ones()
}
fn grade_by(&self, elem: &Self::Elem, grade: Self::Grade) -> Self::Output {
(self.grade_of(elem) == grade).then_some(*elem)
}
}
impl<U: Mask> Involution for Metric<U> {
type Output = bool;
#[inline]
fn automorphism(&self, elem: Self::Elem) -> Self::Output {
let g = self.grade_of(&elem);
g & 1 != 0
}
#[inline]
fn reverse(&self, elem: Self::Elem) -> Self::Output {
let g = self.grade_of(&elem);
g & 2 != 0
}
#[inline]
fn conjugate(&self, elem: Self::Elem) -> Self::Output {
let g = self.grade_of(&elem);
(g & 1 != 0) ^ (g & 2 != 0)
}
}