Eigen  3.3.3
Complex.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 // Copyright (C) 2010-2016 Konstantinos Margaritis <markos@freevec.org>
00006 //
00007 // This Source Code Form is subject to the terms of the Mozilla
00008 // Public License v. 2.0. If a copy of the MPL was not distributed
00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00010 
00011 #ifndef EIGEN_COMPLEX32_ALTIVEC_H
00012 #define EIGEN_COMPLEX32_ALTIVEC_H
00013 
00014 namespace Eigen {
00015 
00016 namespace internal {
00017 
00018 static Packet4ui  p4ui_CONJ_XOR = vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO);//{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 };
00019 #ifdef __VSX__
00020 #if defined(_BIG_ENDIAN)
00021 static Packet2ul  p2ul_CONJ_XOR1 = (Packet2ul) vec_sld((Packet4ui) p2d_MZERO, (Packet4ui) p2l_ZERO, 8);//{ 0x8000000000000000, 0x0000000000000000 };
00022 static Packet2ul  p2ul_CONJ_XOR2 = (Packet2ul) vec_sld((Packet4ui) p2l_ZERO,  (Packet4ui) p2d_MZERO, 8);//{ 0x8000000000000000, 0x0000000000000000 };
00023 #else
00024 static Packet2ul  p2ul_CONJ_XOR1 = (Packet2ul) vec_sld((Packet4ui) p2l_ZERO,  (Packet4ui) p2d_MZERO, 8);//{ 0x8000000000000000, 0x0000000000000000 };
00025 static Packet2ul  p2ul_CONJ_XOR2 = (Packet2ul) vec_sld((Packet4ui) p2d_MZERO, (Packet4ui) p2l_ZERO, 8);//{ 0x8000000000000000, 0x0000000000000000 };
00026 #endif
00027 #endif
00028 
00029 //---------- float ----------
00030 struct Packet2cf
00031 {
00032   EIGEN_STRONG_INLINE explicit Packet2cf() : v(p4f_ZERO) {}
00033   EIGEN_STRONG_INLINE explicit Packet2cf(const Packet4f& a) : v(a) {}
00034   Packet4f  v;
00035 };
00036 
00037 template<> struct packet_traits<std::complex<float> >  : default_packet_traits
00038 {
00039   typedef Packet2cf type;
00040   typedef Packet2cf half;
00041   enum {
00042     Vectorizable = 1,
00043     AlignedOnScalar = 1,
00044     size = 2,
00045     HasHalfPacket = 0,
00046 
00047     HasAdd    = 1,
00048     HasSub    = 1,
00049     HasMul    = 1,
00050     HasDiv    = 1,
00051     HasNegate = 1,
00052     HasAbs    = 0,
00053     HasAbs2   = 0,
00054     HasMin    = 0,
00055     HasMax    = 0,
00056 #ifdef __VSX__
00057     HasBlend  = 1,
00058 #endif
00059     HasSetLinear = 0
00060   };
00061 };
00062 
00063 template<> struct unpacket_traits<Packet2cf> { typedef std::complex<float> type; enum {size=2, alignment=Aligned16}; typedef Packet2cf half; };
00064 
00065 template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>&  from)
00066 {
00067   Packet2cf res;
00068   if((std::ptrdiff_t(&from) % 16) == 0)
00069     res.v = pload<Packet4f>((const float *)&from);
00070   else
00071     res.v = ploadu<Packet4f>((const float *)&from);
00072   res.v = vec_perm(res.v, res.v, p16uc_PSET64_HI);
00073   return res;
00074 }
00075 
00076 template<> EIGEN_STRONG_INLINE Packet2cf pload<Packet2cf>(const std::complex<float>*        from) { return Packet2cf(pload<Packet4f>((const float *) from)); }
00077 template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<float>*       from) { return Packet2cf(ploadu<Packet4f>((const float*) from)); }
00078 template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>*     from) { return pset1<Packet2cf>(*from); }
00079 
00080 template<> EIGEN_STRONG_INLINE void pstore <std::complex<float> >(std::complex<float> *   to, const Packet2cf& from) { pstore((float*)to, from.v); }
00081 template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<float> >(std::complex<float> *   to, const Packet2cf& from) { pstoreu((float*)to, from.v); }
00082 
00083 template<> EIGEN_DEVICE_FUNC inline Packet2cf pgather<std::complex<float>, Packet2cf>(const std::complex<float>* from, Index stride)
00084 {
00085   std::complex<float> EIGEN_ALIGN16 af[2];
00086   af[0] = from[0*stride];
00087   af[1] = from[1*stride];
00088   return pload<Packet2cf>(af);
00089 }
00090 template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<float>, Packet2cf>(std::complex<float>* to, const Packet2cf& from, Index stride)
00091 {
00092   std::complex<float> EIGEN_ALIGN16 af[2];
00093   pstore<std::complex<float> >((std::complex<float> *) af, from);
00094   to[0*stride] = af[0];
00095   to[1*stride] = af[1];
00096 }
00097 
00098 template<> EIGEN_STRONG_INLINE Packet2cf padd<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(a.v + b.v); }
00099 template<> EIGEN_STRONG_INLINE Packet2cf psub<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(a.v - b.v); }
00100 template<> EIGEN_STRONG_INLINE Packet2cf pnegate(const Packet2cf& a) { return Packet2cf(pnegate(a.v)); }
00101 template<> EIGEN_STRONG_INLINE Packet2cf pconj(const Packet2cf& a) { return Packet2cf(pxor<Packet4f>(a.v, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR))); }
00102 
00103 template<> EIGEN_STRONG_INLINE Packet2cf pmul<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
00104 {
00105   Packet4f v1, v2;
00106 
00107   // Permute and multiply the real parts of a and b
00108   v1 = vec_perm(a.v, a.v, p16uc_PSET32_WODD);
00109   // Get the imaginary parts of a
00110   v2 = vec_perm(a.v, a.v, p16uc_PSET32_WEVEN);
00111   // multiply a_re * b 
00112   v1 = vec_madd(v1, b.v, p4f_ZERO);
00113   // multiply a_im * b and get the conjugate result
00114   v2 = vec_madd(v2, b.v, p4f_ZERO);
00115   v2 = reinterpret_cast<Packet4f>(pxor(v2, reinterpret_cast<Packet4f>(p4ui_CONJ_XOR)));
00116   // permute back to a proper order
00117   v2 = vec_perm(v2, v2, p16uc_COMPLEX32_REV);
00118   
00119   return Packet2cf(padd<Packet4f>(v1, v2));
00120 }
00121 
00122 template<> EIGEN_STRONG_INLINE Packet2cf pand   <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(pand<Packet4f>(a.v, b.v)); }
00123 template<> EIGEN_STRONG_INLINE Packet2cf por    <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(por<Packet4f>(a.v, b.v)); }
00124 template<> EIGEN_STRONG_INLINE Packet2cf pxor   <Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(pxor<Packet4f>(a.v, b.v)); }
00125 template<> EIGEN_STRONG_INLINE Packet2cf pandnot<Packet2cf>(const Packet2cf& a, const Packet2cf& b) { return Packet2cf(pandnot<Packet4f>(a.v, b.v)); }
00126 
00127 template<> EIGEN_STRONG_INLINE void prefetch<std::complex<float> >(const std::complex<float> * addr)    { EIGEN_PPC_PREFETCH(addr); }
00128 
00129 template<> EIGEN_STRONG_INLINE std::complex<float>  pfirst<Packet2cf>(const Packet2cf& a)
00130 {
00131   std::complex<float> EIGEN_ALIGN16 res[2];
00132   pstore((float *)&res, a.v);
00133 
00134   return res[0];
00135 }
00136 
00137 template<> EIGEN_STRONG_INLINE Packet2cf preverse(const Packet2cf& a)
00138 {
00139   Packet4f rev_a;
00140   rev_a = vec_perm(a.v, a.v, p16uc_COMPLEX32_REV2);
00141   return Packet2cf(rev_a);
00142 }
00143 
00144 template<> EIGEN_STRONG_INLINE std::complex<float> predux<Packet2cf>(const Packet2cf& a)
00145 {
00146   Packet4f b;
00147   b = vec_sld(a.v, a.v, 8);
00148   b = padd<Packet4f>(a.v, b);
00149   return pfirst<Packet2cf>(Packet2cf(b));
00150 }
00151 
00152 template<> EIGEN_STRONG_INLINE Packet2cf preduxp<Packet2cf>(const Packet2cf* vecs)
00153 {
00154   Packet4f b1, b2;
00155 #ifdef _BIG_ENDIAN  
00156   b1 = vec_sld(vecs[0].v, vecs[1].v, 8);
00157   b2 = vec_sld(vecs[1].v, vecs[0].v, 8);
00158 #else
00159   b1 = vec_sld(vecs[1].v, vecs[0].v, 8);
00160   b2 = vec_sld(vecs[0].v, vecs[1].v, 8);
00161 #endif
00162   b2 = vec_sld(b2, b2, 8);
00163   b2 = padd<Packet4f>(b1, b2);
00164 
00165   return Packet2cf(b2);
00166 }
00167 
00168 template<> EIGEN_STRONG_INLINE std::complex<float> predux_mul<Packet2cf>(const Packet2cf& a)
00169 {
00170   Packet4f b;
00171   Packet2cf prod;
00172   b = vec_sld(a.v, a.v, 8);
00173   prod = pmul<Packet2cf>(a, Packet2cf(b));
00174 
00175   return pfirst<Packet2cf>(prod);
00176 }
00177 
00178 template<int Offset>
00179 struct palign_impl<Offset,Packet2cf>
00180 {
00181   static EIGEN_STRONG_INLINE void run(Packet2cf& first, const Packet2cf& second)
00182   {
00183     if (Offset==1)
00184     {
00185 #ifdef _BIG_ENDIAN
00186       first.v = vec_sld(first.v, second.v, 8);
00187 #else
00188       first.v = vec_sld(second.v, first.v, 8);
00189 #endif
00190     }
00191   }
00192 };
00193 
00194 template<> struct conj_helper<Packet2cf, Packet2cf, false,true>
00195 {
00196   EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
00197   { return padd(pmul(x,y),c); }
00198 
00199   EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
00200   {
00201     return internal::pmul(a, pconj(b));
00202   }
00203 };
00204 
00205 template<> struct conj_helper<Packet2cf, Packet2cf, true,false>
00206 {
00207   EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
00208   { return padd(pmul(x,y),c); }
00209 
00210   EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
00211   {
00212     return internal::pmul(pconj(a), b);
00213   }
00214 };
00215 
00216 template<> struct conj_helper<Packet2cf, Packet2cf, true,true>
00217 {
00218   EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet2cf& y, const Packet2cf& c) const
00219   { return padd(pmul(x,y),c); }
00220 
00221   EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& a, const Packet2cf& b) const
00222   {
00223     return pconj(internal::pmul(a, b));
00224   }
00225 };
00226 
00227 template<> struct conj_helper<Packet4f, Packet2cf, false,false>
00228 {
00229   EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet4f& x, const Packet2cf& y, const Packet2cf& c) const
00230   { return padd(c, pmul(x,y)); }
00231 
00232   EIGEN_STRONG_INLINE Packet2cf pmul(const Packet4f& x, const Packet2cf& y) const
00233   { return Packet2cf(internal::pmul<Packet4f>(x, y.v)); }
00234 };
00235 
00236 template<> struct conj_helper<Packet2cf, Packet4f, false,false>
00237 {
00238   EIGEN_STRONG_INLINE Packet2cf pmadd(const Packet2cf& x, const Packet4f& y, const Packet2cf& c) const
00239   { return padd(c, pmul(x,y)); }
00240 
00241   EIGEN_STRONG_INLINE Packet2cf pmul(const Packet2cf& x, const Packet4f& y) const
00242   { return Packet2cf(internal::pmul<Packet4f>(x.v, y)); }
00243 };
00244 
00245 template<> EIGEN_STRONG_INLINE Packet2cf pdiv<Packet2cf>(const Packet2cf& a, const Packet2cf& b)
00246 {
00247   // TODO optimize it for AltiVec
00248   Packet2cf res = conj_helper<Packet2cf,Packet2cf,false,true>().pmul(a, b);
00249   Packet4f s = pmul<Packet4f>(b.v, b.v);
00250   return Packet2cf(pdiv(res.v, padd<Packet4f>(s, vec_perm(s, s, p16uc_COMPLEX32_REV))));
00251 }
00252 
00253 template<> EIGEN_STRONG_INLINE Packet2cf pcplxflip<Packet2cf>(const Packet2cf& x)
00254 {
00255   return Packet2cf(vec_perm(x.v, x.v, p16uc_COMPLEX32_REV));
00256 }
00257 
00258 EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet2cf,2>& kernel)
00259 {
00260   Packet4f tmp = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_HI);
00261   kernel.packet[1].v = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_LO);
00262   kernel.packet[0].v = tmp;
00263 }
00264 
00265 #ifdef __VSX__
00266 template<> EIGEN_STRONG_INLINE Packet2cf pblend(const Selector<2>& ifPacket, const Packet2cf& thenPacket, const Packet2cf& elsePacket) {
00267   Packet2cf result;
00268   result.v = reinterpret_cast<Packet4f>(pblend<Packet2d>(ifPacket, reinterpret_cast<Packet2d>(thenPacket.v), reinterpret_cast<Packet2d>(elsePacket.v)));
00269   return result;
00270 }
00271 #endif
00272 
00273 //---------- double ----------
00274 #ifdef __VSX__
00275 struct Packet1cd
00276 {
00277   EIGEN_STRONG_INLINE Packet1cd() {}
00278   EIGEN_STRONG_INLINE explicit Packet1cd(const Packet2d& a) : v(a) {}
00279   Packet2d v;
00280 };
00281 
00282 template<> struct packet_traits<std::complex<double> >  : default_packet_traits
00283 {
00284   typedef Packet1cd type;
00285   typedef Packet1cd half;
00286   enum {
00287     Vectorizable = 1,
00288     AlignedOnScalar = 0,
00289     size = 1,
00290     HasHalfPacket = 0,
00291 
00292     HasAdd    = 1,
00293     HasSub    = 1,
00294     HasMul    = 1,
00295     HasDiv    = 1,
00296     HasNegate = 1,
00297     HasAbs    = 0,
00298     HasAbs2   = 0,
00299     HasMin    = 0,
00300     HasMax    = 0,
00301     HasSetLinear = 0
00302   };
00303 };
00304 
00305 template<> struct unpacket_traits<Packet1cd> { typedef std::complex<double> type; enum {size=1, alignment=Aligned16}; typedef Packet1cd half; };
00306 
00307 template<> EIGEN_STRONG_INLINE Packet1cd pload <Packet1cd>(const std::complex<double>* from) { return Packet1cd(pload<Packet2d>((const double*)from)); }
00308 template<> EIGEN_STRONG_INLINE Packet1cd ploadu<Packet1cd>(const std::complex<double>* from) { return Packet1cd(ploadu<Packet2d>((const double*)from)); }
00309 template<> EIGEN_STRONG_INLINE void pstore <std::complex<double> >(std::complex<double> *   to, const Packet1cd& from) { pstore((double*)to, from.v); }
00310 template<> EIGEN_STRONG_INLINE void pstoreu<std::complex<double> >(std::complex<double> *   to, const Packet1cd& from) { pstoreu((double*)to, from.v); }
00311 
00312 template<> EIGEN_STRONG_INLINE Packet1cd pset1<Packet1cd>(const std::complex<double>&  from)
00313 { /* here we really have to use unaligned loads :( */ return ploadu<Packet1cd>(&from); }
00314 
00315 template<> EIGEN_DEVICE_FUNC inline Packet1cd pgather<std::complex<double>, Packet1cd>(const std::complex<double>* from, Index stride)
00316 {
00317   std::complex<double> EIGEN_ALIGN16 af[2];
00318   af[0] = from[0*stride];
00319   af[1] = from[1*stride];
00320   return pload<Packet1cd>(af);
00321 }
00322 template<> EIGEN_DEVICE_FUNC inline void pscatter<std::complex<double>, Packet1cd>(std::complex<double>* to, const Packet1cd& from, Index stride)
00323 {
00324   std::complex<double> EIGEN_ALIGN16 af[2];
00325   pstore<std::complex<double> >(af, from);
00326   to[0*stride] = af[0];
00327   to[1*stride] = af[1];
00328 }
00329 
00330 template<> EIGEN_STRONG_INLINE Packet1cd padd<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(a.v + b.v); }
00331 template<> EIGEN_STRONG_INLINE Packet1cd psub<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(a.v - b.v); }
00332 template<> EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) { return Packet1cd(pnegate(Packet2d(a.v))); }
00333 template<> EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) { return Packet1cd(pxor(a.v, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR2))); }
00334 
00335 template<> EIGEN_STRONG_INLINE Packet1cd pmul<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
00336 {
00337   Packet2d a_re, a_im, v1, v2;
00338 
00339   // Permute and multiply the real parts of a and b
00340   a_re = vec_perm(a.v, a.v, p16uc_PSET64_HI);
00341   // Get the imaginary parts of a
00342   a_im = vec_perm(a.v, a.v, p16uc_PSET64_LO);
00343   // multiply a_re * b
00344   v1 = vec_madd(a_re, b.v, p2d_ZERO);
00345   // multiply a_im * b and get the conjugate result
00346   v2 = vec_madd(a_im, b.v, p2d_ZERO);
00347   v2 = reinterpret_cast<Packet2d>(vec_sld(reinterpret_cast<Packet4ui>(v2), reinterpret_cast<Packet4ui>(v2), 8));
00348   v2 = pxor(v2, reinterpret_cast<Packet2d>(p2ul_CONJ_XOR1));
00349 
00350   return Packet1cd(padd<Packet2d>(v1, v2));
00351 }
00352 
00353 template<> EIGEN_STRONG_INLINE Packet1cd pand   <Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(pand(a.v,b.v)); }
00354 template<> EIGEN_STRONG_INLINE Packet1cd por    <Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(por(a.v,b.v)); }
00355 template<> EIGEN_STRONG_INLINE Packet1cd pxor   <Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(pxor(a.v,b.v)); }
00356 template<> EIGEN_STRONG_INLINE Packet1cd pandnot<Packet1cd>(const Packet1cd& a, const Packet1cd& b) { return Packet1cd(pandnot(a.v, b.v)); }
00357 
00358 template<> EIGEN_STRONG_INLINE Packet1cd ploaddup<Packet1cd>(const std::complex<double>*     from)  { return pset1<Packet1cd>(*from); }
00359 
00360 template<> EIGEN_STRONG_INLINE void prefetch<std::complex<double> >(const std::complex<double> * addr)    { EIGEN_PPC_PREFETCH(addr); }
00361 
00362 template<> EIGEN_STRONG_INLINE std::complex<double>  pfirst<Packet1cd>(const Packet1cd& a)
00363 {
00364   std::complex<double> EIGEN_ALIGN16 res[2];
00365   pstore<std::complex<double> >(res, a);
00366 
00367   return res[0];
00368 }
00369 
00370 template<> EIGEN_STRONG_INLINE Packet1cd preverse(const Packet1cd& a) { return a; }
00371 
00372 template<> EIGEN_STRONG_INLINE std::complex<double> predux<Packet1cd>(const Packet1cd& a) { return pfirst(a); }
00373 template<> EIGEN_STRONG_INLINE Packet1cd preduxp<Packet1cd>(const Packet1cd* vecs)        { return vecs[0]; }
00374 
00375 template<> EIGEN_STRONG_INLINE std::complex<double> predux_mul<Packet1cd>(const Packet1cd& a) { return pfirst(a); }
00376 
00377 template<int Offset>
00378 struct palign_impl<Offset,Packet1cd>
00379 {
00380   static EIGEN_STRONG_INLINE void run(Packet1cd& /*first*/, const Packet1cd& /*second*/)
00381   {
00382     // FIXME is it sure we never have to align a Packet1cd?
00383     // Even though a std::complex<double> has 16 bytes, it is not necessarily aligned on a 16 bytes boundary...
00384   }
00385 };
00386 
00387 template<> struct conj_helper<Packet1cd, Packet1cd, false,true>
00388 {
00389   EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
00390   { return padd(pmul(x,y),c); }
00391 
00392   EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
00393   {
00394     return internal::pmul(a, pconj(b));
00395   }
00396 };
00397 
00398 template<> struct conj_helper<Packet1cd, Packet1cd, true,false>
00399 {
00400   EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
00401   { return padd(pmul(x,y),c); }
00402 
00403   EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
00404   {
00405     return internal::pmul(pconj(a), b);
00406   }
00407 };
00408 
00409 template<> struct conj_helper<Packet1cd, Packet1cd, true,true>
00410 {
00411   EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet1cd& y, const Packet1cd& c) const
00412   { return padd(pmul(x,y),c); }
00413 
00414   EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) const
00415   {
00416     return pconj(internal::pmul(a, b));
00417   }
00418 };
00419 template<> struct conj_helper<Packet2d, Packet1cd, false,false>
00420 {
00421   EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet2d& x, const Packet1cd& y, const Packet1cd& c) const
00422   { return padd(c, pmul(x,y)); }
00423 
00424   EIGEN_STRONG_INLINE Packet1cd pmul(const Packet2d& x, const Packet1cd& y) const
00425   { return Packet1cd(internal::pmul<Packet2d>(x, y.v)); }
00426 };
00427 
00428 template<> struct conj_helper<Packet1cd, Packet2d, false,false>
00429 {
00430   EIGEN_STRONG_INLINE Packet1cd pmadd(const Packet1cd& x, const Packet2d& y, const Packet1cd& c) const
00431   { return padd(c, pmul(x,y)); }
00432 
00433   EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& x, const Packet2d& y) const
00434   { return Packet1cd(internal::pmul<Packet2d>(x.v, y)); }
00435 };
00436 
00437 template<> EIGEN_STRONG_INLINE Packet1cd pdiv<Packet1cd>(const Packet1cd& a, const Packet1cd& b)
00438 {
00439   // TODO optimize it for AltiVec
00440   Packet1cd res = conj_helper<Packet1cd,Packet1cd,false,true>().pmul(a,b);
00441   Packet2d s = pmul<Packet2d>(b.v, b.v);
00442   return Packet1cd(pdiv(res.v, padd<Packet2d>(s, vec_perm(s, s, p16uc_REVERSE64))));
00443 }
00444 
00445 EIGEN_STRONG_INLINE Packet1cd pcplxflip/*<Packet1cd>*/(const Packet1cd& x)
00446 {
00447   return Packet1cd(preverse(Packet2d(x.v)));
00448 }
00449 
00450 EIGEN_STRONG_INLINE void ptranspose(PacketBlock<Packet1cd,2>& kernel)
00451 {
00452   Packet2d tmp = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_HI);
00453   kernel.packet[1].v = vec_perm(kernel.packet[0].v, kernel.packet[1].v, p16uc_TRANSPOSE64_LO);
00454   kernel.packet[0].v = tmp;
00455 }
00456 #endif // __VSX__
00457 } // end namespace internal
00458 
00459 } // end namespace Eigen
00460 
00461 #endif // EIGEN_COMPLEX32_ALTIVEC_H
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends