MOAB  4.9.3pre
Dot.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) 2006-2008, 2010 Benoit Jacob <[email protected]>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_DOT_H
00011 #define EIGEN_DOT_H
00012 
00013 namespace Eigen { 
00014 
00015 namespace internal {
00016 
00017 // helper function for dot(). The problem is that if we put that in the body of dot(), then upon calling dot
00018 // with mismatched types, the compiler emits errors about failing to instantiate cwiseProduct BEFORE
00019 // looking at the static assertions. Thus this is a trick to get better compile errors.
00020 template<typename T, typename U,
00021 // the NeedToTranspose condition here is taken straight from Assign.h
00022          bool NeedToTranspose = T::IsVectorAtCompileTime
00023                 && U::IsVectorAtCompileTime
00024                 && ((int(T::RowsAtCompileTime) == 1 && int(U::ColsAtCompileTime) == 1)
00025                       |  // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
00026                          // revert to || as soon as not needed anymore.
00027                     (int(T::ColsAtCompileTime) == 1 && int(U::RowsAtCompileTime) == 1))
00028 >
00029 struct dot_nocheck
00030 {
00031   typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
00032   EIGEN_DEVICE_FUNC
00033   static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
00034   {
00035     return a.template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
00036   }
00037 };
00038 
00039 template<typename T, typename U>
00040 struct dot_nocheck<T, U, true>
00041 {
00042   typedef typename scalar_product_traits<typename traits<T>::Scalar,typename traits<U>::Scalar>::ReturnType ResScalar;
00043   EIGEN_DEVICE_FUNC
00044   static inline ResScalar run(const MatrixBase<T>& a, const MatrixBase<U>& b)
00045   {
00046     return a.transpose().template binaryExpr<scalar_conj_product_op<typename traits<T>::Scalar,typename traits<U>::Scalar> >(b).sum();
00047   }
00048 };
00049 
00050 } // end namespace internal
00051 
00062 template<typename Derived>
00063 template<typename OtherDerived>
00064 EIGEN_DEVICE_FUNC
00065 typename internal::scalar_product_traits<typename internal::traits<Derived>::Scalar,typename internal::traits<OtherDerived>::Scalar>::ReturnType
00066 MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
00067 {
00068   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
00069   EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived)
00070   EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived,OtherDerived)
00071   typedef internal::scalar_conj_product_op<Scalar,typename OtherDerived::Scalar> func;
00072   EIGEN_CHECK_BINARY_COMPATIBILIY(func,Scalar,typename OtherDerived::Scalar);
00073 
00074   eigen_assert(size() == other.size());
00075 
00076   return internal::dot_nocheck<Derived,OtherDerived>::run(*this, other);
00077 }
00078 
00079 //---------- implementation of L2 norm and related functions ----------
00080 
00087 template<typename Derived>
00088 EIGEN_STRONG_INLINE typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::squaredNorm() const
00089 {
00090   return numext::real((*this).cwiseAbs2().sum());
00091 }
00092 
00099 template<typename Derived>
00100 inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
00101 {
00102   return numext::sqrt(squaredNorm());
00103 }
00104 
00114 template<typename Derived>
00115 inline const typename MatrixBase<Derived>::PlainObject
00116 MatrixBase<Derived>::normalized() const
00117 {
00118   typedef typename internal::nested_eval<Derived,2>::type _Nested;
00119   _Nested n(derived());
00120   RealScalar z = n.squaredNorm();
00121   // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
00122   if(z>RealScalar(0))
00123     return n / numext::sqrt(z);
00124   else
00125     return n;
00126 }
00127 
00136 template<typename Derived>
00137 inline void MatrixBase<Derived>::normalize()
00138 {
00139   RealScalar z = squaredNorm();
00140   // NOTE: after extensive benchmarking, this conditional does not impact performance, at least on recent x86 CPU
00141   if(z>RealScalar(0))
00142     derived() /= numext::sqrt(z);
00143 }
00144 
00157 template<typename Derived>
00158 inline const typename MatrixBase<Derived>::PlainObject
00159 MatrixBase<Derived>::stableNormalized() const
00160 {
00161   typedef typename internal::nested_eval<Derived,3>::type _Nested;
00162   _Nested n(derived());
00163   RealScalar w = n.cwiseAbs().maxCoeff();
00164   RealScalar z = (n/w).squaredNorm();
00165   if(z>RealScalar(0))
00166     return n / (numext::sqrt(z)*w);
00167   else
00168     return n;
00169 }
00170 
00182 template<typename Derived>
00183 inline void MatrixBase<Derived>::stableNormalize()
00184 {
00185   RealScalar w = cwiseAbs().maxCoeff();
00186   RealScalar z = (derived()/w).squaredNorm();
00187   if(z>RealScalar(0))
00188     derived() /= numext::sqrt(z)*w;
00189 }
00190 
00191 //---------- implementation of other norms ----------
00192 
00193 namespace internal {
00194 
00195 template<typename Derived, int p>
00196 struct lpNorm_selector
00197 {
00198   typedef typename NumTraits<typename traits<Derived>::Scalar>::Real RealScalar;
00199   EIGEN_DEVICE_FUNC
00200   static inline RealScalar run(const MatrixBase<Derived>& m)
00201   {
00202     EIGEN_USING_STD_MATH(pow)
00203     return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p);
00204   }
00205 };
00206 
00207 template<typename Derived>
00208 struct lpNorm_selector<Derived, 1>
00209 {
00210   EIGEN_DEVICE_FUNC
00211   static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
00212   {
00213     return m.cwiseAbs().sum();
00214   }
00215 };
00216 
00217 template<typename Derived>
00218 struct lpNorm_selector<Derived, 2>
00219 {
00220   EIGEN_DEVICE_FUNC
00221   static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
00222   {
00223     return m.norm();
00224   }
00225 };
00226 
00227 template<typename Derived>
00228 struct lpNorm_selector<Derived, Infinity>
00229 {
00230   EIGEN_DEVICE_FUNC
00231   static inline typename NumTraits<typename traits<Derived>::Scalar>::Real run(const MatrixBase<Derived>& m)
00232   {
00233     return m.cwiseAbs().maxCoeff();
00234   }
00235 };
00236 
00237 } // end namespace internal
00238 
00247 template<typename Derived>
00248 template<int p>
00249 #ifndef EIGEN_PARSED_BY_DOXYGEN
00250 inline typename NumTraits<typename internal::traits<Derived>::Scalar>::Real
00251 #else
00252 MatrixBase<Derived>::RealScalar
00253 #endif
00254 MatrixBase<Derived>::lpNorm() const
00255 {
00256   return internal::lpNorm_selector<Derived, p>::run(*this);
00257 }
00258 
00259 //---------- implementation of isOrthogonal / isUnitary ----------
00260 
00267 template<typename Derived>
00268 template<typename OtherDerived>
00269 bool MatrixBase<Derived>::isOrthogonal
00270 (const MatrixBase<OtherDerived>& other, const RealScalar& prec) const
00271 {
00272   typename internal::nested_eval<Derived,2>::type nested(derived());
00273   typename internal::nested_eval<OtherDerived,2>::type otherNested(other.derived());
00274   return numext::abs2(nested.dot(otherNested)) <= prec * prec * nested.squaredNorm() * otherNested.squaredNorm();
00275 }
00276 
00288 template<typename Derived>
00289 bool MatrixBase<Derived>::isUnitary(const RealScalar& prec) const
00290 {
00291   typename internal::nested_eval<Derived,1>::type self(derived());
00292   for(Index i = 0; i < cols(); ++i)
00293   {
00294     if(!internal::isApprox(self.col(i).squaredNorm(), static_cast<RealScalar>(1), prec))
00295       return false;
00296     for(Index j = 0; j < i; ++j)
00297       if(!internal::isMuchSmallerThan(self.col(i).dot(self.col(j)), static_cast<Scalar>(1), prec))
00298         return false;
00299   }
00300   return true;
00301 }
00302 
00303 } // end namespace Eigen
00304 
00305 #endif // EIGEN_DOT_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines