Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
ComplexDouble.h
Go to the documentation of this file.
1
32#pragma once
33
35
36namespace ogdf {
37
38namespace sse {
39
41#ifdef OGDF_FME_KERNEL_USE_SSE
42class ComplexDouble {
43public:
45
46 inline ComplexDouble() { reg = _mm_setzero_pd(); }
47
48 inline ComplexDouble(const ComplexDouble& other) { reg = other.reg; }
49
50 inline ComplexDouble(double x) { reg = _mm_setr_pd((x), (0)); }
51
52 inline ComplexDouble(double x, double y) { reg = _mm_setr_pd((x), (y)); }
53
54 inline ComplexDouble(const double* ptr) { reg = _mm_load_pd(ptr); }
55
56 inline ComplexDouble(__m128d r) : reg(r) { }
57
58 inline ComplexDouble(float x, float y) { reg = _mm_cvtps_pd(_mm_setr_ps((x), (y), 0, 0)); }
59
62
63 inline ComplexDouble operator+(const ComplexDouble& other) const {
64 return ComplexDouble(_mm_add_pd(reg, other.reg));
65 }
66
67 inline ComplexDouble operator-(const ComplexDouble& other) const {
68 return ComplexDouble(_mm_sub_pd(reg, other.reg));
69 }
70
71 inline ComplexDouble operator-(void) const {
73 }
74
75 inline ComplexDouble operator*(const ComplexDouble& other) const {
76 // ---------------------------------
77 // | a0*b0 - a1*b1 | a0*b1 + a1*b0 |
78 // ---------------------------------
79 // bt = | b1 | b0 |
81 // left = | a0*b0 | a1*b1 |
82 __m128d left = _mm_mul_pd(reg, other.reg);
83 // right = | a0*b1 | a1*b0 |
84 __m128d right = _mm_mul_pd(reg, b_t);
85 // left = | a0*b0 | -a1*b1 |
86 left = _mm_mul_pd(left, _mm_setr_pd(1.0, -1.0));
87 // left = | a0*b0 + (-a1*b1) | a0*b1 + a1*b0 |
88 return ComplexDouble(_mm_hadd_pd(left, right));
89 }
90
91 inline ComplexDouble operator/(const ComplexDouble& other) const {
92 // 1/(length(other)^2 * this * other.conj;
93 // bt = | b0 | -b1 |
94 __m128d conj_reg = _mm_mul_pd(other.reg, _mm_setr_pd(1.0, -1.0));
95 // bt = | b1 | b0 |
97 // left = | a0*b0 | a1*b1 |
99 // right = | a0*b1 | a1*b0 |
100 __m128d right = _mm_mul_pd(reg, b_t);
101 // left = | a0*b0 | -a1*b1 |
102 left = _mm_mul_pd(left, _mm_setr_pd(1.0, -1.0));
103 // left = | a0*b0 + (-a1*b1) | a0*b1 + a1*b0 |
104 __m128d product = _mm_hadd_pd(left, right);
105 // product = reg*other.reg.conj
106 // ell = b0*b0 | b1*b1
108 // ell = b0*b0 + b1*b1 | b0*b0 + b1*b1
110 // ell = length^2 | length^2
112 }
113
114 inline ComplexDouble operator*(double scalar) const {
116 }
117
118 inline ComplexDouble operator/(double scalar) const {
119 //double rcp = 1.0/scalar;
121 }
122
123 inline ComplexDouble operator*(unsigned int scalar) const {
124 return ComplexDouble(_mm_mul_pd(reg, _mm_setr_pd((double)scalar, (double)scalar)));
125 }
126
127 inline void operator+=(const ComplexDouble& other) { reg = _mm_add_pd(reg, other.reg); }
128
129 inline void operator-=(const ComplexDouble& other) { reg = _mm_sub_pd(reg, other.reg); }
130
131 inline void operator*=(const ComplexDouble& other) {
132 // bt = | b1 | b0 |
134 // left = | a0*b0 | a1*b1 |
135 __m128d left = _mm_mul_pd(reg, other.reg);
136 // right = | a0*b1 | a1*b0 |
137 __m128d right = _mm_mul_pd(reg, b_t);
138 // left = | a0*b0 | -a1*b1 |
139 left = _mm_mul_pd(left, _mm_setr_pd(1.0, -1.0));
140 // left = | a0*b0 + (-a1*b1) | a0*b1 + a1*b0 |
141 reg = _mm_hadd_pd(left, right);
142 }
143
144 inline void operator*=(double scalar) {
145 // (real*scalar, imag*scalar)
147 }
148
149 inline void operator/=(const ComplexDouble& other) {
150 // 1/(length(other)^2 * this * other.conj;
151 // bt = | b0 | -b1 |
152 __m128d conj_reg = _mm_mul_pd(other.reg, _mm_setr_pd(1.0, -1.0));
153 // bt = | b1 | b0 |
155 // left = | a0*b0 | a1*b1 |
157 // right = | a0*b1 | a1*b0 |
158 __m128d right = _mm_mul_pd(reg, b_t);
159 // left = | a0*b0 | -a1*b1 |
160 left = _mm_mul_pd(left, _mm_setr_pd(1.0, -1.0));
161 // left = | a0*b0 + (-a1*b1) | a0*b1 + a1*b0 |
162 __m128d product = _mm_hadd_pd(left, right);
163 // ell = b0*b0 | b1*b1
165 // ell = b0*b0 + b1*b1 | b0*b0 + b1*b1
167 // ell = length^2 | length^2
169 }
170
174
175 inline double length() const {
176 // sqrt(real*real + imag*imag)
177 double res;
180 r = _mm_sqrt_sd(r, r);
181 _mm_store_sd(&res, r);
182 return res;
183 }
184
185 inline ComplexDouble conj() const {
186 // (real, -imag)
187 return ComplexDouble(_mm_mul_pd(reg, _mm_setr_pd(1.0, -1.0)));
188 }
189
193
194 inline void operator=(const ComplexDouble& other) { reg = other.reg; }
195
197 inline void operator=(double* ptr) { reg = _mm_load_pd(ptr); }
198
202
204 inline void load(const double* ptr) { reg = _mm_load_pd(ptr); }
205
207 inline void load_unaligned(const double* ptr) { reg = _mm_loadu_pd(ptr); }
208
210 inline void store(double* ptr) const { _mm_store_pd(ptr, reg); }
211
213 inline void store_unaligned(double* ptr) const { _mm_storeu_pd(ptr, reg); }
214
216};
217
218#else
220public:
221 double reg[2];
222
223 inline ComplexDouble() {
224 reg[0] = 0.0;
225 reg[1] = 0.0;
226 }
227
229 reg[0] = other.reg[0];
230 reg[1] = other.reg[1];
231 }
232
233 inline ComplexDouble(double x) {
234 reg[0] = x;
235 reg[1] = 0;
236 }
237
238 inline ComplexDouble(double x, double y) {
239 reg[0] = x;
240 reg[1] = y;
241 }
242
243 inline ComplexDouble(double* ptr) {
244 reg[0] = ptr[0];
245 reg[1] = ptr[1];
246 }
247
251 return ComplexDouble(reg[0] + other.reg[0], reg[1] + other.reg[1]);
252 }
253
255 return ComplexDouble(reg[0] - other.reg[0], reg[1] - other.reg[1]);
256 }
257
258 inline ComplexDouble operator-(void) const { return ComplexDouble(-reg[0], -reg[1]); }
259
261 return ComplexDouble(reg[0] * other.reg[0] - reg[1] * other.reg[1],
262 reg[0] * other.reg[1] + reg[1] * other.reg[0]);
263 }
264
266 return (*this) * other.conj() / (other.reg[0] * other.reg[0] + other.reg[1] * other.reg[1]);
267 }
268
269 inline ComplexDouble operator*(double scalar) const {
270 return ComplexDouble(reg[0] * scalar, reg[1] * scalar);
271 }
272
273 inline ComplexDouble operator/(double scalar) const {
274 return ComplexDouble(reg[0] / scalar, reg[1] / scalar);
275 }
276
277 inline ComplexDouble operator*(unsigned int scalar) const {
278 return ComplexDouble(reg[0] * (double)scalar, reg[1] * (double)scalar);
279 }
280
281 inline void operator+=(const ComplexDouble& other) {
282 reg[0] += other.reg[0];
283 reg[1] += other.reg[1];
284 }
285
286 inline void operator-=(const ComplexDouble& other) {
287 reg[0] -= other.reg[0];
288 reg[1] -= other.reg[1];
289 }
290
291 inline void operator*=(const ComplexDouble& other) {
292 double t[2];
293 t[0] = reg[0] * other.reg[0] - reg[1] * other.reg[1];
294 t[1] = reg[0] * other.reg[1] + reg[1] * other.reg[0];
295 reg[0] = t[0];
296 reg[1] = t[1];
297 }
298
299 inline void operator*=(double scalar) {
300 reg[0] *= scalar;
301 reg[1] *= scalar;
302 }
303
304 inline void operator/=(const ComplexDouble& other) {
305 ComplexDouble t = other.conj() / (other.reg[0] * other.reg[0] + other.reg[1] * other.reg[1]);
306 double r[2];
307 r[0] = reg[0] * t.reg[0] - reg[1] * t.reg[1];
308 r[1] = reg[0] * t.reg[1] + reg[1] * t.reg[0];
309 reg[0] = r[0];
310 reg[1] = r[1];
311 }
312
316
317 inline double length() const {
318 // sqrt(real*real + imag*imag)
319 return sqrt(reg[0] * reg[0] + reg[1] * reg[1]);
320 }
321
322 inline ComplexDouble conj() const {
323 // (real, -imag)
324 return ComplexDouble(reg[0], -reg[1]);
325 }
326
330
332 reg[0] = other.reg[0];
333 reg[1] = other.reg[1];
334 return *this;
335 }
336
338 inline ComplexDouble& operator=(double* ptr) {
339 reg[0] = ptr[0];
340 reg[1] = ptr[1];
341 return *this;
342 }
343
347
349 inline void load(const double* ptr) {
350 reg[0] = ptr[0];
351 reg[1] = ptr[1];
352 }
353
355 inline void load_unaligned(const double* ptr) {
356 reg[0] = ptr[0];
357 reg[1] = ptr[1];
358 }
359
361 inline void store(double* ptr) const {
362 ptr[0] = reg[0];
363 ptr[1] = reg[1];
364 }
365
367 inline void store_unaligned(double* ptr) const {
368 ptr[0] = reg[0];
369 ptr[1] = reg[1];
370 }
371
373};
374
375#endif
376}
377
378}
Definition of utility functions for FME layout.
Class to generate instrinsics for complex number arithmetic functions.
void store_unaligned(double *ptr) const
store to unaligned ptr
void operator*=(double scalar)
ComplexDouble operator/(const ComplexDouble &other) const
void load(const double *ptr)
load from 16byte aligned ptr
ComplexDouble(const ComplexDouble &other)
ComplexDouble operator*(unsigned int scalar) const
ComplexDouble operator+(const ComplexDouble &other) const
void operator/=(const ComplexDouble &other)
void operator+=(const ComplexDouble &other)
ComplexDouble conj() const
ComplexDouble & operator=(double *ptr)
load from 16byte aligned ptr
ComplexDouble operator*(double scalar) const
ComplexDouble & operator=(const ComplexDouble &other)
void load_unaligned(const double *ptr)
load from unaligned ptr
ComplexDouble(double x, double y)
ComplexDouble operator-(const ComplexDouble &other) const
ComplexDouble operator/(double scalar) const
void operator*=(const ComplexDouble &other)
void store(double *ptr) const
store to 16byte aligned ptr
void operator-=(const ComplexDouble &other)
ComplexDouble operator-(void) const
ComplexDouble operator*(const ComplexDouble &other) const
int r[]
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.