Eigen  5.0.1
 
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) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2010-2016 Konstantinos Margaritis <markos@freevec.org>
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_COMPLEX32_ALTIVEC_H
13#define EIGEN_COMPLEX32_ALTIVEC_H
14
15// IWYU pragma: private
16#include "../../InternalHeaderCheck.h"
17
18namespace Eigen {
19
20namespace internal {
21
22EIGEN_GCC_FAST_MATH_COMPLEX_VECTORIZE_WORKAROUND_PUSH
23
24inline Packet4ui p4ui_CONJ_XOR() {
25 return vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); //{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
26}
27#ifdef EIGEN_VECTORIZE_VSX
28#if defined(_BIG_ENDIAN)
29inline Packet2ul p2ul_CONJ_XOR1() {
30 return (Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO,
31 8); //{ 0x8000000000000000, 0x0000000000000000 };
32}
33inline Packet2ul p2ul_CONJ_XOR2() {
34 return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
35 8); //{ 0x8000000000000000, 0x0000000000000000 };
36}
37#else
38inline Packet2ul p2ul_CONJ_XOR1() {
39 return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
40 8); //{ 0x8000000000000000, 0x0000000000000000 };
41}
42inline Packet2ul p2ul_CONJ_XOR2() {
43 return (Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO,
44 8); //{ 0x8000000000000000, 0x0000000000000000 };
45}
46#endif
47#endif
48
49//---------- float ----------
50struct Packet2cf {
51 EIGEN_STRONG_INLINE explicit Packet2cf() {}
52 EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) {}
53
54 EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) {
55 Packet4f v1, v2;
56
57 // Permute and multiply the real parts of a and b
58 v1 = vec_perm(a.v, a.v, p16uc_PSET32_WODD);
59 // Get the imaginary parts of a
60 v2 = vec_perm(a.v, a.v, p16uc_PSET32_WEVEN);
61 // multiply a_re * b
62 v1 = vec_madd(v1, b.v, p4f_ZERO);
63 // multiply a_im * b and get the conjugate result
64 v2 = vec_madd(v2, b.v, p4f_ZERO);
65 v2 = reinterpret_cast<Packet4f>(pxor(v2, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR())));
66 // permute back to a proper order
67 v2 = vec_perm(v2, v2, p16uc_COMPLEX32_REV);
68
69 return Packet2cf(padd<Packet4f>(v1, v2));
70 }
71
72 EIGEN_STRONG_INLINE Packet2cf& operator*=(const Packet2cf& b) {
73 v = pmul(Packet2cf(*this), b).v;
74 return *this;
75 }
76 EIGEN_STRONG_INLINE Packet2cf operator*(const Packet2cf& b) const { return Packet2cf(*this) *= b; }
77
78 EIGEN_STRONG_INLINE Packet2cf& operator+=(const Packet2cf& b) {
79 v = padd(v, b.v);
80 return *this;
81 }
82 EIGEN_STRONG_INLINE Packet2cf operator+(const Packet2cf& b) const { return Packet2cf(*this) += b; }
83 EIGEN_STRONG_INLINE Packet2cf& operator-=(const Packet2cf& b) {
84 v = psub(v, b.v);
85 return *this;
86 }
87 EIGEN_STRONG_INLINE Packet2cf operator-(const Packet2cf& b) const { return Packet2cf(*this) -= b; }
88 EIGEN_STRONG_INLINE Packet2cf operator-(void) const { return Packet2cf(-v); }
89
90 Packet4f v;
91};
92
93template <>
94struct packet_traits<std::complex<float> > : default_packet_traits {
95 typedef Packet2cf type;
96 typedef Packet2cf half;
97 typedef Packet4f as_real;
98 enum {
99 Vectorizable = 1,
100 AlignedOnScalar = 1,
101 size = 2,
102
103 HasAdd = 1,
104 HasSub = 1,
105 HasMul = 1,
106 HasDiv = 1,
107 HasNegate = 1,
108 HasAbs = 0,
109 HasAbs2 = 0,
110 HasMin = 0,
111 HasMax = 0,
112 HasSqrt = 1,
113 HasLog = 1,
114 HasExp = 1,
115 HasSetLinear = 0
116 };
117};
118
119template <>
120struct unpacket_traits<Packet2cf> {
121 typedef std::complex<float> type;
122 enum {
123 size = 2,
124 alignment = Aligned16,
125 vectorizable = true,
126 masked_load_available = false,
127 masked_store_available = false
128 };
129 typedef Packet2cf half;
130 typedef Packet4f as_real;
131};
132
133template <>
134EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from) {
135 Packet2cf res;
136#ifdef EIGEN_VECTORIZE_VSX
137 // Load a single std::complex<float> from memory and duplicate
138 //
139 // Using pload would read past the end of the reference in this case
140 // Using vec_xl_len + vec_splat, generates poor assembly
141 __asm__("lxvdsx %x0,%y1" : "=wa"(res.v) : "Z"(from));
142#else
143 if ((std::ptrdiff_t(&from) % 16) == 0)
144 res.v = pload<Packet4f>((const float*)&from);
145 else
146 res.v = ploadu<Packet4f>((const float*)&from);
147 res.v = vec_perm(res.v, res.v, p16uc_PSET64_HI);
148#endif
149 return res;
150}
151
152template <>
153EIGEN_STRONG_INLINE Packet2cf pload<Packet2cf>(const std::complex<float>* from) {
154 return Packet2cf(pload<Packet4f>((const float*)from));
155}
156template <>
157EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) {
158 return Packet2cf(ploadu<Packet4f>((const float*)from));
159}
160template <>
161EIGEN_ALWAYS_INLINE Packet2cf pload_partial<Packet2cf>(const std::complex<float>* from, const Index n,
162 const Index offset) {
163 return Packet2cf(pload_partial<Packet4f>((const float*)from, n * 2, offset * 2));
164}
165template <>
166EIGEN_ALWAYS_INLINE Packet2cf ploadu_partial<Packet2cf>(const std::complex<float>* from, const Index n,
167 const Index offset) {
168 return Packet2cf(ploadu_partial<Packet4f>((const float*)from, n * 2, offset * 2));
169}
170template <>
171EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) {
172 return pset1<Packet2cf>(*from);
173}
174
175template <>
176EIGEN_STRONG_INLINE void pstore<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
177 pstore((float*)to, from.v);
178}
179template <>
180EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
181 pstoreu((float*)to, from.v);
182}
183template <>
184EIGEN_ALWAYS_INLINE void pstore_partial<std::complex<float> >(std::complex<float>* to, const Packet2cf& from,
185 const Index n, const Index offset) {
186 pstore_partial((float*)to, from.v, n * 2, offset * 2);
187}
188template <>
189EIGEN_ALWAYS_INLINE void pstoreu_partial<std::complex<float> >(std::complex<float>* to, const Packet2cf& from,
190 const Index n, const Index offset) {
191 pstoreu_partial((float*)to, from.v, n * 2, offset * 2);
192}
193
194EIGEN_STRONG_INLINE Packet2cf pload2(const std::complex<float>& from0, const std::complex<float>& from1) {
195 Packet4f res0, res1;
196#ifdef EIGEN_VECTORIZE_VSX
197 // Load two std::complex<float> from memory and combine
198 __asm__("lxsdx %x0,%y1" : "=wa"(res0) : "Z"(from0));
199 __asm__("lxsdx %x0,%y1" : "=wa"(res1) : "Z"(from1));
200#ifdef _BIG_ENDIAN
201 __asm__("xxpermdi %x0, %x1, %x2, 0" : "=wa"(res0) : "wa"(res0), "wa"(res1));
202#else
203 __asm__("xxpermdi %x0, %x2, %x1, 0" : "=wa"(res0) : "wa"(res0), "wa"(res1));
204#endif
205#else
206 *reinterpret_cast<std::complex<float>*>(&res0) = from0;
207 *reinterpret_cast<std::complex<float>*>(&res1) = from1;
208 res0 = vec_perm(res0, res1, p16uc_TRANSPOSE64_HI);
209#endif
210 return Packet2cf(res0);
211}
212
213template <>
214EIGEN_ALWAYS_INLINE Packet2cf pload_ignore<Packet2cf>(const std::complex<float>* from) {
215 Packet2cf res;
216 res.v = pload_ignore<Packet4f>(reinterpret_cast<const float*>(from));
217 return res;
218}
219
220template <typename Scalar, typename Packet>
221EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pgather_complex_size2(const Scalar* from, Index stride,
222 const Index n = 2) {
223 eigen_internal_assert(n <= unpacket_traits<Packet>::size && "number of elements will gather past end of packet");
224 EIGEN_ALIGN16 Scalar af[2];
225 for (Index i = 0; i < n; i++) {
226 af[i] = from[i * stride];
227 }
228 return pload_ignore<Packet>(af);
229}
230template <>
231EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from,
232 Index stride) {
233 return pgather_complex_size2<std::complex<float>, Packet2cf>(from, stride);
234}
235template <>
236EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet2cf
237pgather_partial<std::complex<float>, Packet2cf>(const std::complex<float>* from, Index stride, const Index n) {
238 return pgather_complex_size2<std::complex<float>, Packet2cf>(from, stride, n);
239}
240template <typename Scalar, typename Packet>
241EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter_complex_size2(Scalar* to, const Packet& from, Index stride,
242 const Index n = 2) {
243 eigen_internal_assert(n <= unpacket_traits<Packet>::size && "number of elements will scatter past end of packet");
244 EIGEN_ALIGN16 Scalar af[2];
245 pstore<Scalar>((Scalar*)af, from);
246 for (Index i = 0; i < n; i++) {
247 to[i * stride] = af[i];
248 }
249}
250template <>
251EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to,
252 const Packet2cf& from,
253 Index stride) {
254 pscatter_complex_size2<std::complex<float>, Packet2cf>(to, from, stride);
255}
256template <>
257EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter_partial<std::complex<float>, Packet2cf>(std::complex<float>* to,
258 const Packet2cf& from,
259 Index stride,
260 const Index n) {
261 pscatter_complex_size2<std::complex<float>, Packet2cf>(to, from, stride, n);
262}
263
264template <>
265EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
266 return Packet2cf(a.v + b.v);
267}
268template <>
269EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
270 return Packet2cf(a.v - b.v);
271}
272template <>
273EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) {
274 return Packet2cf(pnegate(a.v));
275}
276template <>
277EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) {
278 return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR())));
279}
280
281template <>
282EIGEN_STRONG_INLINE Packet2cf pand<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
283 return Packet2cf(pand<Packet4f>(a.v, b.v));
284}
285template <>
286EIGEN_STRONG_INLINE Packet2cf por<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
287 return Packet2cf(por<Packet4f>(a.v, b.v));
288}
289template <>
290EIGEN_STRONG_INLINE Packet2cf pxor<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
291 return Packet2cf(pxor<Packet4f>(a.v, b.v));
292}
293template <>
294EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
295 return Packet2cf(pandnot<Packet4f>(a.v, b.v));
296}
297
298template <>
299EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float>* addr) {
300 EIGEN_PPC_PREFETCH(addr);
301}
302
303template <>
304EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a) {
305 EIGEN_ALIGN16 std::complex<float> res[2];
306 pstore((float*)&res, a.v);
307
308 return res[0];
309}
310
311template <>
312EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a) {
313 Packet4f rev_a;
314 rev_a = vec_sld(a.v, a.v, 8);
315 return Packet2cf(rev_a);
316}
317
318template <>
319EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a) {
320 Packet4f b;
321 b = vec_sld(a.v, a.v, 8);
322 b = padd<Packet4f>(a.v, b);
323 return pfirst<Packet2cf>(Packet2cf(b));
324}
325
326template <>
327EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a) {
328 Packet4f b;
329 Packet2cf prod;
330 b = vec_sld(a.v, a.v, 8);
331 prod = pmul<Packet2cf>(a, Packet2cf(b));
332
333 return pfirst<Packet2cf>(prod);
334}
335
336EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf, Packet4f)
337
338template <>
339EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
340 return pdiv_complex(a, b);
341}
342
343template <>
344EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x) {
345 return Packet2cf(vec_perm(x.v, x.v, p16uc_COMPLEX32_REV));
346}
347
348EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet2cf, 2>& kernel) {
349#ifdef EIGEN_VECTORIZE_VSX
350 Packet4f tmp = reinterpret_cast<Packet4f>(
351 vec_mergeh(reinterpret_cast<Packet2d>(kernel.packet[0].v), reinterpret_cast<Packet2d>(kernel.packet[1].v)));
352 kernel.packet[1].v = reinterpret_cast<Packet4f>(
353 vec_mergel(reinterpret_cast<Packet2d>(kernel.packet[0].v), reinterpret_cast<Packet2d>(kernel.packet[1].v)));
354#else
355 Packet4f tmp = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_HI);
356 kernel.packet[1].v = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_LO);
357#endif
358 kernel.packet[0].v = tmp;
359}
360
361template <>
362EIGEN_STRONG_INLINE Packet2cf pcmp_eq(const Packet2cf& a, const Packet2cf& b) {
363 Packet4f eq = reinterpret_cast<Packet4f>(vec_cmpeq(a.v, b.v));
364 return Packet2cf(vec_and(eq, vec_perm(eq, eq, p16uc_COMPLEX32_REV)));
365}
366
367EIGEN_INSTANTIATE_COMPLEX_MATH_FUNCS(Packet2cf)
368
369//---------- double ----------
370#ifdef EIGEN_VECTORIZE_VSX
371struct Packet1cd {
372 EIGEN_STRONG_INLINE Packet1cd() {}
373 EIGEN_STRONG_INLINE explicit Packet1cd(const Packet2d& a) : v(a) {}
374
375 EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) {
376 Packet2d a_re, a_im, v1, v2;
377
378 // Permute and multiply the real parts of a and b
379 a_re = vec_perm(a.v, a.v, p16uc_PSET64_HI);
380 // Get the imaginary parts of a
381 a_im = vec_perm(a.v, a.v, p16uc_PSET64_LO);
382 // multiply a_re * b
383 v1 = vec_madd(a_re, b.v, p2d_ZERO);
384 // multiply a_im * b and get the conjugate result
385 v2 = vec_madd(a_im, b.v, p2d_ZERO);
386 v2 = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(v2), reinterpret_cast<Packet4ui>(v2), 8));
387 v2 = pxor(v2, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR1()));
388
389 return Packet1cd(padd<Packet2d>(v1, v2));
390 }
391
392 EIGEN_STRONG_INLINE Packet1cd& operator*=(const Packet1cd& b) {
393 v = pmul(Packet1cd(*this), b).v;
394 return *this;
395 }
396 EIGEN_STRONG_INLINE Packet1cd operator*(const Packet1cd& b) const { return Packet1cd(*this) *= b; }
397
398 EIGEN_STRONG_INLINE Packet1cd& operator+=(const Packet1cd& b) {
399 v = padd(v, b.v);
400 return *this;
401 }
402 EIGEN_STRONG_INLINE Packet1cd operator+(const Packet1cd& b) const { return Packet1cd(*this) += b; }
403 EIGEN_STRONG_INLINE Packet1cd& operator-=(const Packet1cd& b) {
404 v = psub(v, b.v);
405 return *this;
406 }
407 EIGEN_STRONG_INLINE Packet1cd operator-(const Packet1cd& b) const { return Packet1cd(*this) -= b; }
408 EIGEN_STRONG_INLINE Packet1cd operator-(void) const { return Packet1cd(-v); }
409
410 Packet2d v;
411};
412
413template <>
414struct packet_traits<std::complex<double> > : default_packet_traits {
415 typedef Packet1cd type;
416 typedef Packet1cd half;
417 typedef Packet2d as_real;
418 enum {
419 Vectorizable = 1,
420 AlignedOnScalar = 0,
421 size = 1,
422
423 HasAdd = 1,
424 HasSub = 1,
425 HasMul = 1,
426 HasDiv = 1,
427 HasNegate = 1,
428 HasAbs = 0,
429 HasAbs2 = 0,
430 HasMin = 0,
431 HasMax = 0,
432 HasSqrt = 1,
433 HasLog = 1,
434 HasSetLinear = 0
435 };
436};
437
438template <>
439struct unpacket_traits<Packet1cd> {
440 typedef std::complex<double> type;
441 enum {
442 size = 1,
443 alignment = Aligned16,
444 vectorizable = true,
445 masked_load_available = false,
446 masked_store_available = false
447 };
448 typedef Packet1cd half;
449 typedef Packet2d as_real;
450};
451
452template <>
453EIGEN_STRONG_INLINE Packet1cd pload<Packet1cd>(const std::complex<double>* from) {
454 return Packet1cd(pload<Packet2d>((const double*)from));
455}
456template <>
457EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from) {
458 return Packet1cd(ploadu<Packet2d>((const double*)from));
459}
460template <>
461EIGEN_ALWAYS_INLINE Packet1cd pload_partial<Packet1cd>(const std::complex<double>* from, const Index n,
462 const Index offset) {
463 return Packet1cd(pload_partial<Packet2d>((const double*)from, n * 2, offset * 2));
464}
465template <>
466EIGEN_ALWAYS_INLINE Packet1cd ploadu_partial<Packet1cd>(const std::complex<double>* from, const Index n,
467 const Index offset) {
468 return Packet1cd(ploadu_partial<Packet2d>((const double*)from, n * 2, offset * 2));
469}
470template <>
471EIGEN_STRONG_INLINE void pstore<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
472 pstore((double*)to, from.v);
473}
474template <>
475EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
476 pstoreu((double*)to, from.v);
477}
478template <>
479EIGEN_ALWAYS_INLINE void pstore_partial<std::complex<double> >(std::complex<double>* to, const Packet1cd& from,
480 const Index n, const Index offset) {
481 pstore_partial((double*)to, from.v, n * 2, offset * 2);
482}
483template <>
484EIGEN_ALWAYS_INLINE void pstoreu_partial<std::complex<double> >(std::complex<double>* to, const Packet1cd& from,
485 const Index n, const Index offset) {
486 pstoreu_partial((double*)to, from.v, n * 2, offset * 2);
487}
488
489template <>
490EIGEN_STRONG_INLINE Packet1cd
491pset1<Packet1cd>(const std::complex<double>& from) { /* here we really have to use unaligned loads :( */
492 return ploadu<Packet1cd>(&from);
493}
494
495template <>
496EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
497pgather<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index) {
498 return pload<Packet1cd>(from);
499}
500template <>
501EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
502pgather_partial<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index, const Index) {
503 return pload<Packet1cd>(from);
504}
505template <>
506EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter<std::complex<double>, Packet1cd>(std::complex<double>* to,
507 const Packet1cd& from, Index) {
508 pstore<std::complex<double> >(to, from);
509}
510template <>
511EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter_partial<std::complex<double>, Packet1cd>(std::complex<double>* to,
512 const Packet1cd& from,
513 Index, const Index) {
514 pstore<std::complex<double> >(to, from);
515}
516
517template <>
518EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
519 return Packet1cd(a.v + b.v);
520}
521template <>
522EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
523 return Packet1cd(a.v - b.v);
524}
525template <>
526EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) {
527 return Packet1cd(pnegate(Packet2d(a.v)));
528}
529template <>
530EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) {
531 return Packet1cd(pxor(a.v, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR2())));
532}
533
534template <>
535EIGEN_STRONG_INLINE Packet1cd pand<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
536 return Packet1cd(pand(a.v, b.v));
537}
538template <>
539EIGEN_STRONG_INLINE Packet1cd por<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
540 return Packet1cd(por(a.v, b.v));
541}
542template <>
543EIGEN_STRONG_INLINE Packet1cd pxor<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
544 return Packet1cd(pxor(a.v, b.v));
545}
546template <>
547EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
548 return Packet1cd(pandnot(a.v, b.v));
549}
550
551template <>
552EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double>* addr) {
553 EIGEN_PPC_PREFETCH(addr);
554}
555
556template <>
557EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet1cd>(const Packet1cd& a) {
558 EIGEN_ALIGN16 std::complex<double> res[1];
559 pstore<std::complex<double> >(res, a);
560
561 return res[0];
562}
563
564EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd, Packet2d)
565
566template <>
567EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
568 return pdiv_complex(a, b);
569}
570
571EIGEN_STRONG_INLINE Packet1cd pcplxflip /*<Packet1cd>*/ (const Packet1cd& x) {
572 return Packet1cd(preverse(Packet2d(x.v)));
573}
574
575EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet1cd, 2>& kernel) {
576 Packet2d tmp = vec_mergeh(kernel.packet[0].v, kernel.packet[1].v);
577 kernel.packet[1].v = vec_mergel(kernel.packet[0].v, kernel.packet[1].v);
578 kernel.packet[0].v = tmp;
579}
580
581template <>
582EIGEN_STRONG_INLINE Packet1cd pcmp_eq(const Packet1cd& a, const Packet1cd& b) {
583 // Compare real and imaginary parts of a and b to get the mask vector:
584 // [re(a)==re(b), im(a)==im(b)]
585 Packet2d eq = reinterpret_cast<Packet2d>(vec_cmpeq(a.v, b.v));
586 // Swap real/imag elements in the mask in to get:
587 // [im(a)==im(b), re(a)==re(b)]
588 Packet2d eq_swapped =
589 reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(eq), reinterpret_cast<Packet4ui>(eq), 8));
590 // Return re(a)==re(b) & im(a)==im(b) by computing bitwise AND of eq and eq_swapped
591 return Packet1cd(vec_and(eq, eq_swapped));
592}
593
594EIGEN_INSTANTIATE_COMPLEX_MATH_FUNCS_NO_EXP(Packet1cd)
595
596#endif // __VSX__
597
598EIGEN_GCC_FAST_MATH_COMPLEX_VECTORIZE_WORKAROUND_POP
599} // end namespace internal
600
601} // end namespace Eigen
602
603#endif // EIGEN_COMPLEX32_ALTIVEC_H
@ Aligned16
Definition Constants.h:238