cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

Complex.h (17541B)


      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 {
     24   EIGEN_STRONG_INLINE Packet2cf() {
     25   }
     26   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   }
     31   EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) {
     32   }
     33   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   }
     39   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