Eigen  5.0.1-dev+284dcc12
 
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
11#ifndef EIGEN_COMPLEX32_ALTIVEC_H
12#define EIGEN_COMPLEX32_ALTIVEC_H
13
14// IWYU pragma: private
15#include "../../InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21inline Packet4ui p4ui_CONJ_XOR() {
22 return vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); //{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
23}
24#ifdef EIGEN_VECTORIZE_VSX
25#if defined(_BIG_ENDIAN)
26inline Packet2ul p2ul_CONJ_XOR1() {
27 return (Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO,
28 8); //{ 0x8000000000000000, 0x0000000000000000 };
29}
30inline Packet2ul p2ul_CONJ_XOR2() {
31 return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
32 8); //{ 0x8000000000000000, 0x0000000000000000 };
33}
34#else
35inline Packet2ul p2ul_CONJ_XOR1() {
36 return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
37 8); //{ 0x8000000000000000, 0x0000000000000000 };
38}
39inline Packet2ul p2ul_CONJ_XOR2() {
40 return (Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO,
41 8); //{ 0x8000000000000000, 0x0000000000000000 };
42}
43#endif
44#endif
45
46//---------- float ----------
47struct Packet2cf {
48 EIGEN_STRONG_INLINE explicit Packet2cf() {}
49 EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) {}
50
51 EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) {
52 Packet4f v1, v2;
53
54 // Permute and multiply the real parts of a and b
55 v1 = vec_perm(a.v, a.v, p16uc_PSET32_WODD);
56 // Get the imaginary parts of a
57 v2 = vec_perm(a.v, a.v, p16uc_PSET32_WEVEN);
58 // multiply a_re * b
59 v1 = vec_madd(v1, b.v, p4f_ZERO);
60 // multiply a_im * b and get the conjugate result
61 v2 = vec_madd(v2, b.v, p4f_ZERO);
62 v2 = reinterpret_cast<Packet4f>(pxor(v2, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR())));
63 // permute back to a proper order
64 v2 = vec_perm(v2, v2, p16uc_COMPLEX32_REV);
65
66 return Packet2cf(padd<Packet4f>(v1, v2));
67 }
68
69 EIGEN_STRONG_INLINE Packet2cf& operator*=(const Packet2cf& b) {
70 v = pmul(Packet2cf(*this), b).v;
71 return *this;
72 }
73 EIGEN_STRONG_INLINE Packet2cf operator*(const Packet2cf& b) const { return Packet2cf(*this) *= b; }
74
75 EIGEN_STRONG_INLINE Packet2cf& operator+=(const Packet2cf& b) {
76 v = padd(v, b.v);
77 return *this;
78 }
79 EIGEN_STRONG_INLINE Packet2cf operator+(const Packet2cf& b) const { return Packet2cf(*this) += b; }
80 EIGEN_STRONG_INLINE Packet2cf& operator-=(const Packet2cf& b) {
81 v = psub(v, b.v);
82 return *this;
83 }
84 EIGEN_STRONG_INLINE Packet2cf operator-(const Packet2cf& b) const { return Packet2cf(*this) -= b; }
85 EIGEN_STRONG_INLINE Packet2cf operator-(void) const { return Packet2cf(-v); }
86
87 Packet4f v;
88};
89
90template <>
91struct packet_traits<std::complex<float> > : default_packet_traits {
92 typedef Packet2cf type;
93 typedef Packet2cf half;
94 typedef Packet4f as_real;
95 enum {
96 Vectorizable = 1,
97 AlignedOnScalar = 1,
98 size = 2,
99
100 HasAdd = 1,
101 HasSub = 1,
102 HasMul = 1,
103 HasDiv = 1,
104 HasNegate = 1,
105 HasAbs = 0,
106 HasAbs2 = 0,
107 HasMin = 0,
108 HasMax = 0,
109 HasSqrt = 1,
110 HasLog = 1,
111 HasExp = 1,
112#ifdef EIGEN_VECTORIZE_VSX
113 HasBlend = 1,
114#endif
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
367#ifdef EIGEN_VECTORIZE_VSX
368template <>
369EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, const Packet2cf& thenPacket,
370 const Packet2cf& elsePacket) {
371 Packet2cf result;
372 result.v = reinterpret_cast<Packet4f>(
373 pblend<Packet2d>(ifPacket, reinterpret_cast<Packet2d>(thenPacket.v), reinterpret_cast<Packet2d>(elsePacket.v)));
374 return result;
375}
376#endif
377
378template <>
379EIGEN_STRONG_INLINE Packet2cf psqrt<Packet2cf>(const Packet2cf& a) {
380 return psqrt_complex<Packet2cf>(a);
381}
382
383template <>
384EIGEN_STRONG_INLINE Packet2cf plog<Packet2cf>(const Packet2cf& a) {
385 return plog_complex<Packet2cf>(a);
386}
387
388template <>
389EIGEN_STRONG_INLINE Packet2cf pexp<Packet2cf>(const Packet2cf& a) {
390 return pexp_complex<Packet2cf>(a);
391}
392
393//---------- double ----------
394#ifdef EIGEN_VECTORIZE_VSX
395struct Packet1cd {
396 EIGEN_STRONG_INLINE Packet1cd() {}
397 EIGEN_STRONG_INLINE explicit Packet1cd(const Packet2d& a) : v(a) {}
398
399 EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) {
400 Packet2d a_re, a_im, v1, v2;
401
402 // Permute and multiply the real parts of a and b
403 a_re = vec_perm(a.v, a.v, p16uc_PSET64_HI);
404 // Get the imaginary parts of a
405 a_im = vec_perm(a.v, a.v, p16uc_PSET64_LO);
406 // multiply a_re * b
407 v1 = vec_madd(a_re, b.v, p2d_ZERO);
408 // multiply a_im * b and get the conjugate result
409 v2 = vec_madd(a_im, b.v, p2d_ZERO);
410 v2 = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(v2), reinterpret_cast<Packet4ui>(v2), 8));
411 v2 = pxor(v2, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR1()));
412
413 return Packet1cd(padd<Packet2d>(v1, v2));
414 }
415
416 EIGEN_STRONG_INLINE Packet1cd& operator*=(const Packet1cd& b) {
417 v = pmul(Packet1cd(*this), b).v;
418 return *this;
419 }
420 EIGEN_STRONG_INLINE Packet1cd operator*(const Packet1cd& b) const { return Packet1cd(*this) *= b; }
421
422 EIGEN_STRONG_INLINE Packet1cd& operator+=(const Packet1cd& b) {
423 v = padd(v, b.v);
424 return *this;
425 }
426 EIGEN_STRONG_INLINE Packet1cd operator+(const Packet1cd& b) const { return Packet1cd(*this) += b; }
427 EIGEN_STRONG_INLINE Packet1cd& operator-=(const Packet1cd& b) {
428 v = psub(v, b.v);
429 return *this;
430 }
431 EIGEN_STRONG_INLINE Packet1cd operator-(const Packet1cd& b) const { return Packet1cd(*this) -= b; }
432 EIGEN_STRONG_INLINE Packet1cd operator-(void) const { return Packet1cd(-v); }
433
434 Packet2d v;
435};
436
437template <>
438struct packet_traits<std::complex<double> > : default_packet_traits {
439 typedef Packet1cd type;
440 typedef Packet1cd half;
441 typedef Packet2d as_real;
442 enum {
443 Vectorizable = 1,
444 AlignedOnScalar = 0,
445 size = 1,
446
447 HasAdd = 1,
448 HasSub = 1,
449 HasMul = 1,
450 HasDiv = 1,
451 HasNegate = 1,
452 HasAbs = 0,
453 HasAbs2 = 0,
454 HasMin = 0,
455 HasMax = 0,
456 HasSqrt = 1,
457 HasLog = 1,
458 HasSetLinear = 0
459 };
460};
461
462template <>
463struct unpacket_traits<Packet1cd> {
464 typedef std::complex<double> type;
465 enum {
466 size = 1,
467 alignment = Aligned16,
468 vectorizable = true,
469 masked_load_available = false,
470 masked_store_available = false
471 };
472 typedef Packet1cd half;
473 typedef Packet2d as_real;
474};
475
476template <>
477EIGEN_STRONG_INLINE Packet1cd pload<Packet1cd>(const std::complex<double>* from) {
478 return Packet1cd(pload<Packet2d>((const double*)from));
479}
480template <>
481EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from) {
482 return Packet1cd(ploadu<Packet2d>((const double*)from));
483}
484template <>
485EIGEN_ALWAYS_INLINE Packet1cd pload_partial<Packet1cd>(const std::complex<double>* from, const Index n,
486 const Index offset) {
487 return Packet1cd(pload_partial<Packet2d>((const double*)from, n * 2, offset * 2));
488}
489template <>
490EIGEN_ALWAYS_INLINE Packet1cd ploadu_partial<Packet1cd>(const std::complex<double>* from, const Index n,
491 const Index offset) {
492 return Packet1cd(ploadu_partial<Packet2d>((const double*)from, n * 2, offset * 2));
493}
494template <>
495EIGEN_STRONG_INLINE void pstore<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
496 pstore((double*)to, from.v);
497}
498template <>
499EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
500 pstoreu((double*)to, from.v);
501}
502template <>
503EIGEN_ALWAYS_INLINE void pstore_partial<std::complex<double> >(std::complex<double>* to, const Packet1cd& from,
504 const Index n, const Index offset) {
505 pstore_partial((double*)to, from.v, n * 2, offset * 2);
506}
507template <>
508EIGEN_ALWAYS_INLINE void pstoreu_partial<std::complex<double> >(std::complex<double>* to, const Packet1cd& from,
509 const Index n, const Index offset) {
510 pstoreu_partial((double*)to, from.v, n * 2, offset * 2);
511}
512
513template <>
514EIGEN_STRONG_INLINE Packet1cd
515pset1<Packet1cd>(const std::complex<double>& from) { /* here we really have to use unaligned loads :( */
516 return ploadu<Packet1cd>(&from);
517}
518
519template <>
520EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
521pgather<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index) {
522 return pload<Packet1cd>(from);
523}
524template <>
525EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
526pgather_partial<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index, const Index) {
527 return pload<Packet1cd>(from);
528}
529template <>
530EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter<std::complex<double>, Packet1cd>(std::complex<double>* to,
531 const Packet1cd& from, Index) {
532 pstore<std::complex<double> >(to, from);
533}
534template <>
535EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter_partial<std::complex<double>, Packet1cd>(std::complex<double>* to,
536 const Packet1cd& from,
537 Index, const Index) {
538 pstore<std::complex<double> >(to, from);
539}
540
541template <>
542EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
543 return Packet1cd(a.v + b.v);
544}
545template <>
546EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
547 return Packet1cd(a.v - b.v);
548}
549template <>
550EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) {
551 return Packet1cd(pnegate(Packet2d(a.v)));
552}
553template <>
554EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) {
555 return Packet1cd(pxor(a.v, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR2())));
556}
557
558template <>
559EIGEN_STRONG_INLINE Packet1cd pand<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
560 return Packet1cd(pand(a.v, b.v));
561}
562template <>
563EIGEN_STRONG_INLINE Packet1cd por<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
564 return Packet1cd(por(a.v, b.v));
565}
566template <>
567EIGEN_STRONG_INLINE Packet1cd pxor<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
568 return Packet1cd(pxor(a.v, b.v));
569}
570template <>
571EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
572 return Packet1cd(pandnot(a.v, b.v));
573}
574
575template <>
576EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) {
577 return pset1<Packet1cd>(*from);
578}
579
580template <>
581EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double>* addr) {
582 EIGEN_PPC_PREFETCH(addr);
583}
584
585template <>
586EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet1cd>(const Packet1cd& a) {
587 EIGEN_ALIGN16 std::complex<double> res[1];
588 pstore<std::complex<double> >(res, a);
589
590 return res[0];
591}
592
593template <>
594EIGEN_STRONG_INLINE Packet1cd preverse(const Packet1cd& a) {
595 return a;
596}
597
598template <>
599EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Packet1cd& a) {
600 return pfirst(a);
601}
602
603template <>
604EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) {
605 return pfirst(a);
606}
607
608EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd, Packet2d)
609
610template <>
611EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
612 return pdiv_complex(a, b);
613}
614
615EIGEN_STRONG_INLINE Packet1cd pcplxflip /*<Packet1cd>*/ (const Packet1cd& x) {
616 return Packet1cd(preverse(Packet2d(x.v)));
617}
618
619EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet1cd, 2>& kernel) {
620 Packet2d tmp = vec_mergeh(kernel.packet[0].v, kernel.packet[1].v);
621 kernel.packet[1].v = vec_mergel(kernel.packet[0].v, kernel.packet[1].v);
622 kernel.packet[0].v = tmp;
623}
624
625template <>
626EIGEN_STRONG_INLINE Packet1cd pcmp_eq(const Packet1cd& a, const Packet1cd& b) {
627 // Compare real and imaginary parts of a and b to get the mask vector:
628 // [re(a)==re(b), im(a)==im(b)]
629 Packet2d eq = reinterpret_cast<Packet2d>(vec_cmpeq(a.v, b.v));
630 // Swap real/imag elements in the mask in to get:
631 // [im(a)==im(b), re(a)==re(b)]
632 Packet2d eq_swapped =
633 reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(eq), reinterpret_cast<Packet4ui>(eq), 8));
634 // Return re(a)==re(b) & im(a)==im(b) by computing bitwise AND of eq and eq_swapped
635 return Packet1cd(vec_and(eq, eq_swapped));
636}
637
638template <>
639EIGEN_STRONG_INLINE Packet1cd psqrt<Packet1cd>(const Packet1cd& a) {
640 return psqrt_complex<Packet1cd>(a);
641}
642
643template <>
644EIGEN_STRONG_INLINE Packet1cd plog<Packet1cd>(const Packet1cd& a) {
645 return plog_complex<Packet1cd>(a);
646}
647
648#endif // __VSX__
649} // end namespace internal
650
651} // end namespace Eigen
652
653#endif // EIGEN_COMPLEX32_ALTIVEC_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