MOAB
4.9.3pre
|
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