Main MRPT website > C++ reference
MRPT logo

Functors.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-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // Eigen is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 3 of the License, or (at your option) any later version.
00010 //
00011 // Alternatively, you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License as
00013 // published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00017 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License and a copy of the GNU General Public License along with
00023 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00024 
00025 #ifndef EIGEN_FUNCTORS_H
00026 #define EIGEN_FUNCTORS_H
00027 
00028 namespace internal {
00029 
00030 // associative functors:
00031 
00032 /** \internal
00033   * \brief Template functor to compute the sum of two scalars
00034   *
00035   * \sa class CwiseBinaryOp, MatrixBase::operator+, class VectorwiseOp, MatrixBase::sum()
00036   */
00037 template<typename Scalar> struct scalar_sum_op {
00038   EIGEN_EMPTY_STRUCT_CTOR(scalar_sum_op)
00039   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a + b; }
00040   template<typename Packet>
00041   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00042   { return internal::padd(a,b); }
00043   template<typename Packet>
00044   EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
00045   { return internal::predux(a); }
00046 };
00047 template<typename Scalar>
00048 struct functor_traits<scalar_sum_op<Scalar> > {
00049   enum {
00050     Cost = NumTraits<Scalar>::AddCost,
00051     PacketAccess = packet_traits<Scalar>::HasAdd
00052   };
00053 };
00054 
00055 /** \internal
00056   * \brief Template functor to compute the product of two scalars
00057   *
00058   * \sa class CwiseBinaryOp, Cwise::operator*(), class VectorwiseOp, MatrixBase::redux()
00059   */
00060 template<typename LhsScalar,typename RhsScalar> struct scalar_product_op {
00061   enum {
00062     Vectorizable = is_same<LhsScalar,RhsScalar>::value && packet_traits<LhsScalar>::HasMul && packet_traits<RhsScalar>::HasMul
00063   };
00064   typedef typename scalar_product_traits<LhsScalar,RhsScalar>::ReturnType result_type;
00065   EIGEN_EMPTY_STRUCT_CTOR(scalar_product_op)
00066   EIGEN_STRONG_INLINE const result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a * b; }
00067   template<typename Packet>
00068   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00069   { return internal::pmul(a,b); }
00070   template<typename Packet>
00071   EIGEN_STRONG_INLINE const result_type predux(const Packet& a) const
00072   { return internal::predux_mul(a); }
00073 };
00074 template<typename LhsScalar,typename RhsScalar>
00075 struct functor_traits<scalar_product_op<LhsScalar,RhsScalar> > {
00076   enum {
00077     Cost = (NumTraits<LhsScalar>::MulCost + NumTraits<RhsScalar>::MulCost)/2, // rough estimate!
00078     PacketAccess = scalar_product_op<LhsScalar,RhsScalar>::Vectorizable
00079   };
00080 };
00081 
00082 /** \internal
00083   * \brief Template functor to compute the conjugate product of two scalars
00084   *
00085   * This is a short cut for conj(x) * y which is needed for optimization purpose
00086   */
00087 template<typename Scalar> struct scalar_conj_product_op {
00088   enum { Conj = NumTraits<Scalar>::IsComplex };
00089   EIGEN_EMPTY_STRUCT_CTOR(scalar_conj_product_op)
00090   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const
00091   { return conj_helper<Scalar,Scalar,Conj,false>().pmul(a,b); }
00092   template<typename Packet>
00093   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00094   { return conj_helper<Packet,Packet,Conj,false>().pmul(a,b); }
00095 };
00096 template<typename Scalar>
00097 struct functor_traits<scalar_conj_product_op<Scalar> > {
00098   enum {
00099     Cost = NumTraits<Scalar>::MulCost,
00100     PacketAccess = packet_traits<Scalar>::HasMul
00101   };
00102 };
00103 
00104 /** \internal
00105   * \brief Template functor to compute the min of two scalars
00106   *
00107   * \sa class CwiseBinaryOp, MatrixBase::cwiseMin, class VectorwiseOp, MatrixBase::minCoeff()
00108   */
00109 template<typename Scalar> struct scalar_min_op {
00110   EIGEN_EMPTY_STRUCT_CTOR(scalar_min_op)
00111   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::min(a, b); }
00112   template<typename Packet>
00113   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00114   { return internal::pmin(a,b); }
00115   template<typename Packet>
00116   EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
00117   { return internal::predux_min(a); }
00118 };
00119 template<typename Scalar>
00120 struct functor_traits<scalar_min_op<Scalar> > {
00121   enum {
00122     Cost = NumTraits<Scalar>::AddCost,
00123     PacketAccess = packet_traits<Scalar>::HasMin
00124   };
00125 };
00126 
00127 /** \internal
00128   * \brief Template functor to compute the max of two scalars
00129   *
00130   * \sa class CwiseBinaryOp, MatrixBase::cwiseMax, class VectorwiseOp, MatrixBase::maxCoeff()
00131   */
00132 template<typename Scalar> struct scalar_max_op {
00133   EIGEN_EMPTY_STRUCT_CTOR(scalar_max_op)
00134   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return std::max(a, b); }
00135   template<typename Packet>
00136   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00137   { return internal::pmax(a,b); }
00138   template<typename Packet>
00139   EIGEN_STRONG_INLINE const Scalar predux(const Packet& a) const
00140   { return internal::predux_max(a); }
00141 };
00142 template<typename Scalar>
00143 struct functor_traits<scalar_max_op<Scalar> > {
00144   enum {
00145     Cost = NumTraits<Scalar>::AddCost,
00146     PacketAccess = packet_traits<Scalar>::HasMax
00147   };
00148 };
00149 
00150 /** \internal
00151   * \brief Template functor to compute the hypot of two scalars
00152   *
00153   * \sa MatrixBase::stableNorm(), class Redux
00154   */
00155 template<typename Scalar> struct scalar_hypot_op {
00156   EIGEN_EMPTY_STRUCT_CTOR(scalar_hypot_op)
00157 //   typedef typename NumTraits<Scalar>::Real result_type;
00158   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& _x, const Scalar& _y) const
00159   {
00160     Scalar p = std::max(_x, _y);
00161     Scalar q = std::min(_x, _y);
00162     Scalar qp = q/p;
00163     return p * sqrt(Scalar(1) + qp*qp);
00164   }
00165 };
00166 template<typename Scalar>
00167 struct functor_traits<scalar_hypot_op<Scalar> > {
00168   enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess=0 };
00169 };
00170 
00171 // other binary functors:
00172 
00173 /** \internal
00174   * \brief Template functor to compute the difference of two scalars
00175   *
00176   * \sa class CwiseBinaryOp, MatrixBase::operator-
00177   */
00178 template<typename Scalar> struct scalar_difference_op {
00179   EIGEN_EMPTY_STRUCT_CTOR(scalar_difference_op)
00180   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a - b; }
00181   template<typename Packet>
00182   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00183   { return internal::psub(a,b); }
00184 };
00185 template<typename Scalar>
00186 struct functor_traits<scalar_difference_op<Scalar> > {
00187   enum {
00188     Cost = NumTraits<Scalar>::AddCost,
00189     PacketAccess = packet_traits<Scalar>::HasSub
00190   };
00191 };
00192 
00193 /** \internal
00194   * \brief Template functor to compute the quotient of two scalars
00195   *
00196   * \sa class CwiseBinaryOp, Cwise::operator/()
00197   */
00198 template<typename Scalar> struct scalar_quotient_op {
00199   EIGEN_EMPTY_STRUCT_CTOR(scalar_quotient_op)
00200   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& b) const { return a / b; }
00201   template<typename Packet>
00202   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
00203   { return internal::pdiv(a,b); }
00204 };
00205 template<typename Scalar>
00206 struct functor_traits<scalar_quotient_op<Scalar> > {
00207   enum {
00208     Cost = 2 * NumTraits<Scalar>::MulCost,
00209     PacketAccess = packet_traits<Scalar>::HasDiv
00210   };
00211 };
00212 
00213 // unary functors:
00214 
00215 /** \internal
00216   * \brief Template functor to compute the opposite of a scalar
00217   *
00218   * \sa class CwiseUnaryOp, MatrixBase::operator-
00219   */
00220 template<typename Scalar> struct scalar_opposite_op {
00221   EIGEN_EMPTY_STRUCT_CTOR(scalar_opposite_op)
00222   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return -a; }
00223   template<typename Packet>
00224   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
00225   { return internal::pnegate(a); }
00226 };
00227 template<typename Scalar>
00228 struct functor_traits<scalar_opposite_op<Scalar> >
00229 { enum {
00230     Cost = NumTraits<Scalar>::AddCost,
00231     PacketAccess = packet_traits<Scalar>::HasNegate };
00232 };
00233 
00234 /** \internal
00235   * \brief Template functor to compute the absolute value of a scalar
00236   *
00237   * \sa class CwiseUnaryOp, Cwise::abs
00238   */
00239 template<typename Scalar> struct scalar_abs_op {
00240   EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op)
00241   typedef typename NumTraits<Scalar>::Real result_type;
00242   EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return abs(a); }
00243   template<typename Packet>
00244   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
00245   { return internal::pabs(a); }
00246 };
00247 template<typename Scalar>
00248 struct functor_traits<scalar_abs_op<Scalar> >
00249 {
00250   enum {
00251     Cost = NumTraits<Scalar>::AddCost,
00252     PacketAccess = packet_traits<Scalar>::HasAbs
00253   };
00254 };
00255 
00256 /** \internal
00257   * \brief Template functor to compute the squared absolute value of a scalar
00258   *
00259   * \sa class CwiseUnaryOp, Cwise::abs2
00260   */
00261 template<typename Scalar> struct scalar_abs2_op {
00262   EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op)
00263   typedef typename NumTraits<Scalar>::Real result_type;
00264   EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return abs2(a); }
00265   template<typename Packet>
00266   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
00267   { return internal::pmul(a,a); }
00268 };
00269 template<typename Scalar>
00270 struct functor_traits<scalar_abs2_op<Scalar> >
00271 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasAbs2 }; };
00272 
00273 /** \internal
00274   * \brief Template functor to compute the conjugate of a complex value
00275   *
00276   * \sa class CwiseUnaryOp, MatrixBase::conjugate()
00277   */
00278 template<typename Scalar> struct scalar_conjugate_op {
00279   EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op)
00280   EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return conj(a); }
00281   template<typename Packet>
00282   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); }
00283 };
00284 template<typename Scalar>
00285 struct functor_traits<scalar_conjugate_op<Scalar> >
00286 {
00287   enum {
00288     Cost = NumTraits<Scalar>::IsComplex ? NumTraits<Scalar>::AddCost : 0,
00289     PacketAccess = packet_traits<Scalar>::HasConj
00290   };
00291 };
00292 
00293 /** \internal
00294   * \brief Template functor to cast a scalar to another type
00295   *
00296   * \sa class CwiseUnaryOp, MatrixBase::cast()
00297   */
00298 template<typename Scalar, typename NewType>
00299 struct scalar_cast_op {
00300   EIGEN_EMPTY_STRUCT_CTOR(scalar_cast_op)
00301   typedef NewType result_type;
00302   EIGEN_STRONG_INLINE const NewType operator() (const Scalar& a) const { return cast<Scalar, NewType>(a); }
00303 };
00304 template<typename Scalar, typename NewType>
00305 struct functor_traits<scalar_cast_op<Scalar,NewType> >
00306 { enum { Cost = is_same<Scalar, NewType>::value ? 0 : NumTraits<NewType>::AddCost, PacketAccess = false }; };
00307 
00308 /** \internal
00309   * \brief Template functor to extract the real part of a complex
00310   *
00311   * \sa class CwiseUnaryOp, MatrixBase::real()
00312   */
00313 template<typename Scalar>
00314 struct scalar_real_op {
00315   EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op)
00316   typedef typename NumTraits<Scalar>::Real result_type;
00317   EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return real(a); }
00318 };
00319 template<typename Scalar>
00320 struct functor_traits<scalar_real_op<Scalar> >
00321 { enum { Cost = 0, PacketAccess = false }; };
00322 
00323 /** \internal
00324   * \brief Template functor to extract the imaginary part of a complex
00325   *
00326   * \sa class CwiseUnaryOp, MatrixBase::imag()
00327   */
00328 template<typename Scalar>
00329 struct scalar_imag_op {
00330   EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op)
00331   typedef typename NumTraits<Scalar>::Real result_type;
00332   EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return imag(a); }
00333 };
00334 template<typename Scalar>
00335 struct functor_traits<scalar_imag_op<Scalar> >
00336 { enum { Cost = 0, PacketAccess = false }; };
00337 
00338 /** \internal
00339   * \brief Template functor to extract the real part of a complex as a reference
00340   *
00341   * \sa class CwiseUnaryOp, MatrixBase::real()
00342   */
00343 template<typename Scalar>
00344 struct scalar_real_ref_op {
00345   EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op)
00346   typedef typename NumTraits<Scalar>::Real result_type;
00347   EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return real_ref(*const_cast<Scalar*>(&a)); }
00348 };
00349 template<typename Scalar>
00350 struct functor_traits<scalar_real_ref_op<Scalar> >
00351 { enum { Cost = 0, PacketAccess = false }; };
00352 
00353 /** \internal
00354   * \brief Template functor to extract the imaginary part of a complex as a reference
00355   *
00356   * \sa class CwiseUnaryOp, MatrixBase::imag()
00357   */
00358 template<typename Scalar>
00359 struct scalar_imag_ref_op {
00360   EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op)
00361   typedef typename NumTraits<Scalar>::Real result_type;
00362   EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return imag_ref(*const_cast<Scalar*>(&a)); }
00363 };
00364 template<typename Scalar>
00365 struct functor_traits<scalar_imag_ref_op<Scalar> >
00366 { enum { Cost = 0, PacketAccess = false }; };
00367 
00368 /** \internal
00369   *
00370   * \brief Template functor to compute the exponential of a scalar
00371   *
00372   * \sa class CwiseUnaryOp, Cwise::exp()
00373   */
00374 template<typename Scalar> struct scalar_exp_op {
00375   EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op)
00376   inline const Scalar operator() (const Scalar& a) const { return exp(a); }
00377   typedef typename packet_traits<Scalar>::type Packet;
00378   inline Packet packetOp(const Packet& a) const { return internal::pexp(a); }
00379 };
00380 template<typename Scalar>
00381 struct functor_traits<scalar_exp_op<Scalar> >
00382 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasExp }; };
00383 
00384 /** \internal
00385   *
00386   * \brief Template functor to compute the logarithm of a scalar
00387   *
00388   * \sa class CwiseUnaryOp, Cwise::log()
00389   */
00390 template<typename Scalar> struct scalar_log_op {
00391   EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op)
00392   inline const Scalar operator() (const Scalar& a) const { return log(a); }
00393   typedef typename packet_traits<Scalar>::type Packet;
00394   inline Packet packetOp(const Packet& a) const { return internal::plog(a); }
00395 };
00396 template<typename Scalar>
00397 struct functor_traits<scalar_log_op<Scalar> >
00398 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasLog }; };
00399 
00400 /** \internal
00401   * \brief Template functor to multiply a scalar by a fixed other one
00402   *
00403   * \sa class CwiseUnaryOp, MatrixBase::operator*, MatrixBase::operator/
00404   */
00405 /* NOTE why doing the pset1() in packetOp *is* an optimization ?
00406  * indeed it seems better to declare m_other as a Packet and do the pset1() once
00407  * in the constructor. However, in practice:
00408  *  - GCC does not like m_other as a Packet and generate a load every time it needs it
00409  *  - on the other hand GCC is able to moves the pset1() away the loop :)
00410  *  - simpler code ;)
00411  * (ICC and gcc 4.4 seems to perform well in both cases, the issue is visible with y = a*x + b*y)
00412  */
00413 template<typename Scalar>
00414 struct scalar_multiple_op {
00415   typedef typename packet_traits<Scalar>::type Packet;
00416   // FIXME default copy constructors seems bugged with std::complex<>
00417   EIGEN_STRONG_INLINE scalar_multiple_op(const scalar_multiple_op& other) : m_other(other.m_other) { }
00418   EIGEN_STRONG_INLINE scalar_multiple_op(const Scalar& other) : m_other(other) { }
00419   EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
00420   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
00421   { return internal::pmul(a, pset1<Packet>(m_other)); }
00422   typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
00423 };
00424 template<typename Scalar>
00425 struct functor_traits<scalar_multiple_op<Scalar> >
00426 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
00427 
00428 template<typename Scalar1, typename Scalar2>
00429 struct scalar_multiple2_op {
00430   typedef typename scalar_product_traits<Scalar1,Scalar2>::ReturnType result_type;
00431   EIGEN_STRONG_INLINE scalar_multiple2_op(const scalar_multiple2_op& other) : m_other(other.m_other) { }
00432   EIGEN_STRONG_INLINE scalar_multiple2_op(const Scalar2& other) : m_other(other) { }
00433   EIGEN_STRONG_INLINE result_type operator() (const Scalar1& a) const { return a * m_other; }
00434   typename add_const_on_value_type<typename NumTraits<Scalar2>::Nested>::type m_other;
00435 };
00436 template<typename Scalar1,typename Scalar2>
00437 struct functor_traits<scalar_multiple2_op<Scalar1,Scalar2> >
00438 { enum { Cost = NumTraits<Scalar1>::MulCost, PacketAccess = false }; };
00439 
00440 template<typename Scalar, bool IsInteger>
00441 struct scalar_quotient1_impl {
00442   typedef typename packet_traits<Scalar>::type Packet;
00443   // FIXME default copy constructors seems bugged with std::complex<>
00444   EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
00445   EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(static_cast<Scalar>(1) / other) {}
00446   EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a * m_other; }
00447   EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const
00448   { return internal::pmul(a, pset1<Packet>(m_other)); }
00449   const Scalar m_other;
00450 };
00451 template<typename Scalar>
00452 struct functor_traits<scalar_quotient1_impl<Scalar,false> >
00453 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
00454 
00455 template<typename Scalar>
00456 struct scalar_quotient1_impl<Scalar,true> {
00457   // FIXME default copy constructors seems bugged with std::complex<>
00458   EIGEN_STRONG_INLINE scalar_quotient1_impl(const scalar_quotient1_impl& other) : m_other(other.m_other) { }
00459   EIGEN_STRONG_INLINE scalar_quotient1_impl(const Scalar& other) : m_other(other) {}
00460   EIGEN_STRONG_INLINE Scalar operator() (const Scalar& a) const { return a / m_other; }
00461   typename add_const_on_value_type<typename NumTraits<Scalar>::Nested>::type m_other;
00462 };
00463 template<typename Scalar>
00464 struct functor_traits<scalar_quotient1_impl<Scalar,true> >
00465 { enum { Cost = 2 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
00466 
00467 /** \internal
00468   * \brief Template functor to divide a scalar by a fixed other one
00469   *
00470   * This functor is used to implement the quotient of a matrix by
00471   * a scalar where the scalar type is not necessarily a floating point type.
00472   *
00473   * \sa class CwiseUnaryOp, MatrixBase::operator/
00474   */
00475 template<typename Scalar>
00476 struct scalar_quotient1_op : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger > {
00477   EIGEN_STRONG_INLINE scalar_quotient1_op(const Scalar& other)
00478     : scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger >(other) {}
00479 };
00480 template<typename Scalar>
00481 struct functor_traits<scalar_quotient1_op<Scalar> >
00482 : functor_traits<scalar_quotient1_impl<Scalar, NumTraits<Scalar>::IsInteger> >
00483 {};
00484 
00485 // nullary functors
00486 
00487 template<typename Scalar>
00488 struct scalar_constant_op {
00489   typedef typename packet_traits<Scalar>::type Packet;
00490   EIGEN_STRONG_INLINE scalar_constant_op(const scalar_constant_op& other) : m_other(other.m_other) { }
00491   EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) { }
00492   template<typename Index>
00493   EIGEN_STRONG_INLINE const Scalar operator() (Index, Index = 0) const { return m_other; }
00494   template<typename Index>
00495   EIGEN_STRONG_INLINE const Packet packetOp(Index, Index = 0) const { return internal::pset1<Packet>(m_other); }
00496   const Scalar m_other;
00497 };
00498 template<typename Scalar>
00499 struct functor_traits<scalar_constant_op<Scalar> >
00500 // FIXME replace this packet test by a safe one
00501 { enum { Cost = 1, PacketAccess = packet_traits<Scalar>::Vectorizable, IsRepeatable = true }; };
00502 
00503 template<typename Scalar> struct scalar_identity_op {
00504   EIGEN_EMPTY_STRUCT_CTOR(scalar_identity_op)
00505   template<typename Index>
00506   EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const { return row==col ? Scalar(1) : Scalar(0); }
00507 };
00508 template<typename Scalar>
00509 struct functor_traits<scalar_identity_op<Scalar> >
00510 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true }; };
00511 
00512 template <typename Scalar, bool RandomAccess> struct linspaced_op_impl;
00513 
00514 // linear access for packet ops:
00515 // 1) initialization
00516 //   base = [low, ..., low] + ([step, ..., step] * [-size, ..., 0])
00517 // 2) each step
00518 //   base += [size*step, ..., size*step]
00519 template <typename Scalar>
00520 struct linspaced_op_impl<Scalar,false>
00521 {
00522   typedef typename packet_traits<Scalar>::type Packet;
00523 
00524   linspaced_op_impl(Scalar low, Scalar step) :
00525   m_low(low), m_step(step),
00526   m_packetStep(pset1<Packet>(packet_traits<Scalar>::size*step)),
00527   m_base(padd(pset1<Packet>(low),pmul(pset1<Packet>(step),plset<Scalar>(-packet_traits<Scalar>::size)))) {}
00528 
00529   template<typename Index>
00530   EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
00531   template<typename Index>
00532   EIGEN_STRONG_INLINE const Packet packetOp(Index) const { return m_base = padd(m_base,m_packetStep); }
00533 
00534   const Scalar m_low;
00535   const Scalar m_step;
00536   const Packet m_packetStep;
00537   mutable Packet m_base;
00538 };
00539 
00540 // random access for packet ops:
00541 // 1) each step
00542 //   [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
00543 template <typename Scalar>
00544 struct linspaced_op_impl<Scalar,true>
00545 {
00546   typedef typename packet_traits<Scalar>::type Packet;
00547 
00548   linspaced_op_impl(Scalar low, Scalar step) :
00549   m_low(low), m_step(step),
00550   m_lowPacket(pset1<Packet>(m_low)), m_stepPacket(pset1<Packet>(m_step)), m_interPacket(plset<Scalar>(0)) {}
00551 
00552   template<typename Index>
00553   EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return m_low+i*m_step; }
00554 
00555   template<typename Index>
00556   EIGEN_STRONG_INLINE const Packet packetOp(Index i) const
00557   { return internal::padd(m_lowPacket, pmul(m_stepPacket, padd(pset1<Packet>(i),m_interPacket))); }
00558 
00559   const Scalar m_low;
00560   const Scalar m_step;
00561   const Packet m_lowPacket;
00562   const Packet m_stepPacket;
00563   const Packet m_interPacket;
00564 };
00565 
00566 // ----- Linspace functor ----------------------------------------------------------------
00567 
00568 // Forward declaration (we default to random access which does not really give
00569 // us a speed gain when using packet access but it allows to use the functor in
00570 // nested expressions).
00571 template <typename Scalar, bool RandomAccess = true> struct linspaced_op;
00572 template <typename Scalar, bool RandomAccess> struct functor_traits< linspaced_op<Scalar,RandomAccess> >
00573 { enum { Cost = 1, PacketAccess = packet_traits<Scalar>::HasSetLinear, IsRepeatable = true }; };
00574 template <typename Scalar, bool RandomAccess> struct linspaced_op
00575 {
00576   typedef typename packet_traits<Scalar>::type Packet;
00577   linspaced_op(Scalar low, Scalar high, int num_steps) : impl(low, (high-low)/(num_steps-1)) {}
00578 
00579   template<typename Index>
00580   EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); }
00581 
00582   // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
00583   // there row==0 and col is used for the actual iteration.
00584   template<typename Index>
00585   EIGEN_STRONG_INLINE const Scalar operator() (Index row, Index col) const 
00586   {
00587     eigen_assert(col==0 || row==0);
00588     return impl(col + row);
00589   }
00590 
00591   template<typename Index>
00592   EIGEN_STRONG_INLINE const Packet packetOp(Index i) const { return impl.packetOp(i); }
00593 
00594   // We need this function when assigning e.g. a RowVectorXd to a MatrixXd since
00595   // there row==0 and col is used for the actual iteration.
00596   template<typename Index>
00597   EIGEN_STRONG_INLINE const Packet packetOp(Index row, Index col) const
00598   {
00599     eigen_assert(col==0 || row==0);
00600     return impl(col + row);
00601   }
00602 
00603   // This proxy object handles the actual required temporaries, the different
00604   // implementations (random vs. sequential access) as well as the
00605   // correct piping to size 2/4 packet operations.
00606   const linspaced_op_impl<Scalar,RandomAccess> impl;
00607 };
00608 
00609 // all functors allow linear access, except scalar_identity_op. So we fix here a quick meta
00610 // to indicate whether a functor allows linear access, just always answering 'yes' except for
00611 // scalar_identity_op.
00612 // FIXME move this to functor_traits adding a functor_default
00613 template<typename Functor> struct functor_has_linear_access { enum { ret = 1 }; };
00614 template<typename Scalar> struct functor_has_linear_access<scalar_identity_op<Scalar> > { enum { ret = 0 }; };
00615 
00616 // in CwiseBinaryOp, we require the Lhs and Rhs to have the same scalar type, except for multiplication
00617 // where we only require them to have the same _real_ scalar type so one may multiply, say, float by complex<float>.
00618 // FIXME move this to functor_traits adding a functor_default
00619 template<typename Functor> struct functor_allows_mixing_real_and_complex { enum { ret = 0 }; };
00620 template<typename LhsScalar,typename RhsScalar> struct functor_allows_mixing_real_and_complex<scalar_product_op<LhsScalar,RhsScalar> > { enum { ret = 1 }; };
00621 
00622 
00623 /** \internal
00624   * \brief Template functor to add a scalar to a fixed other one
00625   * \sa class CwiseUnaryOp, Array::operator+
00626   */
00627 /* If you wonder why doing the pset1() in packetOp() is an optimization check scalar_multiple_op */
00628 template<typename Scalar>
00629 struct scalar_add_op {
00630   typedef typename packet_traits<Scalar>::type Packet;
00631   // FIXME default copy constructors seems bugged with std::complex<>
00632   inline scalar_add_op(const scalar_add_op& other) : m_other(other.m_other) { }
00633   inline scalar_add_op(const Scalar& other) : m_other(other) { }
00634   inline Scalar operator() (const Scalar& a) const { return a + m_other; }
00635   inline const Packet packetOp(const Packet& a) const
00636   { return internal::padd(a, pset1<Packet>(m_other)); }
00637   const Scalar m_other;
00638 };
00639 template<typename Scalar>
00640 struct functor_traits<scalar_add_op<Scalar> >
00641 { enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasAdd }; };
00642 
00643 /** \internal
00644   * \brief Template functor to compute the square root of a scalar
00645   * \sa class CwiseUnaryOp, Cwise::sqrt()
00646   */
00647 template<typename Scalar> struct scalar_sqrt_op {
00648   EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op)
00649   inline const Scalar operator() (const Scalar& a) const { return sqrt(a); }
00650   typedef typename packet_traits<Scalar>::type Packet;
00651   inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); }
00652 };
00653 template<typename Scalar>
00654 struct functor_traits<scalar_sqrt_op<Scalar> >
00655 { enum {
00656     Cost = 5 * NumTraits<Scalar>::MulCost,
00657     PacketAccess = packet_traits<Scalar>::HasSqrt
00658   };
00659 };
00660 
00661 /** \internal
00662   * \brief Template functor to compute the cosine of a scalar
00663   * \sa class CwiseUnaryOp, Cwise::cos()
00664   */
00665 template<typename Scalar> struct scalar_cos_op {
00666   EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op)
00667   inline Scalar operator() (const Scalar& a) const { return cos(a); }
00668   typedef typename packet_traits<Scalar>::type Packet;
00669   inline Packet packetOp(const Packet& a) const { return internal::pcos(a); }
00670 };
00671 template<typename Scalar>
00672 struct functor_traits<scalar_cos_op<Scalar> >
00673 {
00674   enum {
00675     Cost = 5 * NumTraits<Scalar>::MulCost,
00676     PacketAccess = packet_traits<Scalar>::HasCos
00677   };
00678 };
00679 
00680 /** \internal
00681   * \brief Template functor to compute the sine of a scalar
00682   * \sa class CwiseUnaryOp, Cwise::sin()
00683   */
00684 template<typename Scalar> struct scalar_sin_op {
00685   EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op)
00686   inline const Scalar operator() (const Scalar& a) const { return sin(a); }
00687   typedef typename packet_traits<Scalar>::type Packet;
00688   inline Packet packetOp(const Packet& a) const { return internal::psin(a); }
00689 };
00690 template<typename Scalar>
00691 struct functor_traits<scalar_sin_op<Scalar> >
00692 {
00693   enum {
00694     Cost = 5 * NumTraits<Scalar>::MulCost,
00695     PacketAccess = packet_traits<Scalar>::HasSin
00696   };
00697 };
00698 
00699 /** \internal
00700   * \brief Template functor to raise a scalar to a power
00701   * \sa class CwiseUnaryOp, Cwise::pow
00702   */
00703 template<typename Scalar>
00704 struct scalar_pow_op {
00705   // FIXME default copy constructors seems bugged with std::complex<>
00706   inline scalar_pow_op(const scalar_pow_op& other) : m_exponent(other.m_exponent) { }
00707   inline scalar_pow_op(const Scalar& exponent) : m_exponent(exponent) {}
00708   inline Scalar operator() (const Scalar& a) const { return internal::pow(a, m_exponent); }
00709   const Scalar m_exponent;
00710 };
00711 template<typename Scalar>
00712 struct functor_traits<scalar_pow_op<Scalar> >
00713 { enum { Cost = 5 * NumTraits<Scalar>::MulCost, PacketAccess = false }; };
00714 
00715 /** \internal
00716   * \brief Template functor to compute the inverse of a scalar
00717   * \sa class CwiseUnaryOp, Cwise::inverse()
00718   */
00719 template<typename Scalar>
00720 struct scalar_inverse_op {
00721   EIGEN_EMPTY_STRUCT_CTOR(scalar_inverse_op)
00722   inline Scalar operator() (const Scalar& a) const { return Scalar(1)/a; }
00723   template<typename Packet>
00724   inline const Packet packetOp(const Packet& a) const
00725   { return internal::pdiv(pset1<Packet>(Scalar(1)),a); }
00726 };
00727 template<typename Scalar>
00728 struct functor_traits<scalar_inverse_op<Scalar> >
00729 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasDiv }; };
00730 
00731 /** \internal
00732   * \brief Template functor to compute the square of a scalar
00733   * \sa class CwiseUnaryOp, Cwise::square()
00734   */
00735 template<typename Scalar>
00736 struct scalar_square_op {
00737   EIGEN_EMPTY_STRUCT_CTOR(scalar_square_op)
00738   inline Scalar operator() (const Scalar& a) const { return a*a; }
00739   template<typename Packet>
00740   inline const Packet packetOp(const Packet& a) const
00741   { return internal::pmul(a,a); }
00742 };
00743 template<typename Scalar>
00744 struct functor_traits<scalar_square_op<Scalar> >
00745 { enum { Cost = NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
00746 
00747 /** \internal
00748   * \brief Template functor to compute the cube of a scalar
00749   * \sa class CwiseUnaryOp, Cwise::cube()
00750   */
00751 template<typename Scalar>
00752 struct scalar_cube_op {
00753   EIGEN_EMPTY_STRUCT_CTOR(scalar_cube_op)
00754   inline Scalar operator() (const Scalar& a) const { return a*a*a; }
00755   template<typename Packet>
00756   inline const Packet packetOp(const Packet& a) const
00757   { return internal::pmul(a,pmul(a,a)); }
00758 };
00759 template<typename Scalar>
00760 struct functor_traits<scalar_cube_op<Scalar> >
00761 { enum { Cost = 2*NumTraits<Scalar>::MulCost, PacketAccess = packet_traits<Scalar>::HasMul }; };
00762 
00763 // default functor traits for STL functors:
00764 
00765 template<typename T>
00766 struct functor_traits<std::multiplies<T> >
00767 { enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
00768 
00769 template<typename T>
00770 struct functor_traits<std::divides<T> >
00771 { enum { Cost = NumTraits<T>::MulCost, PacketAccess = false }; };
00772 
00773 template<typename T>
00774 struct functor_traits<std::plus<T> >
00775 { enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
00776 
00777 template<typename T>
00778 struct functor_traits<std::minus<T> >
00779 { enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
00780 
00781 template<typename T>
00782 struct functor_traits<std::negate<T> >
00783 { enum { Cost = NumTraits<T>::AddCost, PacketAccess = false }; };
00784 
00785 template<typename T>
00786 struct functor_traits<std::logical_or<T> >
00787 { enum { Cost = 1, PacketAccess = false }; };
00788 
00789 template<typename T>
00790 struct functor_traits<std::logical_and<T> >
00791 { enum { Cost = 1, PacketAccess = false }; };
00792 
00793 template<typename T>
00794 struct functor_traits<std::logical_not<T> >
00795 { enum { Cost = 1, PacketAccess = false }; };
00796 
00797 template<typename T>
00798 struct functor_traits<std::greater<T> >
00799 { enum { Cost = 1, PacketAccess = false }; };
00800 
00801 template<typename T>
00802 struct functor_traits<std::less<T> >
00803 { enum { Cost = 1, PacketAccess = false }; };
00804 
00805 template<typename T>
00806 struct functor_traits<std::greater_equal<T> >
00807 { enum { Cost = 1, PacketAccess = false }; };
00808 
00809 template<typename T>
00810 struct functor_traits<std::less_equal<T> >
00811 { enum { Cost = 1, PacketAccess = false }; };
00812 
00813 template<typename T>
00814 struct functor_traits<std::equal_to<T> >
00815 { enum { Cost = 1, PacketAccess = false }; };
00816 
00817 template<typename T>
00818 struct functor_traits<std::not_equal_to<T> >
00819 { enum { Cost = 1, PacketAccess = false }; };
00820 
00821 template<typename T>
00822 struct functor_traits<std::binder2nd<T> >
00823 { enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
00824 
00825 template<typename T>
00826 struct functor_traits<std::binder1st<T> >
00827 { enum { Cost = functor_traits<T>::Cost, PacketAccess = false }; };
00828 
00829 template<typename T>
00830 struct functor_traits<std::unary_negate<T> >
00831 { enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
00832 
00833 template<typename T>
00834 struct functor_traits<std::binary_negate<T> >
00835 { enum { Cost = 1 + functor_traits<T>::Cost, PacketAccess = false }; };
00836 
00837 #ifdef EIGEN_STDEXT_SUPPORT
00838 
00839 template<typename T0,typename T1>
00840 struct functor_traits<std::project1st<T0,T1> >
00841 { enum { Cost = 0, PacketAccess = false }; };
00842 
00843 template<typename T0,typename T1>
00844 struct functor_traits<std::project2nd<T0,T1> >
00845 { enum { Cost = 0, PacketAccess = false }; };
00846 
00847 template<typename T0,typename T1>
00848 struct functor_traits<std::select2nd<std::pair<T0,T1> > >
00849 { enum { Cost = 0, PacketAccess = false }; };
00850 
00851 template<typename T0,typename T1>
00852 struct functor_traits<std::select1st<std::pair<T0,T1> > >
00853 { enum { Cost = 0, PacketAccess = false }; };
00854 
00855 template<typename T0,typename T1>
00856 struct functor_traits<std::unary_compose<T0,T1> >
00857 { enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost, PacketAccess = false }; };
00858 
00859 template<typename T0,typename T1,typename T2>
00860 struct functor_traits<std::binary_compose<T0,T1,T2> >
00861 { enum { Cost = functor_traits<T0>::Cost + functor_traits<T1>::Cost + functor_traits<T2>::Cost, PacketAccess = false }; };
00862 
00863 #endif // EIGEN_STDEXT_SUPPORT
00864 
00865 // allow to add new functors and specializations of functor_traits from outside Eigen.
00866 // this macro is really needed because functor_traits must be specialized after it is declared but before it is used...
00867 #ifdef EIGEN_FUNCTORS_PLUGIN
00868 #include EIGEN_FUNCTORS_PLUGIN
00869 #endif
00870 
00871 } // end namespace internal
00872 
00873 #endif // EIGEN_FUNCTORS_H



Page generated by Doxygen 1.7.3 for MRPT 0.9.4 SVN:exported at Tue Jan 25 21:56:31 UTC 2011