-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathabsext4.h
209 lines (191 loc) · 5.07 KB
/
absext4.h
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#pragma once
/*
*
* AbsExt4
*
* Support for performing exterior calculus in R4
*
* Used for performing filter computations.
* All numbers are positive! (overflow/underflow are concerns) and all numbers are kept positive
*
*/
#include "ext4.h"
#include <cmath>
namespace AbsExt4 {
using namespace Ext4;
using std::fabs;
struct AbsExt4_1 {
union {
double v[4];
struct {
double e0;
double e1;
double e2;
double e3;
};
};
};
struct AbsExt4_2 {
union {
double v[6];
struct {
double e01;
double e02;
double e03;
double e12;
double e13;
double e23;
};
};
};
struct AbsExt4_3 {
union {
double v[4];
struct {
double e012;
double e013;
double e023;
double e123;
};
};
};
// ************************
// An abs takes a k-vector and returns a version with
// absolute values of all the coordinates taken
inline void abs(AbsExt4_1 &out, const Ext4_1 &in) {
for (int i = 0; i<4; i++)
out.v[i] = fabs(in.v[i]);
}
inline void abs(AbsExt4_2 &out, const Ext4_2 &in) {
for (int i = 0; i<6; i++)
out.v[i] = fabs(in.v[i]);
}
inline void abs(AbsExt4_3 &out, const Ext4_3 &in) {
for (int i = 0; i<4; i++)
out.v[i] = fabs(in.v[i]);
}
// ************************
// A neg takes a k-vector and returns its negation
// neg(X,Y) is safe for X=Y
inline void neg(AbsExt4_1 &out, const AbsExt4_1 &in) {
out = in;
}
inline void neg(AbsExt4_2 &out, const AbsExt4_2 &in) {
out = in;
}
inline void neg(AbsExt4_3 &out, const AbsExt4_3 &in) {
out = in;
}
// ************************
// A dual operation takes a k-vector and returns a (4-k)-vector
// A reverse dual operation inverts the dual operation
// dual(X,Y) is not safe for X=Y (same with revdual)
inline void dual(AbsExt4_1 &out, const AbsExt4_3 &in) {
out.e0 = in.e123;
out.e1 = in.e023;
out.e2 = in.e013;
out.e3 = in.e012;
}
inline void dual(AbsExt4_2 &out, const AbsExt4_2 &in) {
out.e01 = in.e23;
out.e02 = in.e13;
out.e03 = in.e12;
out.e12 = in.e03;
out.e13 = in.e02;
out.e23 = in.e01;
}
inline void dual(AbsExt4_3 &out, const AbsExt4_1 &in) {
out.e012 = in.e3;
out.e013 = in.e2;
out.e023 = in.e1;
out.e123 = in.e0;
}
inline void revdual(AbsExt4_1 &out, const AbsExt4_3 &in) {
out.e0 = in.e123;
out.e1 = in.e023;
out.e2 = in.e013;
out.e3 = in.e012;
}
inline void revdual(AbsExt4_2 &out, const AbsExt4_2 &in) {
out.e01 = in.e23;
out.e02 = in.e13;
out.e03 = in.e12;
out.e12 = in.e03;
out.e13 = in.e02;
out.e23 = in.e01;
}
inline void revdual(AbsExt4_3 &out, const AbsExt4_1 &in) {
out.e012 = in.e3;
out.e013 = in.e2;
out.e023 = in.e1;
out.e123 = in.e0;
}
// ************************
// A join takes a j-vector and a k-vector and returns a (j+k)-vector
inline void join(AbsExt4_2 &out, const AbsExt4_1 &lhs, const AbsExt4_1 &rhs) {
out.e01 = (lhs.e0 * rhs.e1) + (rhs.e0 * lhs.e1);
out.e02 = (lhs.e0 * rhs.e2) + (rhs.e0 * lhs.e2);
out.e03 = (lhs.e0 * rhs.e3) + (rhs.e0 * lhs.e3);
out.e12 = (lhs.e1 * rhs.e2) + (rhs.e1 * lhs.e2);
out.e13 = (lhs.e1 * rhs.e3) + (rhs.e1 * lhs.e3);
out.e23 = (lhs.e2 * rhs.e3) + (rhs.e2 * lhs.e3);
}
inline void join(AbsExt4_3 &out, const AbsExt4_2 &lhs, const AbsExt4_1 &rhs) {
out.e012 = (lhs.e01 * rhs.e2) + (lhs.e02 * rhs.e1) + (lhs.e12 *rhs.e0);
out.e013 = (lhs.e01 * rhs.e3) + (lhs.e03 * rhs.e1) + (lhs.e13 *rhs.e0);
out.e023 = (lhs.e02 * rhs.e3) + (lhs.e03 * rhs.e2) + (lhs.e23 *rhs.e0);
out.e123 = (lhs.e12 * rhs.e3) + (lhs.e13 * rhs.e2) + (lhs.e23 *rhs.e1);
}
inline void join(AbsExt4_3 &out, const AbsExt4_1 &lhs, const AbsExt4_2 &rhs) {
join(out, rhs, lhs);
}
// ************************
// A meet takes a j-vector and a k-vector and returns a (j+k-4)-vector
inline void meet(AbsExt4_2 &out, const AbsExt4_3 &lhs, const AbsExt4_3 &rhs) {
AbsExt4_2 out_dual;
AbsExt4_1 lhs_dual;
AbsExt4_1 rhs_dual;
dual(lhs_dual, lhs);
dual(rhs_dual, rhs);
join(out_dual, lhs_dual, rhs_dual);
revdual(out, out_dual);
}
inline void meet(AbsExt4_1 &out, const AbsExt4_2 &lhs, const AbsExt4_3 &rhs) {
AbsExt4_3 out_dual;
AbsExt4_2 lhs_dual;
AbsExt4_1 rhs_dual;
dual(lhs_dual, lhs);
dual(rhs_dual, rhs);
join(out_dual, lhs_dual, rhs_dual);
revdual(out, out_dual);
}
inline void meet(AbsExt4_1 &out, const AbsExt4_3 &lhs, const AbsExt4_2 &rhs) {
AbsExt4_3 out_dual;
AbsExt4_1 lhs_dual;
AbsExt4_2 rhs_dual;
dual(lhs_dual, lhs);
dual(rhs_dual, rhs);
join(out_dual, lhs_dual, rhs_dual);
revdual(out, out_dual);
}
// ************************
// An inner product takes two k-vectors and produces a single number
inline double inner(const AbsExt4_1 &lhs, const AbsExt4_1 &rhs) {
double acc = 0.0;
for (int i = 0; i<4; i++)
acc += lhs.v[i] * rhs.v[i];
return acc;
}
inline double inner(const AbsExt4_2 &lhs, const AbsExt4_2 &rhs) {
double acc = 0.0;
for (int i = 0; i<6; i++)
acc += lhs.v[i] * rhs.v[i];
return acc;
}
inline double inner(const AbsExt4_3 &lhs, const AbsExt4_3 &rhs) {
double acc = 0.0;
for (int i = 0; i<4; i++)
acc += lhs.v[i] * rhs.v[i];
return acc;
}
} // end namespace AbsExt4