GenericPacketMath.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
00006 //
00007 // Eigen is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public
00009 // License as published by the Free Software Foundation; either
00010 // version 3 of the License, or (at your option) any later version.
00011 //
00012 // Alternatively, you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public License as
00014 // published by the Free Software Foundation; either version 2 of
00015 // the License, or (at your option) any later version.
00016 //
00017 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00018 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00019 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00020 // GNU General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License and a copy of the GNU General Public License along with
00024 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00025 
00026 #ifndef EIGEN_GENERIC_PACKET_MATH_H
00027 #define EIGEN_GENERIC_PACKET_MATH_H
00028 
00029 namespace Eigen {
00030 
00031 namespace internal {
00032 
00041 #ifndef EIGEN_DEBUG_ALIGNED_LOAD
00042 #define EIGEN_DEBUG_ALIGNED_LOAD
00043 #endif
00044 
00045 #ifndef EIGEN_DEBUG_UNALIGNED_LOAD
00046 #define EIGEN_DEBUG_UNALIGNED_LOAD
00047 #endif
00048 
00049 #ifndef EIGEN_DEBUG_ALIGNED_STORE
00050 #define EIGEN_DEBUG_ALIGNED_STORE
00051 #endif
00052 
00053 #ifndef EIGEN_DEBUG_UNALIGNED_STORE
00054 #define EIGEN_DEBUG_UNALIGNED_STORE
00055 #endif
00056 
00057 struct default_packet_traits
00058 {
00059   enum {
00060     HasAdd    = 1,
00061     HasSub    = 1,
00062     HasMul    = 1,
00063     HasNegate = 1,
00064     HasAbs    = 1,
00065     HasAbs2   = 1,
00066     HasMin    = 1,
00067     HasMax    = 1,
00068     HasConj   = 1,
00069     HasSetLinear = 1,
00070 
00071     HasDiv    = 0,
00072     HasSqrt   = 0,
00073     HasExp    = 0,
00074     HasLog    = 0,
00075     HasPow    = 0,
00076 
00077     HasSin    = 0,
00078     HasCos    = 0,
00079     HasTan    = 0,
00080     HasASin   = 0,
00081     HasACos   = 0,
00082     HasATan   = 0
00083   };
00084 };
00085 
00086 template<typename T> struct packet_traits : default_packet_traits
00087 {
00088   typedef T type;
00089   enum {
00090     Vectorizable = 0,
00091     size = 1,
00092     AlignedOnScalar = 0
00093   };
00094   enum {
00095     HasAdd    = 0,
00096     HasSub    = 0,
00097     HasMul    = 0,
00098     HasNegate = 0,
00099     HasAbs    = 0,
00100     HasAbs2   = 0,
00101     HasMin    = 0,
00102     HasMax    = 0,
00103     HasConj   = 0,
00104     HasSetLinear = 0
00105   };
00106 };
00107 
00109 template<typename Packet> inline Packet
00110 padd(const Packet& a,
00111         const Packet& b) { return a+b; }
00112 
00114 template<typename Packet> inline Packet
00115 psub(const Packet& a,
00116         const Packet& b) { return a-b; }
00117 
00119 template<typename Packet> inline Packet
00120 pnegate(const Packet& a) { return -a; }
00121 
00123 template<typename Packet> inline Packet
00124 pconj(const Packet& a) { return conj(a); }
00125 
00127 template<typename Packet> inline Packet
00128 pmul(const Packet& a,
00129         const Packet& b) { return a*b; }
00130 
00132 template<typename Packet> inline Packet
00133 pdiv(const Packet& a,
00134         const Packet& b) { return a/b; }
00135 
00137 template<typename Packet> inline Packet
00138 pmin(const Packet& a,
00139         const Packet& b) { using std::min; return (min)(a, b); }
00140 
00142 template<typename Packet> inline Packet
00143 pmax(const Packet& a,
00144         const Packet& b) { using std::max; return (max)(a, b); }
00145 
00147 template<typename Packet> inline Packet
00148 pabs(const Packet& a) { return abs(a); }
00149 
00151 template<typename Packet> inline Packet
00152 pand(const Packet& a, const Packet& b) { return a & b; }
00153 
00155 template<typename Packet> inline Packet
00156 por(const Packet& a, const Packet& b) { return a | b; }
00157 
00159 template<typename Packet> inline Packet
00160 pxor(const Packet& a, const Packet& b) { return a ^ b; }
00161 
00163 template<typename Packet> inline Packet
00164 pandnot(const Packet& a, const Packet& b) { return a & (!b); }
00165 
00167 template<typename Packet> inline Packet
00168 pload(const typename unpacket_traits<Packet>::type* from) { return *from; }
00169 
00171 template<typename Packet> inline Packet
00172 ploadu(const typename unpacket_traits<Packet>::type* from) { return *from; }
00173 
00175 template<typename Packet> inline Packet
00176 ploaddup(const typename unpacket_traits<Packet>::type* from) { return *from; }
00177 
00179 template<typename Packet> inline Packet
00180 pset1(const typename unpacket_traits<Packet>::type& a) { return a; }
00181 
00183 template<typename Scalar> inline typename packet_traits<Scalar>::type
00184 plset(const Scalar& a) { return a; }
00185 
00187 template<typename Scalar, typename Packet> inline void pstore(Scalar* to, const Packet& from)
00188 { (*to) = from; }
00189 
00191 template<typename Scalar, typename Packet> inline void pstoreu(Scalar* to, const Packet& from)
00192 { (*to) = from; }
00193 
00195 template<typename Scalar> inline void prefetch(const Scalar* addr)
00196 {
00197 #if !defined(_MSC_VER)
00198 __builtin_prefetch(addr);
00199 #endif
00200 }
00201 
00203 template<typename Packet> inline typename unpacket_traits<Packet>::type pfirst(const Packet& a)
00204 { return a; }
00205 
00207 template<typename Packet> inline Packet
00208 preduxp(const Packet* vecs) { return vecs[0]; }
00209 
00211 template<typename Packet> inline typename unpacket_traits<Packet>::type predux(const Packet& a)
00212 { return a; }
00213 
00215 template<typename Packet> inline typename unpacket_traits<Packet>::type predux_mul(const Packet& a)
00216 { return a; }
00217 
00219 template<typename Packet> inline typename unpacket_traits<Packet>::type predux_min(const Packet& a)
00220 { return a; }
00221 
00223 template<typename Packet> inline typename unpacket_traits<Packet>::type predux_max(const Packet& a)
00224 { return a; }
00225 
00227 template<typename Packet> inline Packet preverse(const Packet& a)
00228 { return a; }
00229 
00230 
00232 template<typename Packet> inline Packet pcplxflip(const Packet& a)
00233 { return Packet(imag(a),real(a)); }
00234 
00235 /**************************
00236 * Special math functions
00237 ***************************/
00238 
00240 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00241 Packet psin(const Packet& a) { return sin(a); }
00242 
00244 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00245 Packet pcos(const Packet& a) { return cos(a); }
00246 
00248 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00249 Packet ptan(const Packet& a) { return tan(a); }
00250 
00252 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00253 Packet pasin(const Packet& a) { return asin(a); }
00254 
00256 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00257 Packet pacos(const Packet& a) { return acos(a); }
00258 
00260 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00261 Packet pexp(const Packet& a) { return exp(a); }
00262 
00264 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00265 Packet plog(const Packet& a) { return log(a); }
00266 
00268 template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS
00269 Packet psqrt(const Packet& a) { return sqrt(a); }
00270 
00271 /***************************************************************************
00272 * The following functions might not have to be overwritten for vectorized types
00273 ***************************************************************************/
00274 
00276 // NOTE: this function must really be templated on the packet type (think about different packet types for the same scalar type)
00277 template<typename Packet>
00278 inline void pstore1(typename unpacket_traits<Packet>::type* to, const typename unpacket_traits<Packet>::type& a)
00279 {
00280   pstore(to, pset1<Packet>(a));
00281 }
00282 
00284 template<typename Packet> inline Packet
00285 pmadd(const Packet&  a,
00286          const Packet&  b,
00287          const Packet&  c)
00288 { return padd(pmul(a, b),c); }
00289 
00292 template<typename Packet, int LoadMode>
00293 inline Packet ploadt(const typename unpacket_traits<Packet>::type* from)
00294 {
00295   if(LoadMode == Aligned)
00296     return pload<Packet>(from);
00297   else
00298     return ploadu<Packet>(from);
00299 }
00300 
00303 template<typename Scalar, typename Packet, int LoadMode>
00304 inline void pstoret(Scalar* to, const Packet& from)
00305 {
00306   if(LoadMode == Aligned)
00307     pstore(to, from);
00308   else
00309     pstoreu(to, from);
00310 }
00311 
00313 template<int Offset,typename PacketType>
00314 struct palign_impl
00315 {
00316   // by default data are aligned, so there is nothing to be done :)
00317   static inline void run(PacketType&, const PacketType&) {}
00318 };
00319 
00322 template<int Offset,typename PacketType>
00323 inline void palign(PacketType& first, const PacketType& second)
00324 {
00325   palign_impl<Offset,PacketType>::run(first,second);
00326 }
00327 
00328 /***************************************************************************
00329 * Fast complex products (GCC generates a function call which is very slow)
00330 ***************************************************************************/
00331 
00332 template<> inline std::complex<float> pmul(const std::complex<float>& a, const std::complex<float>& b)
00333 { return std::complex<float>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); }
00334 
00335 template<> inline std::complex<double> pmul(const std::complex<double>& a, const std::complex<double>& b)
00336 { return std::complex<double>(real(a)*real(b) - imag(a)*imag(b), imag(a)*real(b) + real(a)*imag(b)); }
00337 
00338 } // end namespace internal
00339 
00340 } // end namespace Eigen
00341 
00342 #endif // EIGEN_GENERIC_PACKET_MATH_H
00343