1 2 // This file is part of Eigen, a lightweight C++ template library 3 // for linear algebra. 4 // 5 // Copyright (C) 2017 Gael Guennebaud <[email protected]> 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_ARCH_CONJ_HELPER_H 12 #define EIGEN_ARCH_CONJ_HELPER_H 13 14 #define EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PACKET_CPLX, PACKET_REAL) \ 15 template <> \ 16 struct conj_helper<PACKET_REAL, PACKET_CPLX, false, false> { \ 17 EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_REAL& x, \ 18 const PACKET_CPLX& y, \ 19 const PACKET_CPLX& c) const { \ 20 return padd(c, this->pmul(x, y)); \ 21 } \ 22 EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_REAL& x, \ 23 const PACKET_CPLX& y) const { \ 24 return PACKET_CPLX(Eigen::internal::pmul<PACKET_REAL>(x, y.v)); \ 25 } \ 26 }; \ 27 \ 28 template <> \ 29 struct conj_helper<PACKET_CPLX, PACKET_REAL, false, false> { \ 30 EIGEN_STRONG_INLINE PACKET_CPLX pmadd(const PACKET_CPLX& x, \ 31 const PACKET_REAL& y, \ 32 const PACKET_CPLX& c) const { \ 33 return padd(c, this->pmul(x, y)); \ 34 } \ 35 EIGEN_STRONG_INLINE PACKET_CPLX pmul(const PACKET_CPLX& x, \ 36 const PACKET_REAL& y) const { \ 37 return PACKET_CPLX(Eigen::internal::pmul<PACKET_REAL>(x.v, y)); \ 38 } \ 39 }; 40 41 namespace Eigen { 42 namespace internal { 43 44 template<bool Conjugate> struct conj_if; 45 46 template<> struct conj_if<true> { 47 template<typename T> 48 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T& x) const { return numext::conj(x); } 49 template<typename T> 50 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T pconj(const T& x) const { return internal::pconj(x); } 51 }; 52 53 template<> struct conj_if<false> { 54 template<typename T> 55 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& operator()(const T& x) const { return x; } 56 template<typename T> 57 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& pconj(const T& x) const { return x; } 58 }; 59 60 // Generic Implementation, assume scalars since the packet-version is 61 // specialized below. 62 template<typename LhsType, typename RhsType, bool ConjLhs, bool ConjRhs> 63 struct conj_helper { 64 typedef typename ScalarBinaryOpTraits<LhsType, RhsType>::ReturnType ResultType; 65 66 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType 67 pmadd(const LhsType& x, const RhsType& y, const ResultType& c) const 68 { return this->pmul(x, y) + c; } 69 70 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType 71 pmul(const LhsType& x, const RhsType& y) const 72 { return conj_if<ConjLhs>()(x) * conj_if<ConjRhs>()(y); } 73 }; 74 75 template<typename LhsScalar, typename RhsScalar> 76 struct conj_helper<LhsScalar, RhsScalar, true, true> { 77 typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar>::ReturnType ResultType; 78 79 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType 80 pmadd(const LhsScalar& x, const RhsScalar& y, const ResultType& c) const 81 { return this->pmul(x, y) + c; } 82 83 // We save a conjuation by using the identity conj(a)*conj(b) = conj(a*b). 84 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType 85 pmul(const LhsScalar& x, const RhsScalar& y) const 86 { return numext::conj(x * y); } 87 }; 88 89 // Implementation with equal type, use packet operations. 90 template<typename Packet, bool ConjLhs, bool ConjRhs> 91 struct conj_helper<Packet, Packet, ConjLhs, ConjRhs> 92 { 93 typedef Packet ResultType; 94 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmadd(const Packet& x, const Packet& y, const Packet& c) const 95 { return Eigen::internal::pmadd(conj_if<ConjLhs>().pconj(x), conj_if<ConjRhs>().pconj(y), c); } 96 97 98 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmul(const Packet& x, const Packet& y) const 99 { return Eigen::internal::pmul(conj_if<ConjLhs>().pconj(x), conj_if<ConjRhs>().pconj(y)); } 100 }; 101 102 template<typename Packet> 103 struct conj_helper<Packet, Packet, true, true> 104 { 105 typedef Packet ResultType; 106 107 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmadd(const Packet& x, const Packet& y, const Packet& c) const 108 { return Eigen::internal::pmadd(pconj(x), pconj(y), c); } 109 // We save a conjuation by using the identity conj(a)*conj(b) = conj(a*b). 110 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet pmul(const Packet& x, const Packet& y) const 111 { return pconj(Eigen::internal::pmul(x, y)); } 112 }; 113 114 } // namespace internal 115 } // namespace Eigen 116 117 #endif // EIGEN_ARCH_CONJ_HELPER_H 118