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