MOAB
4.9.3pre
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008-2009 Gael Guennebaud <[email protected]> 00005 // Copyright (C) 2006-2008 Benoit Jacob <[email protected]> 00006 // 00007 // This Source Code Form is subject to the terms of the Mozilla 00008 // Public License v. 2.0. If a copy of the MPL was not distributed 00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00010 00011 #ifndef EIGEN_ORTHOMETHODS_H 00012 #define EIGEN_ORTHOMETHODS_H 00013 00014 namespace Eigen { 00015 00027 template<typename Derived> 00028 template<typename OtherDerived> 00029 #ifndef EIGEN_PARSED_BY_DOXYGEN 00030 inline typename MatrixBase<Derived>::template cross_product_return_type<OtherDerived>::type 00031 #else 00032 inline typename MatrixBase<Derived>::PlainObject 00033 #endif 00034 MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const 00035 { 00036 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,3) 00037 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3) 00038 00039 // Note that there is no need for an expression here since the compiler 00040 // optimize such a small temporary very well (even within a complex expression) 00041 typename internal::nested_eval<Derived,2>::type lhs(derived()); 00042 typename internal::nested_eval<OtherDerived,2>::type rhs(other.derived()); 00043 return typename cross_product_return_type<OtherDerived>::type( 00044 numext::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)), 00045 numext::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)), 00046 numext::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)) 00047 ); 00048 } 00049 00050 namespace internal { 00051 00052 template< int Arch,typename VectorLhs,typename VectorRhs, 00053 typename Scalar = typename VectorLhs::Scalar, 00054 bool Vectorizable = bool((VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit)> 00055 struct cross3_impl { 00056 static inline typename internal::plain_matrix_type<VectorLhs>::type 00057 run(const VectorLhs& lhs, const VectorRhs& rhs) 00058 { 00059 return typename internal::plain_matrix_type<VectorLhs>::type( 00060 numext::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)), 00061 numext::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)), 00062 numext::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)), 00063 0 00064 ); 00065 } 00066 }; 00067 00068 } 00069 00079 template<typename Derived> 00080 template<typename OtherDerived> 00081 inline typename MatrixBase<Derived>::PlainObject 00082 MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const 00083 { 00084 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,4) 00085 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,4) 00086 00087 typedef typename internal::nested_eval<Derived,2>::type DerivedNested; 00088 typedef typename internal::nested_eval<OtherDerived,2>::type OtherDerivedNested; 00089 DerivedNested lhs(derived()); 00090 OtherDerivedNested rhs(other.derived()); 00091 00092 return internal::cross3_impl<Architecture::Target, 00093 typename internal::remove_all<DerivedNested>::type, 00094 typename internal::remove_all<OtherDerivedNested>::type>::run(lhs,rhs); 00095 } 00096 00106 template<typename ExpressionType, int Direction> 00107 template<typename OtherDerived> 00108 const typename VectorwiseOp<ExpressionType,Direction>::CrossReturnType 00109 VectorwiseOp<ExpressionType,Direction>::cross(const MatrixBase<OtherDerived>& other) const 00110 { 00111 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3) 00112 EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value), 00113 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) 00114 00115 typename internal::nested_eval<ExpressionType,2>::type mat(_expression()); 00116 typename internal::nested_eval<OtherDerived,2>::type vec(other.derived()); 00117 00118 CrossReturnType res(_expression().rows(),_expression().cols()); 00119 if(Direction==Vertical) 00120 { 00121 eigen_assert(CrossReturnType::RowsAtCompileTime==3 && "the matrix must have exactly 3 rows"); 00122 res.row(0) = (mat.row(1) * vec.coeff(2) - mat.row(2) * vec.coeff(1)).conjugate(); 00123 res.row(1) = (mat.row(2) * vec.coeff(0) - mat.row(0) * vec.coeff(2)).conjugate(); 00124 res.row(2) = (mat.row(0) * vec.coeff(1) - mat.row(1) * vec.coeff(0)).conjugate(); 00125 } 00126 else 00127 { 00128 eigen_assert(CrossReturnType::ColsAtCompileTime==3 && "the matrix must have exactly 3 columns"); 00129 res.col(0) = (mat.col(1) * vec.coeff(2) - mat.col(2) * vec.coeff(1)).conjugate(); 00130 res.col(1) = (mat.col(2) * vec.coeff(0) - mat.col(0) * vec.coeff(2)).conjugate(); 00131 res.col(2) = (mat.col(0) * vec.coeff(1) - mat.col(1) * vec.coeff(0)).conjugate(); 00132 } 00133 return res; 00134 } 00135 00136 namespace internal { 00137 00138 template<typename Derived, int Size = Derived::SizeAtCompileTime> 00139 struct unitOrthogonal_selector 00140 { 00141 typedef typename plain_matrix_type<Derived>::type VectorType; 00142 typedef typename traits<Derived>::Scalar Scalar; 00143 typedef typename NumTraits<Scalar>::Real RealScalar; 00144 typedef Matrix<Scalar,2,1> Vector2; 00145 EIGEN_DEVICE_FUNC 00146 static inline VectorType run(const Derived& src) 00147 { 00148 VectorType perp = VectorType::Zero(src.size()); 00149 Index maxi = 0; 00150 Index sndi = 0; 00151 src.cwiseAbs().maxCoeff(&maxi); 00152 if (maxi==0) 00153 sndi = 1; 00154 RealScalar invnm = RealScalar(1)/(Vector2() << src.coeff(sndi),src.coeff(maxi)).finished().norm(); 00155 perp.coeffRef(maxi) = -numext::conj(src.coeff(sndi)) * invnm; 00156 perp.coeffRef(sndi) = numext::conj(src.coeff(maxi)) * invnm; 00157 00158 return perp; 00159 } 00160 }; 00161 00162 template<typename Derived> 00163 struct unitOrthogonal_selector<Derived,3> 00164 { 00165 typedef typename plain_matrix_type<Derived>::type VectorType; 00166 typedef typename traits<Derived>::Scalar Scalar; 00167 typedef typename NumTraits<Scalar>::Real RealScalar; 00168 EIGEN_DEVICE_FUNC 00169 static inline VectorType run(const Derived& src) 00170 { 00171 VectorType perp; 00172 /* Let us compute the crossed product of *this with a vector 00173 * that is not too close to being colinear to *this. 00174 */ 00175 00176 /* unless the x and y coords are both close to zero, we can 00177 * simply take ( -y, x, 0 ) and normalize it. 00178 */ 00179 if((!isMuchSmallerThan(src.x(), src.z())) 00180 || (!isMuchSmallerThan(src.y(), src.z()))) 00181 { 00182 RealScalar invnm = RealScalar(1)/src.template head<2>().norm(); 00183 perp.coeffRef(0) = -numext::conj(src.y())*invnm; 00184 perp.coeffRef(1) = numext::conj(src.x())*invnm; 00185 perp.coeffRef(2) = 0; 00186 } 00187 /* if both x and y are close to zero, then the vector is close 00188 * to the z-axis, so it's far from colinear to the x-axis for instance. 00189 * So we take the crossed product with (1,0,0) and normalize it. 00190 */ 00191 else 00192 { 00193 RealScalar invnm = RealScalar(1)/src.template tail<2>().norm(); 00194 perp.coeffRef(0) = 0; 00195 perp.coeffRef(1) = -numext::conj(src.z())*invnm; 00196 perp.coeffRef(2) = numext::conj(src.y())*invnm; 00197 } 00198 00199 return perp; 00200 } 00201 }; 00202 00203 template<typename Derived> 00204 struct unitOrthogonal_selector<Derived,2> 00205 { 00206 typedef typename plain_matrix_type<Derived>::type VectorType; 00207 EIGEN_DEVICE_FUNC 00208 static inline VectorType run(const Derived& src) 00209 { return VectorType(-numext::conj(src.y()), numext::conj(src.x())).normalized(); } 00210 }; 00211 00212 } // end namespace internal 00213 00223 template<typename Derived> 00224 typename MatrixBase<Derived>::PlainObject 00225 MatrixBase<Derived>::unitOrthogonal() const 00226 { 00227 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) 00228 return internal::unitOrthogonal_selector<Derived>::run(derived()); 00229 } 00230 00231 } // end namespace Eigen 00232 00233 #endif // EIGEN_ORTHOMETHODS_H