// This file is part of Eigen, a lightweight C++ template library // for linear algebra. Eigen itself is part of the KDE project. // // Copyright (C) 2006-2008 Benoit Jacob // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 3 of the License, or (at your option) any later version. // // Alternatively, you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License and a copy of the GNU General Public License along with // Eigen. If not, see . #ifndef EIGEN_DOT_H #define EIGEN_DOT_H template struct ei_dot_unroller { inline static void run(const Derived1 &v1, const Derived2& v2, typename Derived1::Scalar &dot) { ei_dot_unroller::run(v1, v2, dot); dot += v1.coeff(Index) * ei_conj(v2.coeff(Index)); } }; template struct ei_dot_unroller<0, Size, Derived1, Derived2> { inline static void run(const Derived1 &v1, const Derived2& v2, typename Derived1::Scalar &dot) { dot = v1.coeff(0) * ei_conj(v2.coeff(0)); } }; template struct ei_dot_unroller { inline static void run(const Derived1&, const Derived2&, typename Derived1::Scalar&) {} }; // prevent buggy user code from causing an infinite recursion template struct ei_dot_unroller { inline static void run(const Derived1&, const Derived2&, typename Derived1::Scalar&) {} }; /** \returns the dot product of *this with other. * * \only_for_vectors * * \note If the scalar type is complex numbers, then this function returns the hermitian * (sesquilinear) dot product, linear in the first variable and anti-linear in the * second variable. * * \sa norm2(), norm() */ template template typename ei_traits::Scalar MatrixBase::dot(const MatrixBase& other) const { typedef typename Derived::Nested Nested; typedef typename OtherDerived::Nested OtherNested; typedef typename ei_unref::type _Nested; typedef typename ei_unref::type _OtherNested; Nested nested(derived()); OtherNested otherNested(other.derived()); ei_assert(_Nested::IsVectorAtCompileTime && _OtherNested::IsVectorAtCompileTime && nested.size() == otherNested.size()); Scalar res; const bool unroll = SizeAtCompileTime * (_Nested::CoeffReadCost + _OtherNested::CoeffReadCost + NumTraits::MulCost) + (int(SizeAtCompileTime) - 1) * NumTraits::AddCost <= EIGEN_UNROLLING_LIMIT; if(unroll) ei_dot_unroller ::run(nested, otherNested, res); else { res = nested.coeff(0) * ei_conj(otherNested.coeff(0)); for(int i = 1; i < size(); i++) res += nested.coeff(i)* ei_conj(otherNested.coeff(i)); } return res; } /** \returns the squared norm of *this, i.e. the dot product of *this with itself. * * \only_for_vectors * * \sa dot(), norm() */ template inline typename NumTraits::Scalar>::Real MatrixBase::norm2() const { return ei_real(dot(*this)); } /** \returns the norm of *this, i.e. the square root of the dot product of *this with itself. * * \only_for_vectors * * \sa dot(), norm2() */ template inline typename NumTraits::Scalar>::Real MatrixBase::norm() const { return ei_sqrt(norm2()); } /** \returns an expression of the quotient of *this by its own norm. * * \only_for_vectors * * \sa norm() */ template inline const typename MatrixBase::ScalarMultipleReturnType MatrixBase::normalized() const { return (*this) * (RealScalar(1)/norm()); } /** \returns true if *this is approximately orthogonal to \a other, * within the precision given by \a prec. * * Example: \include MatrixBase_isOrtho_vector.cpp * Output: \verbinclude MatrixBase_isOrtho_vector.out */ template template bool MatrixBase::isOrtho (const MatrixBase& other, RealScalar prec) const { typename ei_nested::type nested(derived()); typename ei_nested::type otherNested(other.derived()); return ei_abs2(nested.dot(otherNested)) <= prec * prec * nested.norm2() * otherNested.norm2(); } /** \returns true if *this is approximately an unitary matrix, * within the precision given by \a prec. In the case where the \a Scalar * type is real numbers, a unitary matrix is an orthogonal matrix, whence the name. * * \note This can be used to check whether a family of vectors forms an orthonormal basis. * Indeed, \c m.isOrtho() returns true if and only if the columns of m form an * orthonormal basis. * * Example: \include MatrixBase_isOrtho_matrix.cpp * Output: \verbinclude MatrixBase_isOrtho_matrix.out */ template bool MatrixBase::isOrtho(RealScalar prec) const { typename Derived::Nested nested(derived()); for(int i = 0; i < cols(); i++) { if(!ei_isApprox(nested.col(i).norm2(), static_cast(1), prec)) return false; for(int j = 0; j < i; j++) if(!ei_isMuchSmallerThan(nested.col(i).dot(nested.col(j)), static_cast(1), prec)) return false; } return true; } #endif // EIGEN_DOT_H