Eigen  5.0.1-dev+7c7d8473
 
Loading...
Searching...
No Matches
Complex.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2018 Wave Computing, Inc.
5// Written by:
6// Chris Larsen
7// Alexey Frunze (afrunze@wavecomp.com)
8//
9// This Source Code Form is subject to the terms of the Mozilla
10// Public License v. 2.0. If a copy of the MPL was not distributed
11// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
12
13#ifndef EIGEN_COMPLEX_MSA_H
14#define EIGEN_COMPLEX_MSA_H
15
16#include <iostream>
17
18// IWYU pragma: private
19#include "../../InternalHeaderCheck.h"
20
21namespace Eigen {
22
23namespace internal {
24
25//---------- float ----------
26struct Packet2cf {
27 EIGEN_STRONG_INLINE Packet2cf() {}
28 EIGEN_STRONG_INLINE explicit Packet2cf(const std::complex<float>& a, const std::complex<float>& b) {
29 Packet4f t = {std::real(a), std::imag(a), std::real(b), std::imag(b)};
30 v = t;
31 }
32 EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) {}
33 EIGEN_STRONG_INLINE Packet2cf(const Packet2cf& a) : v(a.v) {}
34 EIGEN_STRONG_INLINE Packet2cf& operator=(const Packet2cf& b) {
35 v = b.v;
36 return *this;
37 }
38 EIGEN_STRONG_INLINE Packet2cf conjugate(void) const {
39 return Packet2cf((Packet4f)__builtin_msa_bnegi_d((v2u64)v, 63));
40 }
41 EIGEN_STRONG_INLINE Packet2cf& operator*=(const Packet2cf& b) {
42 Packet4f v1, v2;
43
44 // Get the real values of a | a1_re | a1_re | a2_re | a2_re |
45 v1 = (Packet4f)__builtin_msa_ilvev_w((v4i32)v, (v4i32)v);
46 // Get the imag values of a | a1_im | a1_im | a2_im | a2_im |
47 v2 = (Packet4f)__builtin_msa_ilvod_w((v4i32)v, (v4i32)v);
48 // Multiply the real a with b
49 v1 = pmul(v1, b.v);
50 // Multiply the imag a with b
51 v2 = pmul(v2, b.v);
52 // Conjugate v2
53 v2 = Packet2cf(v2).conjugate().v;
54 // Swap real/imag elements in v2.
55 v2 = (Packet4f)__builtin_msa_shf_w((v4i32)v2, EIGEN_MSA_SHF_I8(1, 0, 3, 2));
56 // Add and return the result
57 v = padd(v1, v2);
58 return *this;
59 }
60 EIGEN_STRONG_INLINE Packet2cf operator*(const Packet2cf& b) const { return Packet2cf(*this) *= b; }
61 EIGEN_STRONG_INLINE Packet2cf& operator+=(const Packet2cf& b) {
62 v = padd(v, b.v);
63 return *this;
64 }
65 EIGEN_STRONG_INLINE Packet2cf operator+(const Packet2cf& b) const { return Packet2cf(*this) += b; }
66 EIGEN_STRONG_INLINE Packet2cf& operator-=(const Packet2cf& b) {
67 v = psub(v, b.v);
68 return *this;
69 }
70 EIGEN_STRONG_INLINE Packet2cf operator-(const Packet2cf& b) const { return Packet2cf(*this) -= b; }
71 EIGEN_STRONG_INLINE Packet2cf operator/(const Packet2cf& b) const { return pdiv_complex(Packet2cf(*this), b); }
72 EIGEN_STRONG_INLINE Packet2cf& operator/=(const Packet2cf& b) {
73 *this = Packet2cf(*this) / b;
74 return *this;
75 }
76 EIGEN_STRONG_INLINE Packet2cf operator-(void) const { return Packet2cf(pnegate(v)); }
77
78 Packet4f v;
79};
80
81inline std::ostream& operator<<(std::ostream& os, const Packet2cf& value) {
82 os << "[ (" << value.v[0] << ", " << value.v[1]
83 << "i),"
84 " ("
85 << value.v[2] << ", " << value.v[3] << "i) ]";
86 return os;
87}
88
89template <>
90struct packet_traits<std::complex<float> > : default_packet_traits {
91 typedef Packet2cf type;
92 typedef Packet2cf half;
93 enum {
94 Vectorizable = 1,
95 AlignedOnScalar = 1,
96 size = 2,
97
98 HasAdd = 1,
99 HasSub = 1,
100 HasMul = 1,
101 HasDiv = 1,
102 HasNegate = 1,
103 HasAbs = 0,
104 HasAbs2 = 0,
105 HasMin = 0,
106 HasMax = 0,
107 HasSetLinear = 0,
108 };
109};
110
111template <>
112struct unpacket_traits<Packet2cf> {
113 typedef std::complex<float> type;
114 enum {
115 size = 2,
116 alignment = Aligned16,
117 vectorizable = true,
118 masked_load_available = false,
119 masked_store_available = false
120 };
121 typedef Packet2cf half;
122};
123
124template <>
125EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from) {
126 EIGEN_MSA_DEBUG;
127
128 float f0 = from.real(), f1 = from.imag();
129 Packet4f v0 = {f0, f0, f0, f0};
130 Packet4f v1 = {f1, f1, f1, f1};
131 return Packet2cf((Packet4f)__builtin_msa_ilvr_w((Packet4i)v1, (Packet4i)v0));
132}
133
134template <>
135EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
136 EIGEN_MSA_DEBUG;
137
138 return a + b;
139}
140
141template <>
142EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
143 EIGEN_MSA_DEBUG;
144
145 return a - b;
146}
147
148template <>
149EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) {
150 EIGEN_MSA_DEBUG;
151
152 return -a;
153}
154
155template <>
156EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) {
157 EIGEN_MSA_DEBUG;
158
159 return a.conjugate();
160}
161
162template <>
163EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
164 EIGEN_MSA_DEBUG;
165
166 return a * b;
167}
168
169template <>
170EIGEN_STRONG_INLINE Packet2cf pand<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
171 EIGEN_MSA_DEBUG;
172
173 return Packet2cf(pand(a.v, b.v));
174}
175
176template <>
177EIGEN_STRONG_INLINE Packet2cf por<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
178 EIGEN_MSA_DEBUG;
179
180 return Packet2cf(por(a.v, b.v));
181}
182
183template <>
184EIGEN_STRONG_INLINE Packet2cf pxor<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
185 EIGEN_MSA_DEBUG;
186
187 return Packet2cf(pxor(a.v, b.v));
188}
189
190template <>
191EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
192 EIGEN_MSA_DEBUG;
193
194 return Packet2cf(pandnot(a.v, b.v));
195}
196
197template <>
198EIGEN_STRONG_INLINE Packet2cf pload<Packet2cf>(const std::complex<float>* from) {
199 EIGEN_MSA_DEBUG;
200
201 EIGEN_DEBUG_ALIGNED_LOAD return Packet2cf(pload<Packet4f>((const float*)from));
202}
203
204template <>
205EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) {
206 EIGEN_MSA_DEBUG;
207
208 EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cf(ploadu<Packet4f>((const float*)from));
209}
210
211template <>
212EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) {
213 EIGEN_MSA_DEBUG;
214
215 return pset1<Packet2cf>(*from);
216}
217
218template <>
219EIGEN_STRONG_INLINE void pstore<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
220 EIGEN_MSA_DEBUG;
221
222 EIGEN_DEBUG_ALIGNED_STORE pstore<float>((float*)to, from.v);
223}
224
225template <>
226EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
227 EIGEN_MSA_DEBUG;
228
229 EIGEN_DEBUG_UNALIGNED_STORE pstoreu<float>((float*)to, from.v);
230}
231
232template <>
233EIGEN_DEVICE_FUNC inline Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from,
234 Index stride) {
235 EIGEN_MSA_DEBUG;
236
237 return Packet2cf(from[0 * stride], from[1 * stride]);
238}
239
240template <>
241EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to, const Packet2cf& from,
242 Index stride) {
243 EIGEN_MSA_DEBUG;
244
245 *to = std::complex<float>(from.v[0], from.v[1]);
246 to += stride;
247 *to = std::complex<float>(from.v[2], from.v[3]);
248}
249
250template <>
251EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float>* addr) {
252 EIGEN_MSA_DEBUG;
253
254 prefetch(reinterpret_cast<const float*>(addr));
255}
256
257template <>
258EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a) {
259 EIGEN_MSA_DEBUG;
260
261 return std::complex<float>(a.v[0], a.v[1]);
262}
263
264template <>
265EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a) {
266 EIGEN_MSA_DEBUG;
267
268 return Packet2cf((Packet4f)__builtin_msa_shf_w((v4i32)a.v, EIGEN_MSA_SHF_I8(2, 3, 0, 1)));
269}
270
271template <>
272EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& a) {
273 EIGEN_MSA_DEBUG;
274
275 return Packet2cf((Packet4f)__builtin_msa_shf_w((v4i32)a.v, EIGEN_MSA_SHF_I8(1, 0, 3, 2)));
276}
277
278template <>
279EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a) {
280 EIGEN_MSA_DEBUG;
281
282 Packet4f value = (Packet4f)preverse((Packet2d)a.v);
283 value += a.v;
284 return std::complex<float>(value[0], value[1]);
285}
286
287template <>
288EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a) {
289 EIGEN_MSA_DEBUG;
290
291 return std::complex<float>((a.v[0] * a.v[2]) - (a.v[1] * a.v[3]), (a.v[0] * a.v[3]) + (a.v[1] * a.v[2]));
292}
293
294EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf, Packet4f)
295
296template <>
297EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
298 EIGEN_MSA_DEBUG;
299
300 return a / b;
301}
302
303inline std::ostream& operator<<(std::ostream& os, const PacketBlock<Packet2cf, 2>& value) {
304 os << "[ " << value.packet[0] << ", " << std::endl << " " << value.packet[1] << " ]";
305 return os;
306}
307
308EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet2cf, 2>& kernel) {
309 EIGEN_MSA_DEBUG;
310
311 Packet4f tmp = (Packet4f)__builtin_msa_ilvl_d((v2i64)kernel.packet[1].v, (v2i64)kernel.packet[0].v);
312 kernel.packet[0].v = (Packet4f)__builtin_msa_ilvr_d((v2i64)kernel.packet[1].v, (v2i64)kernel.packet[0].v);
313 kernel.packet[1].v = tmp;
314}
315
316//---------- double ----------
317
318struct Packet1cd {
319 EIGEN_STRONG_INLINE Packet1cd() {}
320 EIGEN_STRONG_INLINE explicit Packet1cd(const std::complex<double>& a) {
321 v[0] = std::real(a);
322 v[1] = std::imag(a);
323 }
324 EIGEN_STRONG_INLINE explicit Packet1cd(const Packet2d& a) : v(a) {}
325 EIGEN_STRONG_INLINE Packet1cd(const Packet1cd& a) : v(a.v) {}
326 EIGEN_STRONG_INLINE Packet1cd& operator=(const Packet1cd& b) {
327 v = b.v;
328 return *this;
329 }
330 EIGEN_STRONG_INLINE Packet1cd conjugate(void) const {
331 static const v2u64 p2ul_CONJ_XOR = {0x0, 0x8000000000000000};
332 return (Packet1cd)pxor(v, (Packet2d)p2ul_CONJ_XOR);
333 }
334 EIGEN_STRONG_INLINE Packet1cd& operator*=(const Packet1cd& b) {
335 Packet2d v1, v2;
336
337 // Get the real values of a | a1_re | a1_re
338 v1 = (Packet2d)__builtin_msa_ilvev_d((v2i64)v, (v2i64)v);
339 // Get the imag values of a | a1_im | a1_im
340 v2 = (Packet2d)__builtin_msa_ilvod_d((v2i64)v, (v2i64)v);
341 // Multiply the real a with b
342 v1 = pmul(v1, b.v);
343 // Multiply the imag a with b
344 v2 = pmul(v2, b.v);
345 // Conjugate v2
346 v2 = Packet1cd(v2).conjugate().v;
347 // Swap real/imag elements in v2.
348 v2 = (Packet2d)__builtin_msa_shf_w((v4i32)v2, EIGEN_MSA_SHF_I8(2, 3, 0, 1));
349 // Add and return the result
350 v = padd(v1, v2);
351 return *this;
352 }
353 EIGEN_STRONG_INLINE Packet1cd operator*(const Packet1cd& b) const { return Packet1cd(*this) *= b; }
354 EIGEN_STRONG_INLINE Packet1cd& operator+=(const Packet1cd& b) {
355 v = padd(v, b.v);
356 return *this;
357 }
358 EIGEN_STRONG_INLINE Packet1cd operator+(const Packet1cd& b) const { return Packet1cd(*this) += b; }
359 EIGEN_STRONG_INLINE Packet1cd& operator-=(const Packet1cd& b) {
360 v = psub(v, b.v);
361 return *this;
362 }
363 EIGEN_STRONG_INLINE Packet1cd operator-(const Packet1cd& b) const { return Packet1cd(*this) -= b; }
364 EIGEN_STRONG_INLINE Packet1cd& operator/=(const Packet1cd& b) {
365 *this *= b.conjugate();
366 Packet2d s = pmul<Packet2d>(b.v, b.v);
367 s = padd(s, preverse<Packet2d>(s));
368 v = pdiv(v, s);
369 return *this;
370 }
371 EIGEN_STRONG_INLINE Packet1cd operator/(const Packet1cd& b) const { return Packet1cd(*this) /= b; }
372 EIGEN_STRONG_INLINE Packet1cd operator-(void) const { return Packet1cd(pnegate(v)); }
373
374 Packet2d v;
375};
376
377inline std::ostream& operator<<(std::ostream& os, const Packet1cd& value) {
378 os << "[ (" << value.v[0] << ", " << value.v[1] << "i) ]";
379 return os;
380}
381
382template <>
383struct packet_traits<std::complex<double> > : default_packet_traits {
384 typedef Packet1cd type;
385 typedef Packet1cd half;
386 enum {
387 Vectorizable = 1,
388 AlignedOnScalar = 0,
389 size = 1,
390
391 HasAdd = 1,
392 HasSub = 1,
393 HasMul = 1,
394 HasDiv = 1,
395 HasNegate = 1,
396 HasAbs = 0,
397 HasAbs2 = 0,
398 HasMin = 0,
399 HasMax = 0,
400 HasSetLinear = 0
401 };
402};
403
404template <>
405struct unpacket_traits<Packet1cd> {
406 typedef std::complex<double> type;
407 enum {
408 size = 1,
409 alignment = Aligned16,
410 vectorizable = true,
411 masked_load_available = false,
412 masked_store_available = false
413 };
414 typedef Packet1cd half;
415};
416
417template <>
418EIGEN_STRONG_INLINE Packet1cd pload<Packet1cd>(const std::complex<double>* from) {
419 EIGEN_MSA_DEBUG;
420
421 EIGEN_DEBUG_ALIGNED_LOAD return Packet1cd(pload<Packet2d>((const double*)from));
422}
423
424template <>
425EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from) {
426 EIGEN_MSA_DEBUG;
427
428 EIGEN_DEBUG_UNALIGNED_LOAD return Packet1cd(ploadu<Packet2d>((const double*)from));
429}
430
431template <>
432EIGEN_STRONG_INLINE Packet1cd pset1<Packet1cd>(const std::complex<double>& from) {
433 EIGEN_MSA_DEBUG;
434
435 return Packet1cd(from);
436}
437
438template <>
439EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
440 EIGEN_MSA_DEBUG;
441
442 return a + b;
443}
444
445template <>
446EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
447 EIGEN_MSA_DEBUG;
448
449 return a - b;
450}
451
452template <>
453EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) {
454 EIGEN_MSA_DEBUG;
455
456 return -a;
457}
458
459template <>
460EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) {
461 EIGEN_MSA_DEBUG;
462
463 return a.conjugate();
464}
465
466template <>
467EIGEN_STRONG_INLINE Packet1cd pmul<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
468 EIGEN_MSA_DEBUG;
469
470 return a * b;
471}
472
473template <>
474EIGEN_STRONG_INLINE Packet1cd pand<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
475 EIGEN_MSA_DEBUG;
476
477 return Packet1cd(pand(a.v, b.v));
478}
479
480template <>
481EIGEN_STRONG_INLINE Packet1cd por<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
482 EIGEN_MSA_DEBUG;
483
484 return Packet1cd(por(a.v, b.v));
485}
486
487template <>
488EIGEN_STRONG_INLINE Packet1cd pxor<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
489 EIGEN_MSA_DEBUG;
490
491 return Packet1cd(pxor(a.v, b.v));
492}
493
494template <>
495EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
496 EIGEN_MSA_DEBUG;
497
498 return Packet1cd(pandnot(a.v, b.v));
499}
500
501template <>
502EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) {
503 EIGEN_MSA_DEBUG;
504
505 return pset1<Packet1cd>(*from);
506}
507
508template <>
509EIGEN_STRONG_INLINE void pstore<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
510 EIGEN_MSA_DEBUG;
511
512 EIGEN_DEBUG_ALIGNED_STORE pstore<double>((double*)to, from.v);
513}
514
515template <>
516EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
517 EIGEN_MSA_DEBUG;
518
519 EIGEN_DEBUG_UNALIGNED_STORE pstoreu<double>((double*)to, from.v);
520}
521
522template <>
523EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double>* addr) {
524 EIGEN_MSA_DEBUG;
525
526 prefetch(reinterpret_cast<const double*>(addr));
527}
528
529template <>
530EIGEN_DEVICE_FUNC inline Packet1cd pgather<std::complex<double>, Packet1cd>(const std::complex<double>* from,
531 Index stride __attribute__((unused))) {
532 EIGEN_MSA_DEBUG;
533
534 Packet1cd res;
535 res.v[0] = std::real(from[0]);
536 res.v[1] = std::imag(from[0]);
537 return res;
538}
539
540template <>
541EIGEN_DEVICE_FUNC inline void pscatter<std::complex<double>, Packet1cd>(std::complex<double>* to, const Packet1cd& from,
542 Index stride __attribute__((unused))) {
543 EIGEN_MSA_DEBUG;
544
545 pstore(to, from);
546}
547
548template <>
549EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet1cd>(const Packet1cd& a) {
550 EIGEN_MSA_DEBUG;
551
552 return std::complex<double>(a.v[0], a.v[1]);
553}
554
555template <>
556EIGEN_STRONG_INLINE Packet1cd preverse(const Packet1cd& a) {
557 EIGEN_MSA_DEBUG;
558
559 return a;
560}
561
562template <>
563EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Packet1cd& a) {
564 EIGEN_MSA_DEBUG;
565
566 return pfirst(a);
567}
568
569template <>
570EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) {
571 EIGEN_MSA_DEBUG;
572
573 return pfirst(a);
574}
575
576EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd, Packet2d)
577
578template <>
579EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
580 EIGEN_MSA_DEBUG;
581
582 return a / b;
583}
584
585EIGEN_STRONG_INLINE Packet1cd pcplxflip /*<Packet1cd>*/ (const Packet1cd& x) {
586 EIGEN_MSA_DEBUG;
587
588 return Packet1cd(preverse(Packet2d(x.v)));
589}
590
591inline std::ostream& operator<<(std::ostream& os, const PacketBlock<Packet1cd, 2>& value) {
592 os << "[ " << value.packet[0] << ", " << std::endl << " " << value.packet[1] << " ]";
593 return os;
594}
595
596EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet1cd, 2>& kernel) {
597 EIGEN_MSA_DEBUG;
598
599 Packet2d v1, v2;
600
601 v1 = (Packet2d)__builtin_msa_ilvev_d((v2i64)kernel.packet[0].v, (v2i64)kernel.packet[1].v);
602 // Get the imag values of a
603 v2 = (Packet2d)__builtin_msa_ilvod_d((v2i64)kernel.packet[0].v, (v2i64)kernel.packet[1].v);
604
605 kernel.packet[0].v = v1;
606 kernel.packet[1].v = v2;
607}
608
609} // end namespace internal
610
611} // end namespace Eigen
612
613#endif // EIGEN_COMPLEX_MSA_H
@ Aligned16
Definition Constants.h:237
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82