$darkmode
Eigen  5.0.1-dev
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 
17 namespace Eigen {
18 
19 namespace internal {
20 
21 inline 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)
26 inline Packet2ul p2ul_CONJ_XOR1() {
27  return (Packet2ul)vec_sld((Packet4ui)p2d_MZERO, (Packet4ui)p2l_ZERO,
28  8); //{ 0x8000000000000000, 0x0000000000000000 };
29 }
30 inline Packet2ul p2ul_CONJ_XOR2() {
31  return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
32  8); //{ 0x8000000000000000, 0x0000000000000000 };
33 }
34 #else
35 inline Packet2ul p2ul_CONJ_XOR1() {
36  return (Packet2ul)vec_sld((Packet4ui)p2l_ZERO, (Packet4ui)p2d_MZERO,
37  8); //{ 0x8000000000000000, 0x0000000000000000 };
38 }
39 inline 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 ----------
47 struct 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 
90 template <>
91 struct 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 
119 template <>
120 struct 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 
133 template <>
134 EIGEN_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 
152 template <>
153 EIGEN_STRONG_INLINE Packet2cf pload<Packet2cf>(const std::complex<float>* from) {
154  return Packet2cf(pload<Packet4f>((const float*)from));
155 }
156 template <>
157 EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>* from) {
158  return Packet2cf(ploadu<Packet4f>((const float*)from));
159 }
160 template <>
161 EIGEN_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 }
165 template <>
166 EIGEN_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 }
170 template <>
171 EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) {
172  return pset1<Packet2cf>(*from);
173 }
174 
175 template <>
176 EIGEN_STRONG_INLINE void pstore<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
177  pstore((float*)to, from.v);
178 }
179 template <>
180 EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float>* to, const Packet2cf& from) {
181  pstoreu((float*)to, from.v);
182 }
183 template <>
184 EIGEN_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 }
188 template <>
189 EIGEN_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 
194 EIGEN_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 
213 template <>
214 EIGEN_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 
220 template <typename Scalar, typename Packet>
221 EIGEN_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 }
230 template <>
231 EIGEN_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 }
235 template <>
236 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet2cf
237 pgather_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 }
240 template <typename Scalar, typename Packet>
241 EIGEN_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 }
250 template <>
251 EIGEN_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 }
256 template <>
257 EIGEN_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 
264 template <>
265 EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
266  return Packet2cf(a.v + b.v);
267 }
268 template <>
269 EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
270  return Packet2cf(a.v - b.v);
271 }
272 template <>
273 EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) {
274  return Packet2cf(pnegate(a.v));
275 }
276 template <>
277 EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) {
278  return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR())));
279 }
280 
281 template <>
282 EIGEN_STRONG_INLINE Packet2cf pand<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
283  return Packet2cf(pand<Packet4f>(a.v, b.v));
284 }
285 template <>
286 EIGEN_STRONG_INLINE Packet2cf por<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
287  return Packet2cf(por<Packet4f>(a.v, b.v));
288 }
289 template <>
290 EIGEN_STRONG_INLINE Packet2cf pxor<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
291  return Packet2cf(pxor<Packet4f>(a.v, b.v));
292 }
293 template <>
294 EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
295  return Packet2cf(pandnot<Packet4f>(a.v, b.v));
296 }
297 
298 template <>
299 EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float>* addr) {
300  EIGEN_PPC_PREFETCH(addr);
301 }
302 
303 template <>
304 EIGEN_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 
311 template <>
312 EIGEN_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 
318 template <>
319 EIGEN_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 
326 template <>
327 EIGEN_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 
336 EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cf, Packet4f)
337 
338 template <>
339 EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b) {
340  return pdiv_complex(a, b);
341 }
342 
343 template <>
344 EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x) {
345  return Packet2cf(vec_perm(x.v, x.v, p16uc_COMPLEX32_REV));
346 }
347 
348 EIGEN_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 
361 template <>
362 EIGEN_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
368 template <>
369 EIGEN_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 
378 template <>
379 EIGEN_STRONG_INLINE Packet2cf psqrt<Packet2cf>(const Packet2cf& a) {
380  return psqrt_complex<Packet2cf>(a);
381 }
382 
383 template <>
384 EIGEN_STRONG_INLINE Packet2cf plog<Packet2cf>(const Packet2cf& a) {
385  return plog_complex<Packet2cf>(a);
386 }
387 
388 template <>
389 EIGEN_STRONG_INLINE Packet2cf pexp<Packet2cf>(const Packet2cf& a) {
390  return pexp_complex<Packet2cf>(a);
391 }
392 
393 //---------- double ----------
394 #ifdef EIGEN_VECTORIZE_VSX
395 struct 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 
437 template <>
438 struct 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 
462 template <>
463 struct 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 
476 template <>
477 EIGEN_STRONG_INLINE Packet1cd pload<Packet1cd>(const std::complex<double>* from) {
478  return Packet1cd(pload<Packet2d>((const double*)from));
479 }
480 template <>
481 EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from) {
482  return Packet1cd(ploadu<Packet2d>((const double*)from));
483 }
484 template <>
485 EIGEN_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 }
489 template <>
490 EIGEN_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 }
494 template <>
495 EIGEN_STRONG_INLINE void pstore<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
496  pstore((double*)to, from.v);
497 }
498 template <>
499 EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double>* to, const Packet1cd& from) {
500  pstoreu((double*)to, from.v);
501 }
502 template <>
503 EIGEN_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 }
507 template <>
508 EIGEN_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 
513 template <>
514 EIGEN_STRONG_INLINE Packet1cd
515 pset1<Packet1cd>(const std::complex<double>& from) { /* here we really have to use unaligned loads :( */
516  return ploadu<Packet1cd>(&from);
517 }
518 
519 template <>
520 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
521 pgather<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index) {
522  return pload<Packet1cd>(from);
523 }
524 template <>
525 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE Packet1cd
526 pgather_partial<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index, const Index) {
527  return pload<Packet1cd>(from);
528 }
529 template <>
530 EIGEN_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 }
534 template <>
535 EIGEN_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 
541 template <>
542 EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
543  return Packet1cd(a.v + b.v);
544 }
545 template <>
546 EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
547  return Packet1cd(a.v - b.v);
548 }
549 template <>
550 EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) {
551  return Packet1cd(pnegate(Packet2d(a.v)));
552 }
553 template <>
554 EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) {
555  return Packet1cd(pxor(a.v, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR2())));
556 }
557 
558 template <>
559 EIGEN_STRONG_INLINE Packet1cd pand<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
560  return Packet1cd(pand(a.v, b.v));
561 }
562 template <>
563 EIGEN_STRONG_INLINE Packet1cd por<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
564  return Packet1cd(por(a.v, b.v));
565 }
566 template <>
567 EIGEN_STRONG_INLINE Packet1cd pxor<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
568  return Packet1cd(pxor(a.v, b.v));
569 }
570 template <>
571 EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
572  return Packet1cd(pandnot(a.v, b.v));
573 }
574 
575 template <>
576 EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>* from) {
577  return pset1<Packet1cd>(*from);
578 }
579 
580 template <>
581 EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double>* addr) {
582  EIGEN_PPC_PREFETCH(addr);
583 }
584 
585 template <>
586 EIGEN_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 
593 template <>
594 EIGEN_STRONG_INLINE Packet1cd preverse(const Packet1cd& a) {
595  return a;
596 }
597 
598 template <>
599 EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Packet1cd& a) {
600  return pfirst(a);
601 }
602 
603 template <>
604 EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) {
605  return pfirst(a);
606 }
607 
608 EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cd, Packet2d)
609 
610 template <>
611 EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b) {
612  return pdiv_complex(a, b);
613 }
614 
615 EIGEN_STRONG_INLINE Packet1cd pcplxflip /*<Packet1cd>*/ (const Packet1cd& x) {
616  return Packet1cd(preverse(Packet2d(x.v)));
617 }
618 
619 EIGEN_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 
625 template <>
626 EIGEN_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 
638 template <>
639 EIGEN_STRONG_INLINE Packet1cd psqrt<Packet1cd>(const Packet1cd& a) {
640  return psqrt_complex<Packet1cd>(a);
641 }
642 
643 template <>
644 EIGEN_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
const Product< MatrixDerived, PermutationDerived, DefaultProduct > operator*(const MatrixBase< MatrixDerived > &matrix, const PermutationBase< PermutationDerived > &permutation)
Definition: PermutationMatrix.h:474
Definition: Constants.h:237
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
Definition: BFloat16.h:231
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:82