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) 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 HasSetLinear = 0
113 };
114};
115
116template <>
117struct unpacket_traits<Packet2cf> {
118 typedef std::complex<float> type;
119 enum {
120 size = 2,
121 alignment = Aligned16,
122 vectorizable = true,
123 masked_load_available = false,
124 masked_store_available = false
125 };
126 typedef Packet2cf half;
127 typedef Packet4f as_real;
128};
129
130template <>
131EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>& from) {
132 Packet2cf res;
133#ifdef EIGEN_VECTORIZE_VSX
134 // Load a single std::complex<float> from memory and duplicate
135 //
136 // Using pload would read past the end of the reference in this case
137 // Using vec_xl_len + vec_splat, generates poor assembly
138 __asm__("lxvdsx %x0,%y1" : "=wa"(res.v) : "Z"(from));
139#else
140 if ((std::ptrdiff_t(&from) % 16) == 0)
141 res.v = pload<Packet4f>((const float*)&from);
142 else
143 res.v = ploadu<Packet4f>((const float*)&from);
144 res.v = vec_perm(res.v, res.v, p16uc_PSET64_HI);
145#endif
146 return res;
147}
148
149template <>
150EIGEN_STRONG_INLINE Packet2cf pload<Packet2cf>(const std::complex<float>* from) {
151 return Packet2cf(pload<Packet4f>((const float*)from));
152}
153template <>
154EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) {
155 return Packet2cf(ploadu<Packet4f>((const float*)from));
156}
157template <>
158EIGEN_ALWAYS_INLINE Packet2cf pload_partial<Packet2cf>(const std::complex<float>* from, const Index n,
159 const Index offset) {
160 return Packet2cf(pload_partial<Packet4f>((const float*)from, n * 2, offset * 2));
161}
162template <>
163EIGEN_ALWAYS_INLINE Packet2cf ploadu_partial<Packet2cf>(const std::complex<float>* from, const Index n,
164 const Index offset) {
165 return Packet2cf(ploadu_partial<Packet4f>((const float*)from, n * 2, offset * 2));
166}
167template <>
168EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) {
169 return pset1<Packet2cf>(*from);
170}
171
172template <>
173EIGEN_STRONG_INLINE void pstore<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
174 pstore((float*)to, from.v);
175}
176template <>
177EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
178 pstoreu((float*)to, from.v);
179}
180template <>
181EIGEN_ALWAYS_INLINE void pstore_partial<std::complex<float> >(std::complex<float>* to, const Packet2cf& from,
182 const Index n, const Index offset) {
183 pstore_partial((float*)to, from.v, n * 2, offset * 2);
184}
185template <>
186EIGEN_ALWAYS_INLINE void pstoreu_partial<std::complex<float> >(std::complex<float>* to, const Packet2cf& from,
187 const Index n, const Index offset) {
188 pstoreu_partial((float*)to, from.v, n * 2, offset * 2);
189}
190
191EIGEN_STRONG_INLINE Packet2cf pload2(const std::complex<float>& from0, const std::complex<float>& from1) {
192 Packet4f res0, res1;
193#ifdef EIGEN_VECTORIZE_VSX
194 // Load two std::complex<float> from memory and combine
195 __asm__("lxsdx %x0,%y1" : "=wa"(res0) : "Z"(from0));
196 __asm__("lxsdx %x0,%y1" : "=wa"(res1) : "Z"(from1));
197#ifdef _BIG_ENDIAN
198 __asm__("xxpermdi %x0, %x1, %x2, 0" : "=wa"(res0) : "wa"(res0), "wa"(res1));
199#else
200 __asm__("xxpermdi %x0, %x2, %x1, 0" : "=wa"(res0) : "wa"(res0), "wa"(res1));
201#endif
202#else
203 *reinterpret_cast<std::complex<float>*>(&res0) = from0;
204 *reinterpret_cast<std::complex<float>*>(&res1) = from1;
205 res0 = vec_perm(res0, res1, p16uc_TRANSPOSE64_HI);
206#endif
207 return Packet2cf(res0);
208}
209
210template <>
211EIGEN_ALWAYS_INLINE Packet2cf pload_ignore<Packet2cf>(const std::complex<float>* from) {
212 Packet2cf res;
213 res.v = pload_ignore<Packet4f>(reinterpret_cast<const float*>(from));
214 return res;
215}
216
217template <typename Scalar, typename Packet>
218EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet pgather_complex_size2(const Scalar* from, Index stride,
219 const Index n = 2) {
220 eigen_internal_assert(n <= unpacket_traits<Packet>::size && "number of elements will gather past end of packet");
221 EIGEN_ALIGN16 Scalar af[2];
222 for (Index i = 0; i < n; i++) {
223 af[i] = from[i * stride];
224 }
225 return pload_ignore<Packet>(af);
226}
227template <>
228EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from,
229 Index stride) {
230 return pgather_complex_size2<std::complex<float>, Packet2cf>(from, stride);
231}
232template <>
233EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet2cf
234pgather_partial<std::complex<float>, Packet2cf>(const std::complex<float>* from, Index stride, const Index n) {
235 return pgather_complex_size2<std::complex<float>, Packet2cf>(from, stride, n);
236}
237template <typename Scalar, typename Packet>
238EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter_complex_size2(Scalar* to, const Packet& from, Index stride,
239 const Index n = 2) {
240 eigen_internal_assert(n <= unpacket_traits<Packet>::size && "number of elements will scatter past end of packet");
241 EIGEN_ALIGN16 Scalar af[2];
242 pstore<Scalar>((Scalar*)af, from);
243 for (Index i = 0; i < n; i++) {
244 to[i * stride] = af[i];
245 }
246}
247template <>
248EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to,
249 const Packet2cf& from,
250 Index stride) {
251 pscatter_complex_size2<std::complex<float>, Packet2cf>(to, from, stride);
252}
253template <>
254EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter_partial<std::complex<float>, Packet2cf>(std::complex<float>* to,
255 const Packet2cf& from,
256 Index stride,
257 const Index n) {
258 pscatter_complex_size2<std::complex<float>, Packet2cf>(to, from, stride, n);
259}
260
261template <>
262EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
263 return Packet2cf(a.v + b.v);
264}
265template <>
266EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
267 return Packet2cf(a.v - b.v);
268}
269template <>
270EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) {
271 return Packet2cf(pnegate(a.v));
272}
273template <>
274EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) {
275 return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR())));
276}
277
278template <>
279EIGEN_STRONG_INLINE Packet2cf pand<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
280 return Packet2cf(pand<Packet4f>(a.v, b.v));
281}
282template <>
283EIGEN_STRONG_INLINE Packet2cf por<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
284 return Packet2cf(por<Packet4f>(a.v, b.v));
285}
286template <>
287EIGEN_STRONG_INLINE Packet2cf pxor<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
288 return Packet2cf(pxor<Packet4f>(a.v, b.v));
289}
290template <>
291EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
292 return Packet2cf(pandnot<Packet4f>(a.v, b.v));
293}
294
295template <>
296EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float>* addr) {
297 EIGEN_PPC_PREFETCH(addr);
298}
299
300template <>
301EIGEN_STRONG_INLINE std::complex<float> pfirst<Packet2cf>(const Packet2cf& a) {
302 EIGEN_ALIGN16 std::complex<float> res[2];
303 pstore((float*)&res, a.v);
304
305 return res[0];
306}
307
308template <>
309EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a) {
310 Packet4f rev_a;
311 rev_a = vec_sld(a.v, a.v, 8);
312 return Packet2cf(rev_a);
313}
314
315template <>
316EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a) {
317 Packet4f b;
318 b = vec_sld(a.v, a.v, 8);
319 b = padd<Packet4f>(a.v, b);
320 return pfirst<Packet2cf>(Packet2cf(b));
321}
322
323template <>
324EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a) {
325 Packet4f b;
326 Packet2cf prod;
327 b = vec_sld(a.v, a.v, 8);
328 prod = pmul<Packet2cf>(a, Packet2cf(b));
329
330 return pfirst<Packet2cf>(prod);
331}
332
333EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf, Packet4f)
334
335template <>
336EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
337 return pdiv_complex(a, b);
338}
339
340template <>
341EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x) {
342 return Packet2cf(vec_perm(x.v, x.v, p16uc_COMPLEX32_REV));
343}
344
345EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet2cf, 2>& kernel) {
346#ifdef EIGEN_VECTORIZE_VSX
347 Packet4f tmp = reinterpret_cast<Packet4f>(
348 vec_mergeh(reinterpret_cast<Packet2d>(kernel.packet[0].v), reinterpret_cast<Packet2d>(kernel.packet[1].v)));
349 kernel.packet[1].v = reinterpret_cast<Packet4f>(
350 vec_mergel(reinterpret_cast<Packet2d>(kernel.packet[0].v), reinterpret_cast<Packet2d>(kernel.packet[1].v)));
351#else
352 Packet4f tmp = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_HI);
353 kernel.packet[1].v = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_LO);
354#endif
355 kernel.packet[0].v = tmp;
356}
357
358template <>
359EIGEN_STRONG_INLINE Packet2cf pcmp_eq(const Packet2cf& a, const Packet2cf& b) {
360 Packet4f eq = reinterpret_cast<Packet4f>(vec_cmpeq(a.v, b.v));
361 return Packet2cf(vec_and(eq, vec_perm(eq, eq, p16uc_COMPLEX32_REV)));
362}
363
364template <>
365EIGEN_STRONG_INLINE Packet2cf psqrt<Packet2cf>(const Packet2cf& a) {
366 return psqrt_complex<Packet2cf>(a);
367}
368
369template <>
370EIGEN_STRONG_INLINE Packet2cf plog<Packet2cf>(const Packet2cf& a) {
371 return plog_complex<Packet2cf>(a);
372}
373
374template <>
375EIGEN_STRONG_INLINE Packet2cf pexp<Packet2cf>(const Packet2cf& a) {
376 return pexp_complex<Packet2cf>(a);
377}
378
379//---------- double ----------
380#ifdef EIGEN_VECTORIZE_VSX
381struct Packet1cd {
382 EIGEN_STRONG_INLINE Packet1cd() {}
383 EIGEN_STRONG_INLINE explicit Packet1cd(const Packet2d& a) : v(a) {}
384
385 EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) {
386 Packet2d a_re, a_im, v1, v2;
387
388 // Permute and multiply the real parts of a and b
389 a_re = vec_perm(a.v, a.v, p16uc_PSET64_HI);
390 // Get the imaginary parts of a
391 a_im = vec_perm(a.v, a.v, p16uc_PSET64_LO);
392 // multiply a_re * b
393 v1 = vec_madd(a_re, b.v, p2d_ZERO);
394 // multiply a_im * b and get the conjugate result
395 v2 = vec_madd(a_im, b.v, p2d_ZERO);
396 v2 = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(v2), reinterpret_cast<Packet4ui>(v2), 8));
397 v2 = pxor(v2, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR1()));
398
399 return Packet1cd(padd<Packet2d>(v1, v2));
400 }
401
402 EIGEN_STRONG_INLINE Packet1cd& operator*=(const Packet1cd& b) {
403 v = pmul(Packet1cd(*this), b).v;
404 return *this;
405 }
406 EIGEN_STRONG_INLINE Packet1cd operator*(const Packet1cd& b) const { return Packet1cd(*this) *= b; }
407
408 EIGEN_STRONG_INLINE Packet1cd& operator+=(const Packet1cd& b) {
409 v = padd(v, b.v);
410 return *this;
411 }
412 EIGEN_STRONG_INLINE Packet1cd operator+(const Packet1cd& b) const { return Packet1cd(*this) += b; }
413 EIGEN_STRONG_INLINE Packet1cd& operator-=(const Packet1cd& b) {
414 v = psub(v, b.v);
415 return *this;
416 }
417 EIGEN_STRONG_INLINE Packet1cd operator-(const Packet1cd& b) const { return Packet1cd(*this) -= b; }
418 EIGEN_STRONG_INLINE Packet1cd operator-(void) const { return Packet1cd(-v); }
419
420 Packet2d v;
421};
422
423template <>
424struct packet_traits<std::complex<double> > : default_packet_traits {
425 typedef Packet1cd type;
426 typedef Packet1cd half;
427 typedef Packet2d as_real;
428 enum {
429 Vectorizable = 1,
430 AlignedOnScalar = 0,
431 size = 1,
432
433 HasAdd = 1,
434 HasSub = 1,
435 HasMul = 1,
436 HasDiv = 1,
437 HasNegate = 1,
438 HasAbs = 0,
439 HasAbs2 = 0,
440 HasMin = 0,
441 HasMax = 0,
442 HasSqrt = 1,
443 HasLog = 1,
444 HasSetLinear = 0
445 };
446};
447
448template <>
449struct unpacket_traits<Packet1cd> {
450 typedef std::complex<double> type;
451 enum {
452 size = 1,
453 alignment = Aligned16,
454 vectorizable = true,
455 masked_load_available = false,
456 masked_store_available = false
457 };
458 typedef Packet1cd half;
459 typedef Packet2d as_real;
460};
461
462template <>
463EIGEN_STRONG_INLINE Packet1cd pload<Packet1cd>(const std::complex<double>* from) {
464 return Packet1cd(pload<Packet2d>((const double*)from));
465}
466template <>
467EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from) {
468 return Packet1cd(ploadu<Packet2d>((const double*)from));
469}
470template <>
471EIGEN_ALWAYS_INLINE Packet1cd pload_partial<Packet1cd>(const std::complex<double>* from, const Index n,
472 const Index offset) {
473 return Packet1cd(pload_partial<Packet2d>((const double*)from, n * 2, offset * 2));
474}
475template <>
476EIGEN_ALWAYS_INLINE Packet1cd ploadu_partial<Packet1cd>(const std::complex<double>* from, const Index n,
477 const Index offset) {
478 return Packet1cd(ploadu_partial<Packet2d>((const double*)from, n * 2, offset * 2));
479}
480template <>
481EIGEN_STRONG_INLINE void pstore<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
482 pstore((double*)to, from.v);
483}
484template <>
485EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
486 pstoreu((double*)to, from.v);
487}
488template <>
489EIGEN_ALWAYS_INLINE void pstore_partial<std::complex<double> >(std::complex<double>* to, const Packet1cd& from,
490 const Index n, const Index offset) {
491 pstore_partial((double*)to, from.v, n * 2, offset * 2);
492}
493template <>
494EIGEN_ALWAYS_INLINE void pstoreu_partial<std::complex<double> >(std::complex<double>* to, const Packet1cd& from,
495 const Index n, const Index offset) {
496 pstoreu_partial((double*)to, from.v, n * 2, offset * 2);
497}
498
499template <>
500EIGEN_STRONG_INLINE Packet1cd
501pset1<Packet1cd>(const std::complex<double>& from) { /* here we really have to use unaligned loads :( */
502 return ploadu<Packet1cd>(&from);
503}
504
505template <>
506EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
507pgather<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index) {
508 return pload<Packet1cd>(from);
509}
510template <>
511EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
512pgather_partial<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index, const Index) {
513 return pload<Packet1cd>(from);
514}
515template <>
516EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter<std::complex<double>, Packet1cd>(std::complex<double>* to,
517 const Packet1cd& from, Index) {
518 pstore<std::complex<double> >(to, from);
519}
520template <>
521EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void pscatter_partial<std::complex<double>, Packet1cd>(std::complex<double>* to,
522 const Packet1cd& from,
523 Index, const Index) {
524 pstore<std::complex<double> >(to, from);
525}
526
527template <>
528EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
529 return Packet1cd(a.v + b.v);
530}
531template <>
532EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
533 return Packet1cd(a.v - b.v);
534}
535template <>
536EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) {
537 return Packet1cd(pnegate(Packet2d(a.v)));
538}
539template <>
540EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) {
541 return Packet1cd(pxor(a.v, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR2())));
542}
543
544template <>
545EIGEN_STRONG_INLINE Packet1cd pand<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
546 return Packet1cd(pand(a.v, b.v));
547}
548template <>
549EIGEN_STRONG_INLINE Packet1cd por<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
550 return Packet1cd(por(a.v, b.v));
551}
552template <>
553EIGEN_STRONG_INLINE Packet1cd pxor<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
554 return Packet1cd(pxor(a.v, b.v));
555}
556template <>
557EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
558 return Packet1cd(pandnot(a.v, b.v));
559}
560
561template <>
562EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) {
563 return pset1<Packet1cd>(*from);
564}
565
566template <>
567EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double>* addr) {
568 EIGEN_PPC_PREFETCH(addr);
569}
570
571template <>
572EIGEN_STRONG_INLINE std::complex<double> pfirst<Packet1cd>(const Packet1cd& a) {
573 EIGEN_ALIGN16 std::complex<double> res[1];
574 pstore<std::complex<double> >(res, a);
575
576 return res[0];
577}
578
579template <>
580EIGEN_STRONG_INLINE Packet1cd preverse(const Packet1cd& a) {
581 return a;
582}
583
584template <>
585EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Packet1cd& a) {
586 return pfirst(a);
587}
588
589template <>
590EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) {
591 return pfirst(a);
592}
593
594EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd, Packet2d)
595
596template <>
597EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
598 return pdiv_complex(a, b);
599}
600
601EIGEN_STRONG_INLINE Packet1cd pcplxflip /*<Packet1cd>*/ (const Packet1cd& x) {
602 return Packet1cd(preverse(Packet2d(x.v)));
603}
604
605EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet1cd, 2>& kernel) {
606 Packet2d tmp = vec_mergeh(kernel.packet[0].v, kernel.packet[1].v);
607 kernel.packet[1].v = vec_mergel(kernel.packet[0].v, kernel.packet[1].v);
608 kernel.packet[0].v = tmp;
609}
610
611template <>
612EIGEN_STRONG_INLINE Packet1cd pcmp_eq(const Packet1cd& a, const Packet1cd& b) {
613 // Compare real and imaginary parts of a and b to get the mask vector:
614 // [re(a)==re(b), im(a)==im(b)]
615 Packet2d eq = reinterpret_cast<Packet2d>(vec_cmpeq(a.v, b.v));
616 // Swap real/imag elements in the mask in to get:
617 // [im(a)==im(b), re(a)==re(b)]
618 Packet2d eq_swapped =
619 reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(eq), reinterpret_cast<Packet4ui>(eq), 8));
620 // Return re(a)==re(b) & im(a)==im(b) by computing bitwise AND of eq and eq_swapped
621 return Packet1cd(vec_and(eq, eq_swapped));
622}
623
624template <>
625EIGEN_STRONG_INLINE Packet1cd psqrt<Packet1cd>(const Packet1cd& a) {
626 return psqrt_complex<Packet1cd>(a);
627}
628
629template <>
630EIGEN_STRONG_INLINE Packet1cd plog<Packet1cd>(const Packet1cd& a) {
631 return plog_complex<Packet1cd>(a);
632}
633
634#endif // __VSX__
635} // end namespace internal
636
637} // end namespace Eigen
638
639#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