diff options
Diffstat (limited to 'eigen/unsupported/Eigen/src')
68 files changed, 0 insertions, 20423 deletions
diff --git a/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h b/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h deleted file mode 100644 index 33b6c39..0000000 --- a/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h +++ /dev/null @@ -1,108 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_AUTODIFF_JACOBIAN_H -#define EIGEN_AUTODIFF_JACOBIAN_H - -namespace Eigen -{ - -template<typename Functor> class AutoDiffJacobian : public Functor -{ -public: - AutoDiffJacobian() : Functor() {} - AutoDiffJacobian(const Functor& f) : Functor(f) {} - - // forward constructors -#if EIGEN_HAS_VARIADIC_TEMPLATES - template<typename... T> - AutoDiffJacobian(const T& ...Values) : Functor(Values...) {} -#else - template<typename T0> - AutoDiffJacobian(const T0& a0) : Functor(a0) {} - template<typename T0, typename T1> - AutoDiffJacobian(const T0& a0, const T1& a1) : Functor(a0, a1) {} - template<typename T0, typename T1, typename T2> - AutoDiffJacobian(const T0& a0, const T1& a1, const T2& a2) : Functor(a0, a1, a2) {} -#endif - - typedef typename Functor::InputType InputType; - typedef typename Functor::ValueType ValueType; - typedef typename ValueType::Scalar Scalar; - - enum { - InputsAtCompileTime = InputType::RowsAtCompileTime, - ValuesAtCompileTime = ValueType::RowsAtCompileTime - }; - - typedef Matrix<Scalar, ValuesAtCompileTime, InputsAtCompileTime> JacobianType; - typedef typename JacobianType::Index Index; - - typedef Matrix<Scalar, InputsAtCompileTime, 1> DerivativeType; - typedef AutoDiffScalar<DerivativeType> ActiveScalar; - - typedef Matrix<ActiveScalar, InputsAtCompileTime, 1> ActiveInput; - typedef Matrix<ActiveScalar, ValuesAtCompileTime, 1> ActiveValue; - -#if EIGEN_HAS_VARIADIC_TEMPLATES - // Some compilers don't accept variadic parameters after a default parameter, - // i.e., we can't just write _jac=0 but we need to overload operator(): - EIGEN_STRONG_INLINE - void operator() (const InputType& x, ValueType* v) const - { - this->operator()(x, v, 0); - } - template<typename... ParamsType> - void operator() (const InputType& x, ValueType* v, JacobianType* _jac, - const ParamsType&... Params) const -#else - void operator() (const InputType& x, ValueType* v, JacobianType* _jac=0) const -#endif - { - eigen_assert(v!=0); - - if (!_jac) - { -#if EIGEN_HAS_VARIADIC_TEMPLATES - Functor::operator()(x, v, Params...); -#else - Functor::operator()(x, v); -#endif - return; - } - - JacobianType& jac = *_jac; - - ActiveInput ax = x.template cast<ActiveScalar>(); - ActiveValue av(jac.rows()); - - if(InputsAtCompileTime==Dynamic) - for (Index j=0; j<jac.rows(); j++) - av[j].derivatives().resize(x.rows()); - - for (Index i=0; i<jac.cols(); i++) - ax[i].derivatives() = DerivativeType::Unit(x.rows(),i); - -#if EIGEN_HAS_VARIADIC_TEMPLATES - Functor::operator()(ax, &av, Params...); -#else - Functor::operator()(ax, &av); -#endif - - for (Index i=0; i<jac.rows(); i++) - { - (*v)[i] = av[i].value(); - jac.row(i) = av[i].derivatives(); - } - } -}; - -} - -#endif // EIGEN_AUTODIFF_JACOBIAN_H diff --git a/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h b/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h deleted file mode 100644 index 2f50e99..0000000 --- a/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffScalar.h +++ /dev/null @@ -1,694 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_AUTODIFF_SCALAR_H -#define EIGEN_AUTODIFF_SCALAR_H - -namespace Eigen { - -namespace internal { - -template<typename A, typename B> -struct make_coherent_impl { - static void run(A&, B&) {} -}; - -// resize a to match b is a.size()==0, and conversely. -template<typename A, typename B> -void make_coherent(const A& a, const B&b) -{ - make_coherent_impl<A,B>::run(a.const_cast_derived(), b.const_cast_derived()); -} - -template<typename _DerType, bool Enable> struct auto_diff_special_op; - -} // end namespace internal - -template<typename _DerType> class AutoDiffScalar; - -template<typename NewDerType> -inline AutoDiffScalar<NewDerType> MakeAutoDiffScalar(const typename NewDerType::Scalar& value, const NewDerType &der) { - return AutoDiffScalar<NewDerType>(value,der); -} - -/** \class AutoDiffScalar - * \brief A scalar type replacement with automatic differentation capability - * - * \param _DerType the vector type used to store/represent the derivatives. The base scalar type - * as well as the number of derivatives to compute are determined from this type. - * Typical choices include, e.g., \c Vector4f for 4 derivatives, or \c VectorXf - * if the number of derivatives is not known at compile time, and/or, the number - * of derivatives is large. - * Note that _DerType can also be a reference (e.g., \c VectorXf&) to wrap a - * existing vector into an AutoDiffScalar. - * Finally, _DerType can also be any Eigen compatible expression. - * - * This class represents a scalar value while tracking its respective derivatives using Eigen's expression - * template mechanism. - * - * It supports the following list of global math function: - * - std::abs, std::sqrt, std::pow, std::exp, std::log, std::sin, std::cos, - * - internal::abs, internal::sqrt, numext::pow, internal::exp, internal::log, internal::sin, internal::cos, - * - internal::conj, internal::real, internal::imag, numext::abs2. - * - * AutoDiffScalar can be used as the scalar type of an Eigen::Matrix object. However, - * in that case, the expression template mechanism only occurs at the top Matrix level, - * while derivatives are computed right away. - * - */ - -template<typename _DerType> -class AutoDiffScalar - : public internal::auto_diff_special_op - <_DerType, !internal::is_same<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar, - typename NumTraits<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar>::Real>::value> -{ - public: - typedef internal::auto_diff_special_op - <_DerType, !internal::is_same<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar, - typename NumTraits<typename internal::traits<typename internal::remove_all<_DerType>::type>::Scalar>::Real>::value> Base; - typedef typename internal::remove_all<_DerType>::type DerType; - typedef typename internal::traits<DerType>::Scalar Scalar; - typedef typename NumTraits<Scalar>::Real Real; - - using Base::operator+; - using Base::operator*; - - /** Default constructor without any initialization. */ - AutoDiffScalar() {} - - /** Constructs an active scalar from its \a value, - and initializes the \a nbDer derivatives such that it corresponds to the \a derNumber -th variable */ - AutoDiffScalar(const Scalar& value, int nbDer, int derNumber) - : m_value(value), m_derivatives(DerType::Zero(nbDer)) - { - m_derivatives.coeffRef(derNumber) = Scalar(1); - } - - /** Conversion from a scalar constant to an active scalar. - * The derivatives are set to zero. */ - /*explicit*/ AutoDiffScalar(const Real& value) - : m_value(value) - { - if(m_derivatives.size()>0) - m_derivatives.setZero(); - } - - /** Constructs an active scalar from its \a value and derivatives \a der */ - AutoDiffScalar(const Scalar& value, const DerType& der) - : m_value(value), m_derivatives(der) - {} - - template<typename OtherDerType> - AutoDiffScalar(const AutoDiffScalar<OtherDerType>& other -#ifndef EIGEN_PARSED_BY_DOXYGEN - , typename internal::enable_if< - internal::is_same<Scalar, typename internal::traits<typename internal::remove_all<OtherDerType>::type>::Scalar>::value - && internal::is_convertible<OtherDerType,DerType>::value , void*>::type = 0 -#endif - ) - : m_value(other.value()), m_derivatives(other.derivatives()) - {} - - friend std::ostream & operator << (std::ostream & s, const AutoDiffScalar& a) - { - return s << a.value(); - } - - AutoDiffScalar(const AutoDiffScalar& other) - : m_value(other.value()), m_derivatives(other.derivatives()) - {} - - template<typename OtherDerType> - inline AutoDiffScalar& operator=(const AutoDiffScalar<OtherDerType>& other) - { - m_value = other.value(); - m_derivatives = other.derivatives(); - return *this; - } - - inline AutoDiffScalar& operator=(const AutoDiffScalar& other) - { - m_value = other.value(); - m_derivatives = other.derivatives(); - return *this; - } - - inline AutoDiffScalar& operator=(const Scalar& other) - { - m_value = other; - if(m_derivatives.size()>0) - m_derivatives.setZero(); - return *this; - } - -// inline operator const Scalar& () const { return m_value; } -// inline operator Scalar& () { return m_value; } - - inline const Scalar& value() const { return m_value; } - inline Scalar& value() { return m_value; } - - inline const DerType& derivatives() const { return m_derivatives; } - inline DerType& derivatives() { return m_derivatives; } - - inline bool operator< (const Scalar& other) const { return m_value < other; } - inline bool operator<=(const Scalar& other) const { return m_value <= other; } - inline bool operator> (const Scalar& other) const { return m_value > other; } - inline bool operator>=(const Scalar& other) const { return m_value >= other; } - inline bool operator==(const Scalar& other) const { return m_value == other; } - inline bool operator!=(const Scalar& other) const { return m_value != other; } - - friend inline bool operator< (const Scalar& a, const AutoDiffScalar& b) { return a < b.value(); } - friend inline bool operator<=(const Scalar& a, const AutoDiffScalar& b) { return a <= b.value(); } - friend inline bool operator> (const Scalar& a, const AutoDiffScalar& b) { return a > b.value(); } - friend inline bool operator>=(const Scalar& a, const AutoDiffScalar& b) { return a >= b.value(); } - friend inline bool operator==(const Scalar& a, const AutoDiffScalar& b) { return a == b.value(); } - friend inline bool operator!=(const Scalar& a, const AutoDiffScalar& b) { return a != b.value(); } - - template<typename OtherDerType> inline bool operator< (const AutoDiffScalar<OtherDerType>& b) const { return m_value < b.value(); } - template<typename OtherDerType> inline bool operator<=(const AutoDiffScalar<OtherDerType>& b) const { return m_value <= b.value(); } - template<typename OtherDerType> inline bool operator> (const AutoDiffScalar<OtherDerType>& b) const { return m_value > b.value(); } - template<typename OtherDerType> inline bool operator>=(const AutoDiffScalar<OtherDerType>& b) const { return m_value >= b.value(); } - template<typename OtherDerType> inline bool operator==(const AutoDiffScalar<OtherDerType>& b) const { return m_value == b.value(); } - template<typename OtherDerType> inline bool operator!=(const AutoDiffScalar<OtherDerType>& b) const { return m_value != b.value(); } - - inline const AutoDiffScalar<DerType&> operator+(const Scalar& other) const - { - return AutoDiffScalar<DerType&>(m_value + other, m_derivatives); - } - - friend inline const AutoDiffScalar<DerType&> operator+(const Scalar& a, const AutoDiffScalar& b) - { - return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives()); - } - -// inline const AutoDiffScalar<DerType&> operator+(const Real& other) const -// { -// return AutoDiffScalar<DerType&>(m_value + other, m_derivatives); -// } - -// friend inline const AutoDiffScalar<DerType&> operator+(const Real& a, const AutoDiffScalar& b) -// { -// return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives()); -// } - - inline AutoDiffScalar& operator+=(const Scalar& other) - { - value() += other; - return *this; - } - - template<typename OtherDerType> - inline const AutoDiffScalar<CwiseBinaryOp<internal::scalar_sum_op<Scalar>,const DerType,const typename internal::remove_all<OtherDerType>::type> > - operator+(const AutoDiffScalar<OtherDerType>& other) const - { - internal::make_coherent(m_derivatives, other.derivatives()); - return AutoDiffScalar<CwiseBinaryOp<internal::scalar_sum_op<Scalar>,const DerType,const typename internal::remove_all<OtherDerType>::type> >( - m_value + other.value(), - m_derivatives + other.derivatives()); - } - - template<typename OtherDerType> - inline AutoDiffScalar& - operator+=(const AutoDiffScalar<OtherDerType>& other) - { - (*this) = (*this) + other; - return *this; - } - - inline const AutoDiffScalar<DerType&> operator-(const Scalar& b) const - { - return AutoDiffScalar<DerType&>(m_value - b, m_derivatives); - } - - friend inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> > - operator-(const Scalar& a, const AutoDiffScalar& b) - { - return AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> > - (a - b.value(), -b.derivatives()); - } - - inline AutoDiffScalar& operator-=(const Scalar& other) - { - value() -= other; - return *this; - } - - template<typename OtherDerType> - inline const AutoDiffScalar<CwiseBinaryOp<internal::scalar_difference_op<Scalar>, const DerType,const typename internal::remove_all<OtherDerType>::type> > - operator-(const AutoDiffScalar<OtherDerType>& other) const - { - internal::make_coherent(m_derivatives, other.derivatives()); - return AutoDiffScalar<CwiseBinaryOp<internal::scalar_difference_op<Scalar>, const DerType,const typename internal::remove_all<OtherDerType>::type> >( - m_value - other.value(), - m_derivatives - other.derivatives()); - } - - template<typename OtherDerType> - inline AutoDiffScalar& - operator-=(const AutoDiffScalar<OtherDerType>& other) - { - *this = *this - other; - return *this; - } - - inline const AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> > - operator-() const - { - return AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>, const DerType> >( - -m_value, - -m_derivatives); - } - - inline const AutoDiffScalar<EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DerType,Scalar,product) > - operator*(const Scalar& other) const - { - return MakeAutoDiffScalar(m_value * other, m_derivatives * other); - } - - friend inline const AutoDiffScalar<EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DerType,Scalar,product) > - operator*(const Scalar& other, const AutoDiffScalar& a) - { - return MakeAutoDiffScalar(a.value() * other, a.derivatives() * other); - } - -// inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type > -// operator*(const Real& other) const -// { -// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >( -// m_value * other, -// (m_derivatives * other)); -// } -// -// friend inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type > -// operator*(const Real& other, const AutoDiffScalar& a) -// { -// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >( -// a.value() * other, -// a.derivatives() * other); -// } - - inline const AutoDiffScalar<EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DerType,Scalar,product) > - operator/(const Scalar& other) const - { - return MakeAutoDiffScalar(m_value / other, (m_derivatives * (Scalar(1)/other))); - } - - friend inline const AutoDiffScalar<EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DerType,Scalar,product) > - operator/(const Scalar& other, const AutoDiffScalar& a) - { - return MakeAutoDiffScalar(other / a.value(), a.derivatives() * (Scalar(-other) / (a.value()*a.value()))); - } - -// inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type > -// operator/(const Real& other) const -// { -// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >( -// m_value / other, -// (m_derivatives * (Real(1)/other))); -// } -// -// friend inline const AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type > -// operator/(const Real& other, const AutoDiffScalar& a) -// { -// return AutoDiffScalar<typename CwiseUnaryOp<internal::scalar_multiple_op<Real>, DerType>::Type >( -// other / a.value(), -// a.derivatives() * (-Real(1)/other)); -// } - - template<typename OtherDerType> - inline const AutoDiffScalar<EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE( - CwiseBinaryOp<internal::scalar_difference_op<Scalar> EIGEN_COMMA - const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DerType,Scalar,product) EIGEN_COMMA - const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(typename internal::remove_all<OtherDerType>::type,Scalar,product) >,Scalar,product) > - operator/(const AutoDiffScalar<OtherDerType>& other) const - { - internal::make_coherent(m_derivatives, other.derivatives()); - return MakeAutoDiffScalar( - m_value / other.value(), - ((m_derivatives * other.value()) - (other.derivatives() * m_value)) - * (Scalar(1)/(other.value()*other.value()))); - } - - template<typename OtherDerType> - inline const AutoDiffScalar<CwiseBinaryOp<internal::scalar_sum_op<Scalar>, - const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(DerType,Scalar,product), - const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(typename internal::remove_all<OtherDerType>::type,Scalar,product) > > - operator*(const AutoDiffScalar<OtherDerType>& other) const - { - internal::make_coherent(m_derivatives, other.derivatives()); - return MakeAutoDiffScalar( - m_value * other.value(), - (m_derivatives * other.value()) + (other.derivatives() * m_value)); - } - - inline AutoDiffScalar& operator*=(const Scalar& other) - { - *this = *this * other; - return *this; - } - - template<typename OtherDerType> - inline AutoDiffScalar& operator*=(const AutoDiffScalar<OtherDerType>& other) - { - *this = *this * other; - return *this; - } - - inline AutoDiffScalar& operator/=(const Scalar& other) - { - *this = *this / other; - return *this; - } - - template<typename OtherDerType> - inline AutoDiffScalar& operator/=(const AutoDiffScalar<OtherDerType>& other) - { - *this = *this / other; - return *this; - } - - protected: - Scalar m_value; - DerType m_derivatives; - -}; - -namespace internal { - -template<typename _DerType> -struct auto_diff_special_op<_DerType, true> -// : auto_diff_scalar_op<_DerType, typename NumTraits<Scalar>::Real, -// is_same<Scalar,typename NumTraits<Scalar>::Real>::value> -{ - typedef typename remove_all<_DerType>::type DerType; - typedef typename traits<DerType>::Scalar Scalar; - typedef typename NumTraits<Scalar>::Real Real; - -// typedef auto_diff_scalar_op<_DerType, typename NumTraits<Scalar>::Real, -// is_same<Scalar,typename NumTraits<Scalar>::Real>::value> Base; - -// using Base::operator+; -// using Base::operator+=; -// using Base::operator-; -// using Base::operator-=; -// using Base::operator*; -// using Base::operator*=; - - const AutoDiffScalar<_DerType>& derived() const { return *static_cast<const AutoDiffScalar<_DerType>*>(this); } - AutoDiffScalar<_DerType>& derived() { return *static_cast<AutoDiffScalar<_DerType>*>(this); } - - - inline const AutoDiffScalar<DerType&> operator+(const Real& other) const - { - return AutoDiffScalar<DerType&>(derived().value() + other, derived().derivatives()); - } - - friend inline const AutoDiffScalar<DerType&> operator+(const Real& a, const AutoDiffScalar<_DerType>& b) - { - return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives()); - } - - inline AutoDiffScalar<_DerType>& operator+=(const Real& other) - { - derived().value() += other; - return derived(); - } - - - inline const AutoDiffScalar<typename CwiseUnaryOp<bind2nd_op<scalar_product_op<Scalar,Real> >, DerType>::Type > - operator*(const Real& other) const - { - return AutoDiffScalar<typename CwiseUnaryOp<bind2nd_op<scalar_product_op<Scalar,Real> >, DerType>::Type >( - derived().value() * other, - derived().derivatives() * other); - } - - friend inline const AutoDiffScalar<typename CwiseUnaryOp<bind1st_op<scalar_product_op<Real,Scalar> >, DerType>::Type > - operator*(const Real& other, const AutoDiffScalar<_DerType>& a) - { - return AutoDiffScalar<typename CwiseUnaryOp<bind1st_op<scalar_product_op<Real,Scalar> >, DerType>::Type >( - a.value() * other, - a.derivatives() * other); - } - - inline AutoDiffScalar<_DerType>& operator*=(const Scalar& other) - { - *this = *this * other; - return derived(); - } -}; - -template<typename _DerType> -struct auto_diff_special_op<_DerType, false> -{ - void operator*() const; - void operator-() const; - void operator+() const; -}; - -template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols, typename B> -struct make_coherent_impl<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>, B> { - typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> A; - static void run(A& a, B& b) { - if((A_Rows==Dynamic || A_Cols==Dynamic) && (a.size()==0)) - { - a.resize(b.size()); - a.setZero(); - } - } -}; - -template<typename A, typename B_Scalar, int B_Rows, int B_Cols, int B_Options, int B_MaxRows, int B_MaxCols> -struct make_coherent_impl<A, Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> > { - typedef Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> B; - static void run(A& a, B& b) { - if((B_Rows==Dynamic || B_Cols==Dynamic) && (b.size()==0)) - { - b.resize(a.size()); - b.setZero(); - } - } -}; - -template<typename A_Scalar, int A_Rows, int A_Cols, int A_Options, int A_MaxRows, int A_MaxCols, - typename B_Scalar, int B_Rows, int B_Cols, int B_Options, int B_MaxRows, int B_MaxCols> -struct make_coherent_impl<Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols>, - Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> > { - typedef Matrix<A_Scalar, A_Rows, A_Cols, A_Options, A_MaxRows, A_MaxCols> A; - typedef Matrix<B_Scalar, B_Rows, B_Cols, B_Options, B_MaxRows, B_MaxCols> B; - static void run(A& a, B& b) { - if((A_Rows==Dynamic || A_Cols==Dynamic) && (a.size()==0)) - { - a.resize(b.size()); - a.setZero(); - } - else if((B_Rows==Dynamic || B_Cols==Dynamic) && (b.size()==0)) - { - b.resize(a.size()); - b.setZero(); - } - } -}; - -} // end namespace internal - -template<typename DerType, typename BinOp> -struct ScalarBinaryOpTraits<AutoDiffScalar<DerType>,typename DerType::Scalar,BinOp> -{ - typedef AutoDiffScalar<DerType> ReturnType; -}; - -template<typename DerType, typename BinOp> -struct ScalarBinaryOpTraits<typename DerType::Scalar,AutoDiffScalar<DerType>, BinOp> -{ - typedef AutoDiffScalar<DerType> ReturnType; -}; - - -// The following is an attempt to let Eigen's known about expression template, but that's more tricky! - -// template<typename DerType, typename BinOp> -// struct ScalarBinaryOpTraits<AutoDiffScalar<DerType>,AutoDiffScalar<DerType>, BinOp> -// { -// enum { Defined = 1 }; -// typedef AutoDiffScalar<typename DerType::PlainObject> ReturnType; -// }; -// -// template<typename DerType1,typename DerType2, typename BinOp> -// struct ScalarBinaryOpTraits<AutoDiffScalar<DerType1>,AutoDiffScalar<DerType2>, BinOp> -// { -// enum { Defined = 1 };//internal::is_same<typename DerType1::Scalar,typename DerType2::Scalar>::value }; -// typedef AutoDiffScalar<typename DerType1::PlainObject> ReturnType; -// }; - -#define EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(FUNC,CODE) \ - template<typename DerType> \ - inline const Eigen::AutoDiffScalar< \ - EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(typename Eigen::internal::remove_all<DerType>::type, typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar, product) > \ - FUNC(const Eigen::AutoDiffScalar<DerType>& x) { \ - using namespace Eigen; \ - typedef typename Eigen::internal::traits<typename Eigen::internal::remove_all<DerType>::type>::Scalar Scalar; \ - EIGEN_UNUSED_VARIABLE(sizeof(Scalar)); \ - CODE; \ - } - -template<typename DerType> -inline const AutoDiffScalar<DerType>& conj(const AutoDiffScalar<DerType>& x) { return x; } -template<typename DerType> -inline const AutoDiffScalar<DerType>& real(const AutoDiffScalar<DerType>& x) { return x; } -template<typename DerType> -inline typename DerType::Scalar imag(const AutoDiffScalar<DerType>&) { return 0.; } -template<typename DerType, typename T> -inline AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (min)(const AutoDiffScalar<DerType>& x, const T& y) { - typedef AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ADS; - return (x <= y ? ADS(x) : ADS(y)); -} -template<typename DerType, typename T> -inline AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (max)(const AutoDiffScalar<DerType>& x, const T& y) { - typedef AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ADS; - return (x >= y ? ADS(x) : ADS(y)); -} -template<typename DerType, typename T> -inline AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (min)(const T& x, const AutoDiffScalar<DerType>& y) { - typedef AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ADS; - return (x < y ? ADS(x) : ADS(y)); -} -template<typename DerType, typename T> -inline AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (max)(const T& x, const AutoDiffScalar<DerType>& y) { - typedef AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> ADS; - return (x > y ? ADS(x) : ADS(y)); -} -template<typename DerType> -inline AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (min)(const AutoDiffScalar<DerType>& x, const AutoDiffScalar<DerType>& y) { - return (x.value() < y.value() ? x : y); -} -template<typename DerType> -inline AutoDiffScalar<typename Eigen::internal::remove_all<DerType>::type::PlainObject> (max)(const AutoDiffScalar<DerType>& x, const AutoDiffScalar<DerType>& y) { - return (x.value() >= y.value() ? x : y); -} - - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs, - using std::abs; - return Eigen::MakeAutoDiffScalar(abs(x.value()), x.derivatives() * (x.value()<0 ? -1 : 1) );) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(abs2, - using numext::abs2; - return Eigen::MakeAutoDiffScalar(abs2(x.value()), x.derivatives() * (Scalar(2)*x.value()));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sqrt, - using std::sqrt; - Scalar sqrtx = sqrt(x.value()); - return Eigen::MakeAutoDiffScalar(sqrtx,x.derivatives() * (Scalar(0.5) / sqrtx));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(cos, - using std::cos; - using std::sin; - return Eigen::MakeAutoDiffScalar(cos(x.value()), x.derivatives() * (-sin(x.value())));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sin, - using std::sin; - using std::cos; - return Eigen::MakeAutoDiffScalar(sin(x.value()),x.derivatives() * cos(x.value()));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(exp, - using std::exp; - Scalar expx = exp(x.value()); - return Eigen::MakeAutoDiffScalar(expx,x.derivatives() * expx);) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(log, - using std::log; - return Eigen::MakeAutoDiffScalar(log(x.value()),x.derivatives() * (Scalar(1)/x.value()));) - -template<typename DerType> -inline const Eigen::AutoDiffScalar< -EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(typename internal::remove_all<DerType>::type,typename internal::traits<typename internal::remove_all<DerType>::type>::Scalar,product) > -pow(const Eigen::AutoDiffScalar<DerType> &x, const typename internal::traits<typename internal::remove_all<DerType>::type>::Scalar &y) -{ - using namespace Eigen; - using std::pow; - return Eigen::MakeAutoDiffScalar(pow(x.value(),y), x.derivatives() * (y * pow(x.value(),y-1))); -} - - -template<typename DerTypeA,typename DerTypeB> -inline const AutoDiffScalar<Matrix<typename internal::traits<typename internal::remove_all<DerTypeA>::type>::Scalar,Dynamic,1> > -atan2(const AutoDiffScalar<DerTypeA>& a, const AutoDiffScalar<DerTypeB>& b) -{ - using std::atan2; - typedef typename internal::traits<typename internal::remove_all<DerTypeA>::type>::Scalar Scalar; - typedef AutoDiffScalar<Matrix<Scalar,Dynamic,1> > PlainADS; - PlainADS ret; - ret.value() = atan2(a.value(), b.value()); - - Scalar squared_hypot = a.value() * a.value() + b.value() * b.value(); - - // if (squared_hypot==0) the derivation is undefined and the following results in a NaN: - ret.derivatives() = (a.derivatives() * b.value() - a.value() * b.derivatives()) / squared_hypot; - - return ret; -} - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(tan, - using std::tan; - using std::cos; - return Eigen::MakeAutoDiffScalar(tan(x.value()),x.derivatives() * (Scalar(1)/numext::abs2(cos(x.value()))));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(asin, - using std::sqrt; - using std::asin; - return Eigen::MakeAutoDiffScalar(asin(x.value()),x.derivatives() * (Scalar(1)/sqrt(1-numext::abs2(x.value()))));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(acos, - using std::sqrt; - using std::acos; - return Eigen::MakeAutoDiffScalar(acos(x.value()),x.derivatives() * (Scalar(-1)/sqrt(1-numext::abs2(x.value()))));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(tanh, - using std::cosh; - using std::tanh; - return Eigen::MakeAutoDiffScalar(tanh(x.value()),x.derivatives() * (Scalar(1)/numext::abs2(cosh(x.value()))));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(sinh, - using std::sinh; - using std::cosh; - return Eigen::MakeAutoDiffScalar(sinh(x.value()),x.derivatives() * cosh(x.value()));) - -EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(cosh, - using std::sinh; - using std::cosh; - return Eigen::MakeAutoDiffScalar(cosh(x.value()),x.derivatives() * sinh(x.value()));) - -#undef EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY - -template<typename DerType> struct NumTraits<AutoDiffScalar<DerType> > - : NumTraits< typename NumTraits<typename internal::remove_all<DerType>::type::Scalar>::Real > -{ - typedef typename internal::remove_all<DerType>::type DerTypeCleaned; - typedef AutoDiffScalar<Matrix<typename NumTraits<typename DerTypeCleaned::Scalar>::Real,DerTypeCleaned::RowsAtCompileTime,DerTypeCleaned::ColsAtCompileTime, - 0, DerTypeCleaned::MaxRowsAtCompileTime, DerTypeCleaned::MaxColsAtCompileTime> > Real; - typedef AutoDiffScalar<DerType> NonInteger; - typedef AutoDiffScalar<DerType> Nested; - typedef typename NumTraits<typename DerTypeCleaned::Scalar>::Literal Literal; - enum{ - RequireInitialization = 1 - }; -}; - -} - -namespace std { -template <typename T> -class numeric_limits<Eigen::AutoDiffScalar<T> > - : public numeric_limits<typename T::Scalar> {}; - -} // namespace std - -#endif // EIGEN_AUTODIFF_SCALAR_H diff --git a/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h b/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h deleted file mode 100644 index 8c2d048..0000000 --- a/eigen/unsupported/Eigen/src/AutoDiff/AutoDiffVector.h +++ /dev/null @@ -1,220 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_AUTODIFF_VECTOR_H -#define EIGEN_AUTODIFF_VECTOR_H - -namespace Eigen { - -/* \class AutoDiffScalar - * \brief A scalar type replacement with automatic differentation capability - * - * \param DerType the vector type used to store/represent the derivatives (e.g. Vector3f) - * - * This class represents a scalar value while tracking its respective derivatives. - * - * It supports the following list of global math function: - * - std::abs, std::sqrt, std::pow, std::exp, std::log, std::sin, std::cos, - * - internal::abs, internal::sqrt, numext::pow, internal::exp, internal::log, internal::sin, internal::cos, - * - internal::conj, internal::real, internal::imag, numext::abs2. - * - * AutoDiffScalar can be used as the scalar type of an Eigen::Matrix object. However, - * in that case, the expression template mechanism only occurs at the top Matrix level, - * while derivatives are computed right away. - * - */ -template<typename ValueType, typename JacobianType> -class AutoDiffVector -{ - public: - //typedef typename internal::traits<ValueType>::Scalar Scalar; - typedef typename internal::traits<ValueType>::Scalar BaseScalar; - typedef AutoDiffScalar<Matrix<BaseScalar,JacobianType::RowsAtCompileTime,1> > ActiveScalar; - typedef ActiveScalar Scalar; - typedef AutoDiffScalar<typename JacobianType::ColXpr> CoeffType; - typedef typename JacobianType::Index Index; - - inline AutoDiffVector() {} - - inline AutoDiffVector(const ValueType& values) - : m_values(values) - { - m_jacobian.setZero(); - } - - - CoeffType operator[] (Index i) { return CoeffType(m_values[i], m_jacobian.col(i)); } - const CoeffType operator[] (Index i) const { return CoeffType(m_values[i], m_jacobian.col(i)); } - - CoeffType operator() (Index i) { return CoeffType(m_values[i], m_jacobian.col(i)); } - const CoeffType operator() (Index i) const { return CoeffType(m_values[i], m_jacobian.col(i)); } - - CoeffType coeffRef(Index i) { return CoeffType(m_values[i], m_jacobian.col(i)); } - const CoeffType coeffRef(Index i) const { return CoeffType(m_values[i], m_jacobian.col(i)); } - - Index size() const { return m_values.size(); } - - // FIXME here we could return an expression of the sum - Scalar sum() const { /*std::cerr << "sum \n\n";*/ /*std::cerr << m_jacobian.rowwise().sum() << "\n\n";*/ return Scalar(m_values.sum(), m_jacobian.rowwise().sum()); } - - - inline AutoDiffVector(const ValueType& values, const JacobianType& jac) - : m_values(values), m_jacobian(jac) - {} - - template<typename OtherValueType, typename OtherJacobianType> - inline AutoDiffVector(const AutoDiffVector<OtherValueType, OtherJacobianType>& other) - : m_values(other.values()), m_jacobian(other.jacobian()) - {} - - inline AutoDiffVector(const AutoDiffVector& other) - : m_values(other.values()), m_jacobian(other.jacobian()) - {} - - template<typename OtherValueType, typename OtherJacobianType> - inline AutoDiffVector& operator=(const AutoDiffVector<OtherValueType, OtherJacobianType>& other) - { - m_values = other.values(); - m_jacobian = other.jacobian(); - return *this; - } - - inline AutoDiffVector& operator=(const AutoDiffVector& other) - { - m_values = other.values(); - m_jacobian = other.jacobian(); - return *this; - } - - inline const ValueType& values() const { return m_values; } - inline ValueType& values() { return m_values; } - - inline const JacobianType& jacobian() const { return m_jacobian; } - inline JacobianType& jacobian() { return m_jacobian; } - - template<typename OtherValueType,typename OtherJacobianType> - inline const AutoDiffVector< - typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,ValueType,OtherValueType>::Type, - typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,JacobianType,OtherJacobianType>::Type > - operator+(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) const - { - return AutoDiffVector< - typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,ValueType,OtherValueType>::Type, - typename MakeCwiseBinaryOp<internal::scalar_sum_op<BaseScalar>,JacobianType,OtherJacobianType>::Type >( - m_values + other.values(), - m_jacobian + other.jacobian()); - } - - template<typename OtherValueType, typename OtherJacobianType> - inline AutoDiffVector& - operator+=(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) - { - m_values += other.values(); - m_jacobian += other.jacobian(); - return *this; - } - - template<typename OtherValueType,typename OtherJacobianType> - inline const AutoDiffVector< - typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,ValueType,OtherValueType>::Type, - typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,JacobianType,OtherJacobianType>::Type > - operator-(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) const - { - return AutoDiffVector< - typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,ValueType,OtherValueType>::Type, - typename MakeCwiseBinaryOp<internal::scalar_difference_op<Scalar>,JacobianType,OtherJacobianType>::Type >( - m_values - other.values(), - m_jacobian - other.jacobian()); - } - - template<typename OtherValueType, typename OtherJacobianType> - inline AutoDiffVector& - operator-=(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) - { - m_values -= other.values(); - m_jacobian -= other.jacobian(); - return *this; - } - - inline const AutoDiffVector< - typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, ValueType>::Type, - typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, JacobianType>::Type > - operator-() const - { - return AutoDiffVector< - typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, ValueType>::Type, - typename MakeCwiseUnaryOp<internal::scalar_opposite_op<Scalar>, JacobianType>::Type >( - -m_values, - -m_jacobian); - } - - inline const AutoDiffVector< - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type, - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type> - operator*(const BaseScalar& other) const - { - return AutoDiffVector< - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type, - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type >( - m_values * other, - m_jacobian * other); - } - - friend inline const AutoDiffVector< - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type, - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type > - operator*(const Scalar& other, const AutoDiffVector& v) - { - return AutoDiffVector< - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, ValueType>::Type, - typename MakeCwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>::Type >( - v.values() * other, - v.jacobian() * other); - } - -// template<typename OtherValueType,typename OtherJacobianType> -// inline const AutoDiffVector< -// CwiseBinaryOp<internal::scalar_multiple_op<Scalar>, ValueType, OtherValueType> -// CwiseBinaryOp<internal::scalar_sum_op<Scalar>, -// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>, -// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, OtherJacobianType> > > -// operator*(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) const -// { -// return AutoDiffVector< -// CwiseBinaryOp<internal::scalar_multiple_op<Scalar>, ValueType, OtherValueType> -// CwiseBinaryOp<internal::scalar_sum_op<Scalar>, -// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, JacobianType>, -// CwiseUnaryOp<internal::scalar_multiple_op<Scalar>, OtherJacobianType> > >( -// m_values.cwise() * other.values(), -// (m_jacobian * other.values()) + (m_values * other.jacobian())); -// } - - inline AutoDiffVector& operator*=(const Scalar& other) - { - m_values *= other; - m_jacobian *= other; - return *this; - } - - template<typename OtherValueType,typename OtherJacobianType> - inline AutoDiffVector& operator*=(const AutoDiffVector<OtherValueType,OtherJacobianType>& other) - { - *this = *this * other; - return *this; - } - - protected: - ValueType m_values; - JacobianType m_jacobian; - -}; - -} - -#endif // EIGEN_AUTODIFF_VECTOR_H diff --git a/eigen/unsupported/Eigen/src/BVH/BVAlgorithms.h b/eigen/unsupported/Eigen/src/BVH/BVAlgorithms.h deleted file mode 100644 index 994c8af..0000000 --- a/eigen/unsupported/Eigen/src/BVH/BVAlgorithms.h +++ /dev/null @@ -1,293 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Ilya Baran <ibaran@mit.edu> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_BVALGORITHMS_H -#define EIGEN_BVALGORITHMS_H - -namespace Eigen { - -namespace internal { - -#ifndef EIGEN_PARSED_BY_DOXYGEN -template<typename BVH, typename Intersector> -bool intersect_helper(const BVH &tree, Intersector &intersector, typename BVH::Index root) -{ - typedef typename BVH::Index Index; - typedef typename BVH::VolumeIterator VolIter; - typedef typename BVH::ObjectIterator ObjIter; - - VolIter vBegin = VolIter(), vEnd = VolIter(); - ObjIter oBegin = ObjIter(), oEnd = ObjIter(); - - std::vector<Index> todo(1, root); - - while(!todo.empty()) { - tree.getChildren(todo.back(), vBegin, vEnd, oBegin, oEnd); - todo.pop_back(); - - for(; vBegin != vEnd; ++vBegin) //go through child volumes - if(intersector.intersectVolume(tree.getVolume(*vBegin))) - todo.push_back(*vBegin); - - for(; oBegin != oEnd; ++oBegin) //go through child objects - if(intersector.intersectObject(*oBegin)) - return true; //intersector said to stop query - } - return false; -} -#endif //not EIGEN_PARSED_BY_DOXYGEN - -template<typename Volume1, typename Object1, typename Object2, typename Intersector> -struct intersector_helper1 -{ - intersector_helper1(const Object2 &inStored, Intersector &in) : stored(inStored), intersector(in) {} - bool intersectVolume(const Volume1 &vol) { return intersector.intersectVolumeObject(vol, stored); } - bool intersectObject(const Object1 &obj) { return intersector.intersectObjectObject(obj, stored); } - Object2 stored; - Intersector &intersector; -private: - intersector_helper1& operator=(const intersector_helper1&); -}; - -template<typename Volume2, typename Object2, typename Object1, typename Intersector> -struct intersector_helper2 -{ - intersector_helper2(const Object1 &inStored, Intersector &in) : stored(inStored), intersector(in) {} - bool intersectVolume(const Volume2 &vol) { return intersector.intersectObjectVolume(stored, vol); } - bool intersectObject(const Object2 &obj) { return intersector.intersectObjectObject(stored, obj); } - Object1 stored; - Intersector &intersector; -private: - intersector_helper2& operator=(const intersector_helper2&); -}; - -} // end namespace internal - -/** Given a BVH, runs the query encapsulated by \a intersector. - * The Intersector type must provide the following members: \code - bool intersectVolume(const BVH::Volume &volume) //returns true if volume intersects the query - bool intersectObject(const BVH::Object &object) //returns true if the search should terminate immediately - \endcode - */ -template<typename BVH, typename Intersector> -void BVIntersect(const BVH &tree, Intersector &intersector) -{ - internal::intersect_helper(tree, intersector, tree.getRootIndex()); -} - -/** Given two BVH's, runs the query on their Cartesian product encapsulated by \a intersector. - * The Intersector type must provide the following members: \code - bool intersectVolumeVolume(const BVH1::Volume &v1, const BVH2::Volume &v2) //returns true if product of volumes intersects the query - bool intersectVolumeObject(const BVH1::Volume &v1, const BVH2::Object &o2) //returns true if the volume-object product intersects the query - bool intersectObjectVolume(const BVH1::Object &o1, const BVH2::Volume &v2) //returns true if the volume-object product intersects the query - bool intersectObjectObject(const BVH1::Object &o1, const BVH2::Object &o2) //returns true if the search should terminate immediately - \endcode - */ -template<typename BVH1, typename BVH2, typename Intersector> -void BVIntersect(const BVH1 &tree1, const BVH2 &tree2, Intersector &intersector) //TODO: tandem descent when it makes sense -{ - typedef typename BVH1::Index Index1; - typedef typename BVH2::Index Index2; - typedef internal::intersector_helper1<typename BVH1::Volume, typename BVH1::Object, typename BVH2::Object, Intersector> Helper1; - typedef internal::intersector_helper2<typename BVH2::Volume, typename BVH2::Object, typename BVH1::Object, Intersector> Helper2; - typedef typename BVH1::VolumeIterator VolIter1; - typedef typename BVH1::ObjectIterator ObjIter1; - typedef typename BVH2::VolumeIterator VolIter2; - typedef typename BVH2::ObjectIterator ObjIter2; - - VolIter1 vBegin1 = VolIter1(), vEnd1 = VolIter1(); - ObjIter1 oBegin1 = ObjIter1(), oEnd1 = ObjIter1(); - VolIter2 vBegin2 = VolIter2(), vEnd2 = VolIter2(), vCur2 = VolIter2(); - ObjIter2 oBegin2 = ObjIter2(), oEnd2 = ObjIter2(), oCur2 = ObjIter2(); - - std::vector<std::pair<Index1, Index2> > todo(1, std::make_pair(tree1.getRootIndex(), tree2.getRootIndex())); - - while(!todo.empty()) { - tree1.getChildren(todo.back().first, vBegin1, vEnd1, oBegin1, oEnd1); - tree2.getChildren(todo.back().second, vBegin2, vEnd2, oBegin2, oEnd2); - todo.pop_back(); - - for(; vBegin1 != vEnd1; ++vBegin1) { //go through child volumes of first tree - const typename BVH1::Volume &vol1 = tree1.getVolume(*vBegin1); - for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree - if(intersector.intersectVolumeVolume(vol1, tree2.getVolume(*vCur2))) - todo.push_back(std::make_pair(*vBegin1, *vCur2)); - } - - for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree - Helper1 helper(*oCur2, intersector); - if(internal::intersect_helper(tree1, helper, *vBegin1)) - return; //intersector said to stop query - } - } - - for(; oBegin1 != oEnd1; ++oBegin1) { //go through child objects of first tree - for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree - Helper2 helper(*oBegin1, intersector); - if(internal::intersect_helper(tree2, helper, *vCur2)) - return; //intersector said to stop query - } - - for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree - if(intersector.intersectObjectObject(*oBegin1, *oCur2)) - return; //intersector said to stop query - } - } - } -} - -namespace internal { - -#ifndef EIGEN_PARSED_BY_DOXYGEN -template<typename BVH, typename Minimizer> -typename Minimizer::Scalar minimize_helper(const BVH &tree, Minimizer &minimizer, typename BVH::Index root, typename Minimizer::Scalar minimum) -{ - typedef typename Minimizer::Scalar Scalar; - typedef typename BVH::Index Index; - typedef std::pair<Scalar, Index> QueueElement; //first element is priority - typedef typename BVH::VolumeIterator VolIter; - typedef typename BVH::ObjectIterator ObjIter; - - VolIter vBegin = VolIter(), vEnd = VolIter(); - ObjIter oBegin = ObjIter(), oEnd = ObjIter(); - std::priority_queue<QueueElement, std::vector<QueueElement>, std::greater<QueueElement> > todo; //smallest is at the top - - todo.push(std::make_pair(Scalar(), root)); - - while(!todo.empty()) { - tree.getChildren(todo.top().second, vBegin, vEnd, oBegin, oEnd); - todo.pop(); - - for(; oBegin != oEnd; ++oBegin) //go through child objects - minimum = (std::min)(minimum, minimizer.minimumOnObject(*oBegin)); - - for(; vBegin != vEnd; ++vBegin) { //go through child volumes - Scalar val = minimizer.minimumOnVolume(tree.getVolume(*vBegin)); - if(val < minimum) - todo.push(std::make_pair(val, *vBegin)); - } - } - - return minimum; -} -#endif //not EIGEN_PARSED_BY_DOXYGEN - - -template<typename Volume1, typename Object1, typename Object2, typename Minimizer> -struct minimizer_helper1 -{ - typedef typename Minimizer::Scalar Scalar; - minimizer_helper1(const Object2 &inStored, Minimizer &m) : stored(inStored), minimizer(m) {} - Scalar minimumOnVolume(const Volume1 &vol) { return minimizer.minimumOnVolumeObject(vol, stored); } - Scalar minimumOnObject(const Object1 &obj) { return minimizer.minimumOnObjectObject(obj, stored); } - Object2 stored; - Minimizer &minimizer; -private: - minimizer_helper1& operator=(const minimizer_helper1&); -}; - -template<typename Volume2, typename Object2, typename Object1, typename Minimizer> -struct minimizer_helper2 -{ - typedef typename Minimizer::Scalar Scalar; - minimizer_helper2(const Object1 &inStored, Minimizer &m) : stored(inStored), minimizer(m) {} - Scalar minimumOnVolume(const Volume2 &vol) { return minimizer.minimumOnObjectVolume(stored, vol); } - Scalar minimumOnObject(const Object2 &obj) { return minimizer.minimumOnObjectObject(stored, obj); } - Object1 stored; - Minimizer &minimizer; -private: - minimizer_helper2& operator=(const minimizer_helper2&); -}; - -} // end namespace internal - -/** Given a BVH, runs the query encapsulated by \a minimizer. - * \returns the minimum value. - * The Minimizer type must provide the following members: \code - typedef Scalar //the numeric type of what is being minimized--not necessarily the Scalar type of the BVH (if it has one) - Scalar minimumOnVolume(const BVH::Volume &volume) - Scalar minimumOnObject(const BVH::Object &object) - \endcode - */ -template<typename BVH, typename Minimizer> -typename Minimizer::Scalar BVMinimize(const BVH &tree, Minimizer &minimizer) -{ - return internal::minimize_helper(tree, minimizer, tree.getRootIndex(), (std::numeric_limits<typename Minimizer::Scalar>::max)()); -} - -/** Given two BVH's, runs the query on their cartesian product encapsulated by \a minimizer. - * \returns the minimum value. - * The Minimizer type must provide the following members: \code - typedef Scalar //the numeric type of what is being minimized--not necessarily the Scalar type of the BVH (if it has one) - Scalar minimumOnVolumeVolume(const BVH1::Volume &v1, const BVH2::Volume &v2) - Scalar minimumOnVolumeObject(const BVH1::Volume &v1, const BVH2::Object &o2) - Scalar minimumOnObjectVolume(const BVH1::Object &o1, const BVH2::Volume &v2) - Scalar minimumOnObjectObject(const BVH1::Object &o1, const BVH2::Object &o2) - \endcode - */ -template<typename BVH1, typename BVH2, typename Minimizer> -typename Minimizer::Scalar BVMinimize(const BVH1 &tree1, const BVH2 &tree2, Minimizer &minimizer) -{ - typedef typename Minimizer::Scalar Scalar; - typedef typename BVH1::Index Index1; - typedef typename BVH2::Index Index2; - typedef internal::minimizer_helper1<typename BVH1::Volume, typename BVH1::Object, typename BVH2::Object, Minimizer> Helper1; - typedef internal::minimizer_helper2<typename BVH2::Volume, typename BVH2::Object, typename BVH1::Object, Minimizer> Helper2; - typedef std::pair<Scalar, std::pair<Index1, Index2> > QueueElement; //first element is priority - typedef typename BVH1::VolumeIterator VolIter1; - typedef typename BVH1::ObjectIterator ObjIter1; - typedef typename BVH2::VolumeIterator VolIter2; - typedef typename BVH2::ObjectIterator ObjIter2; - - VolIter1 vBegin1 = VolIter1(), vEnd1 = VolIter1(); - ObjIter1 oBegin1 = ObjIter1(), oEnd1 = ObjIter1(); - VolIter2 vBegin2 = VolIter2(), vEnd2 = VolIter2(), vCur2 = VolIter2(); - ObjIter2 oBegin2 = ObjIter2(), oEnd2 = ObjIter2(), oCur2 = ObjIter2(); - std::priority_queue<QueueElement, std::vector<QueueElement>, std::greater<QueueElement> > todo; //smallest is at the top - - Scalar minimum = (std::numeric_limits<Scalar>::max)(); - todo.push(std::make_pair(Scalar(), std::make_pair(tree1.getRootIndex(), tree2.getRootIndex()))); - - while(!todo.empty()) { - tree1.getChildren(todo.top().second.first, vBegin1, vEnd1, oBegin1, oEnd1); - tree2.getChildren(todo.top().second.second, vBegin2, vEnd2, oBegin2, oEnd2); - todo.pop(); - - for(; oBegin1 != oEnd1; ++oBegin1) { //go through child objects of first tree - for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree - minimum = (std::min)(minimum, minimizer.minimumOnObjectObject(*oBegin1, *oCur2)); - } - - for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree - Helper2 helper(*oBegin1, minimizer); - minimum = (std::min)(minimum, internal::minimize_helper(tree2, helper, *vCur2, minimum)); - } - } - - for(; vBegin1 != vEnd1; ++vBegin1) { //go through child volumes of first tree - const typename BVH1::Volume &vol1 = tree1.getVolume(*vBegin1); - - for(oCur2 = oBegin2; oCur2 != oEnd2; ++oCur2) {//go through child objects of second tree - Helper1 helper(*oCur2, minimizer); - minimum = (std::min)(minimum, internal::minimize_helper(tree1, helper, *vBegin1, minimum)); - } - - for(vCur2 = vBegin2; vCur2 != vEnd2; ++vCur2) { //go through child volumes of second tree - Scalar val = minimizer.minimumOnVolumeVolume(vol1, tree2.getVolume(*vCur2)); - if(val < minimum) - todo.push(std::make_pair(val, std::make_pair(*vBegin1, *vCur2))); - } - } - } - return minimum; -} - -} // end namespace Eigen - -#endif // EIGEN_BVALGORITHMS_H diff --git a/eigen/unsupported/Eigen/src/BVH/KdBVH.h b/eigen/unsupported/Eigen/src/BVH/KdBVH.h deleted file mode 100644 index 5e39af2..0000000 --- a/eigen/unsupported/Eigen/src/BVH/KdBVH.h +++ /dev/null @@ -1,223 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Ilya Baran <ibaran@mit.edu> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef KDBVH_H_INCLUDED -#define KDBVH_H_INCLUDED - -namespace Eigen { - -namespace internal { - -//internal pair class for the BVH--used instead of std::pair because of alignment -template<typename Scalar, int Dim> -struct vector_int_pair -{ -EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar, Dim) - typedef Matrix<Scalar, Dim, 1> VectorType; - - vector_int_pair(const VectorType &v, int i) : first(v), second(i) {} - - VectorType first; - int second; -}; - -//these templates help the tree initializer get the bounding boxes either from a provided -//iterator range or using bounding_box in a unified way -template<typename ObjectList, typename VolumeList, typename BoxIter> -struct get_boxes_helper { - void operator()(const ObjectList &objects, BoxIter boxBegin, BoxIter boxEnd, VolumeList &outBoxes) - { - outBoxes.insert(outBoxes.end(), boxBegin, boxEnd); - eigen_assert(outBoxes.size() == objects.size()); - EIGEN_ONLY_USED_FOR_DEBUG(objects); - } -}; - -template<typename ObjectList, typename VolumeList> -struct get_boxes_helper<ObjectList, VolumeList, int> { - void operator()(const ObjectList &objects, int, int, VolumeList &outBoxes) - { - outBoxes.reserve(objects.size()); - for(int i = 0; i < (int)objects.size(); ++i) - outBoxes.push_back(bounding_box(objects[i])); - } -}; - -} // end namespace internal - - -/** \class KdBVH - * \brief A simple bounding volume hierarchy based on AlignedBox - * - * \param _Scalar The underlying scalar type of the bounding boxes - * \param _Dim The dimension of the space in which the hierarchy lives - * \param _Object The object type that lives in the hierarchy. It must have value semantics. Either bounding_box(_Object) must - * be defined and return an AlignedBox<_Scalar, _Dim> or bounding boxes must be provided to the tree initializer. - * - * This class provides a simple (as opposed to optimized) implementation of a bounding volume hierarchy analogous to a Kd-tree. - * Given a sequence of objects, it computes their bounding boxes, constructs a Kd-tree of their centers - * and builds a BVH with the structure of that Kd-tree. When the elements of the tree are too expensive to be copied around, - * it is useful for _Object to be a pointer. - */ -template<typename _Scalar, int _Dim, typename _Object> class KdBVH -{ -public: - enum { Dim = _Dim }; - typedef _Object Object; - typedef std::vector<Object, aligned_allocator<Object> > ObjectList; - typedef _Scalar Scalar; - typedef AlignedBox<Scalar, Dim> Volume; - typedef std::vector<Volume, aligned_allocator<Volume> > VolumeList; - typedef int Index; - typedef const int *VolumeIterator; //the iterators are just pointers into the tree's vectors - typedef const Object *ObjectIterator; - - KdBVH() {} - - /** Given an iterator range over \a Object references, constructs the BVH. Requires that bounding_box(Object) return a Volume. */ - template<typename Iter> KdBVH(Iter begin, Iter end) { init(begin, end, 0, 0); } //int is recognized by init as not being an iterator type - - /** Given an iterator range over \a Object references and an iterator range over their bounding boxes, constructs the BVH */ - template<typename OIter, typename BIter> KdBVH(OIter begin, OIter end, BIter boxBegin, BIter boxEnd) { init(begin, end, boxBegin, boxEnd); } - - /** Given an iterator range over \a Object references, constructs the BVH, overwriting whatever is in there currently. - * Requires that bounding_box(Object) return a Volume. */ - template<typename Iter> void init(Iter begin, Iter end) { init(begin, end, 0, 0); } - - /** Given an iterator range over \a Object references and an iterator range over their bounding boxes, - * constructs the BVH, overwriting whatever is in there currently. */ - template<typename OIter, typename BIter> void init(OIter begin, OIter end, BIter boxBegin, BIter boxEnd) - { - objects.clear(); - boxes.clear(); - children.clear(); - - objects.insert(objects.end(), begin, end); - int n = static_cast<int>(objects.size()); - - if(n < 2) - return; //if we have at most one object, we don't need any internal nodes - - VolumeList objBoxes; - VIPairList objCenters; - - //compute the bounding boxes depending on BIter type - internal::get_boxes_helper<ObjectList, VolumeList, BIter>()(objects, boxBegin, boxEnd, objBoxes); - - objCenters.reserve(n); - boxes.reserve(n - 1); - children.reserve(2 * n - 2); - - for(int i = 0; i < n; ++i) - objCenters.push_back(VIPair(objBoxes[i].center(), i)); - - build(objCenters, 0, n, objBoxes, 0); //the recursive part of the algorithm - - ObjectList tmp(n); - tmp.swap(objects); - for(int i = 0; i < n; ++i) - objects[i] = tmp[objCenters[i].second]; - } - - /** \returns the index of the root of the hierarchy */ - inline Index getRootIndex() const { return (int)boxes.size() - 1; } - - /** Given an \a index of a node, on exit, \a outVBegin and \a outVEnd range over the indices of the volume children of the node - * and \a outOBegin and \a outOEnd range over the object children of the node */ - EIGEN_STRONG_INLINE void getChildren(Index index, VolumeIterator &outVBegin, VolumeIterator &outVEnd, - ObjectIterator &outOBegin, ObjectIterator &outOEnd) const - { //inlining this function should open lots of optimization opportunities to the compiler - if(index < 0) { - outVBegin = outVEnd; - if(!objects.empty()) - outOBegin = &(objects[0]); - outOEnd = outOBegin + objects.size(); //output all objects--necessary when the tree has only one object - return; - } - - int numBoxes = static_cast<int>(boxes.size()); - - int idx = index * 2; - if(children[idx + 1] < numBoxes) { //second index is always bigger - outVBegin = &(children[idx]); - outVEnd = outVBegin + 2; - outOBegin = outOEnd; - } - else if(children[idx] >= numBoxes) { //if both children are objects - outVBegin = outVEnd; - outOBegin = &(objects[children[idx] - numBoxes]); - outOEnd = outOBegin + 2; - } else { //if the first child is a volume and the second is an object - outVBegin = &(children[idx]); - outVEnd = outVBegin + 1; - outOBegin = &(objects[children[idx + 1] - numBoxes]); - outOEnd = outOBegin + 1; - } - } - - /** \returns the bounding box of the node at \a index */ - inline const Volume &getVolume(Index index) const - { - return boxes[index]; - } - -private: - typedef internal::vector_int_pair<Scalar, Dim> VIPair; - typedef std::vector<VIPair, aligned_allocator<VIPair> > VIPairList; - typedef Matrix<Scalar, Dim, 1> VectorType; - struct VectorComparator //compares vectors, or, more specificall, VIPairs along a particular dimension - { - VectorComparator(int inDim) : dim(inDim) {} - inline bool operator()(const VIPair &v1, const VIPair &v2) const { return v1.first[dim] < v2.first[dim]; } - int dim; - }; - - //Build the part of the tree between objects[from] and objects[to] (not including objects[to]). - //This routine partitions the objCenters in [from, to) along the dimension dim, recursively constructs - //the two halves, and adds their parent node. TODO: a cache-friendlier layout - void build(VIPairList &objCenters, int from, int to, const VolumeList &objBoxes, int dim) - { - eigen_assert(to - from > 1); - if(to - from == 2) { - boxes.push_back(objBoxes[objCenters[from].second].merged(objBoxes[objCenters[from + 1].second])); - children.push_back(from + (int)objects.size() - 1); //there are objects.size() - 1 tree nodes - children.push_back(from + (int)objects.size()); - } - else if(to - from == 3) { - int mid = from + 2; - std::nth_element(objCenters.begin() + from, objCenters.begin() + mid, - objCenters.begin() + to, VectorComparator(dim)); //partition - build(objCenters, from, mid, objBoxes, (dim + 1) % Dim); - int idx1 = (int)boxes.size() - 1; - boxes.push_back(boxes[idx1].merged(objBoxes[objCenters[mid].second])); - children.push_back(idx1); - children.push_back(mid + (int)objects.size() - 1); - } - else { - int mid = from + (to - from) / 2; - nth_element(objCenters.begin() + from, objCenters.begin() + mid, - objCenters.begin() + to, VectorComparator(dim)); //partition - build(objCenters, from, mid, objBoxes, (dim + 1) % Dim); - int idx1 = (int)boxes.size() - 1; - build(objCenters, mid, to, objBoxes, (dim + 1) % Dim); - int idx2 = (int)boxes.size() - 1; - boxes.push_back(boxes[idx1].merged(boxes[idx2])); - children.push_back(idx1); - children.push_back(idx2); - } - } - - std::vector<int> children; //children of x are children[2x] and children[2x+1], indices bigger than boxes.size() index into objects. - VolumeList boxes; - ObjectList objects; -}; - -} // end namespace Eigen - -#endif //KDBVH_H_INCLUDED diff --git a/eigen/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h b/eigen/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h deleted file mode 100644 index 866a8a4..0000000 --- a/eigen/unsupported/Eigen/src/Eigenvalues/ArpackSelfAdjointEigenSolver.h +++ /dev/null @@ -1,805 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2012 David Harmon <dharmon@gmail.com> -// -// 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 <http://www.gnu.org/licenses/>. - -#ifndef EIGEN_ARPACKGENERALIZEDSELFADJOINTEIGENSOLVER_H -#define EIGEN_ARPACKGENERALIZEDSELFADJOINTEIGENSOLVER_H - -#include <Eigen/Dense> - -namespace Eigen { - -namespace internal { - template<typename Scalar, typename RealScalar> struct arpack_wrapper; - template<typename MatrixSolver, typename MatrixType, typename Scalar, bool BisSPD> struct OP; -} - - - -template<typename MatrixType, typename MatrixSolver=SimplicialLLT<MatrixType>, bool BisSPD=false> -class ArpackGeneralizedSelfAdjointEigenSolver -{ -public: - //typedef typename MatrixSolver::MatrixType MatrixType; - - /** \brief Scalar type for matrices of type \p MatrixType. */ - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::Index Index; - - /** \brief Real scalar type for \p MatrixType. - * - * This is just \c Scalar if #Scalar is real (e.g., \c float or - * \c Scalar), and the type of the real part of \c Scalar if #Scalar is - * complex. - */ - typedef typename NumTraits<Scalar>::Real RealScalar; - - /** \brief Type for vector of eigenvalues as returned by eigenvalues(). - * - * This is a column vector with entries of type #RealScalar. - * The length of the vector is the size of \p nbrEigenvalues. - */ - typedef typename internal::plain_col_type<MatrixType, RealScalar>::type RealVectorType; - - /** \brief Default constructor. - * - * The default constructor is for cases in which the user intends to - * perform decompositions via compute(). - * - */ - ArpackGeneralizedSelfAdjointEigenSolver() - : m_eivec(), - m_eivalues(), - m_isInitialized(false), - m_eigenvectorsOk(false), - m_nbrConverged(0), - m_nbrIterations(0) - { } - - /** \brief Constructor; computes generalized eigenvalues of given matrix with respect to another matrix. - * - * \param[in] A Self-adjoint matrix whose eigenvalues / eigenvectors will - * computed. By default, the upper triangular part is used, but can be changed - * through the template parameter. - * \param[in] B Self-adjoint matrix for the generalized eigenvalue problem. - * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute. - * Must be less than the size of the input matrix, or an error is returned. - * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with - * respective meanings to find the largest magnitude , smallest magnitude, - * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this - * value can contain floating point value in string form, in which case the - * eigenvalues closest to this value will be found. - * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly. - * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which - * means machine precision. - * - * This constructor calls compute(const MatrixType&, const MatrixType&, Index, string, int, RealScalar) - * to compute the eigenvalues of the matrix \p A with respect to \p B. The eigenvectors are computed if - * \p options equals #ComputeEigenvectors. - * - */ - ArpackGeneralizedSelfAdjointEigenSolver(const MatrixType& A, const MatrixType& B, - Index nbrEigenvalues, std::string eigs_sigma="LM", - int options=ComputeEigenvectors, RealScalar tol=0.0) - : m_eivec(), - m_eivalues(), - m_isInitialized(false), - m_eigenvectorsOk(false), - m_nbrConverged(0), - m_nbrIterations(0) - { - compute(A, B, nbrEigenvalues, eigs_sigma, options, tol); - } - - /** \brief Constructor; computes eigenvalues of given matrix. - * - * \param[in] A Self-adjoint matrix whose eigenvalues / eigenvectors will - * computed. By default, the upper triangular part is used, but can be changed - * through the template parameter. - * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute. - * Must be less than the size of the input matrix, or an error is returned. - * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with - * respective meanings to find the largest magnitude , smallest magnitude, - * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this - * value can contain floating point value in string form, in which case the - * eigenvalues closest to this value will be found. - * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly. - * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which - * means machine precision. - * - * This constructor calls compute(const MatrixType&, Index, string, int, RealScalar) - * to compute the eigenvalues of the matrix \p A. The eigenvectors are computed if - * \p options equals #ComputeEigenvectors. - * - */ - - ArpackGeneralizedSelfAdjointEigenSolver(const MatrixType& A, - Index nbrEigenvalues, std::string eigs_sigma="LM", - int options=ComputeEigenvectors, RealScalar tol=0.0) - : m_eivec(), - m_eivalues(), - m_isInitialized(false), - m_eigenvectorsOk(false), - m_nbrConverged(0), - m_nbrIterations(0) - { - compute(A, nbrEigenvalues, eigs_sigma, options, tol); - } - - - /** \brief Computes generalized eigenvalues / eigenvectors of given matrix using the external ARPACK library. - * - * \param[in] A Selfadjoint matrix whose eigendecomposition is to be computed. - * \param[in] B Selfadjoint matrix for generalized eigenvalues. - * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute. - * Must be less than the size of the input matrix, or an error is returned. - * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with - * respective meanings to find the largest magnitude , smallest magnitude, - * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this - * value can contain floating point value in string form, in which case the - * eigenvalues closest to this value will be found. - * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly. - * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which - * means machine precision. - * - * \returns Reference to \c *this - * - * This function computes the generalized eigenvalues of \p A with respect to \p B using ARPACK. The eigenvalues() - * function can be used to retrieve them. If \p options equals #ComputeEigenvectors, - * then the eigenvectors are also computed and can be retrieved by - * calling eigenvectors(). - * - */ - ArpackGeneralizedSelfAdjointEigenSolver& compute(const MatrixType& A, const MatrixType& B, - Index nbrEigenvalues, std::string eigs_sigma="LM", - int options=ComputeEigenvectors, RealScalar tol=0.0); - - /** \brief Computes eigenvalues / eigenvectors of given matrix using the external ARPACK library. - * - * \param[in] A Selfadjoint matrix whose eigendecomposition is to be computed. - * \param[in] nbrEigenvalues The number of eigenvalues / eigenvectors to compute. - * Must be less than the size of the input matrix, or an error is returned. - * \param[in] eigs_sigma String containing either "LM", "SM", "LA", or "SA", with - * respective meanings to find the largest magnitude , smallest magnitude, - * largest algebraic, or smallest algebraic eigenvalues. Alternatively, this - * value can contain floating point value in string form, in which case the - * eigenvalues closest to this value will be found. - * \param[in] options Can be #ComputeEigenvectors (default) or #EigenvaluesOnly. - * \param[in] tol What tolerance to find the eigenvalues to. Default is 0, which - * means machine precision. - * - * \returns Reference to \c *this - * - * This function computes the eigenvalues of \p A using ARPACK. The eigenvalues() - * function can be used to retrieve them. If \p options equals #ComputeEigenvectors, - * then the eigenvectors are also computed and can be retrieved by - * calling eigenvectors(). - * - */ - ArpackGeneralizedSelfAdjointEigenSolver& compute(const MatrixType& A, - Index nbrEigenvalues, std::string eigs_sigma="LM", - int options=ComputeEigenvectors, RealScalar tol=0.0); - - - /** \brief Returns the eigenvectors of given matrix. - * - * \returns A const reference to the matrix whose columns are the eigenvectors. - * - * \pre The eigenvectors have been computed before. - * - * Column \f$ k \f$ of the returned matrix is an eigenvector corresponding - * to eigenvalue number \f$ k \f$ as returned by eigenvalues(). The - * eigenvectors are normalized to have (Euclidean) norm equal to one. If - * this object was used to solve the eigenproblem for the selfadjoint - * matrix \f$ A \f$, then the matrix returned by this function is the - * matrix \f$ V \f$ in the eigendecomposition \f$ A V = D V \f$. - * For the generalized eigenproblem, the matrix returned is the solution \f$ A V = D B V \f$ - * - * Example: \include SelfAdjointEigenSolver_eigenvectors.cpp - * Output: \verbinclude SelfAdjointEigenSolver_eigenvectors.out - * - * \sa eigenvalues() - */ - const Matrix<Scalar, Dynamic, Dynamic>& eigenvectors() const - { - eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized."); - eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); - return m_eivec; - } - - /** \brief Returns the eigenvalues of given matrix. - * - * \returns A const reference to the column vector containing the eigenvalues. - * - * \pre The eigenvalues have been computed before. - * - * The eigenvalues are repeated according to their algebraic multiplicity, - * so there are as many eigenvalues as rows in the matrix. The eigenvalues - * are sorted in increasing order. - * - * Example: \include SelfAdjointEigenSolver_eigenvalues.cpp - * Output: \verbinclude SelfAdjointEigenSolver_eigenvalues.out - * - * \sa eigenvectors(), MatrixBase::eigenvalues() - */ - const Matrix<Scalar, Dynamic, 1>& eigenvalues() const - { - eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized."); - return m_eivalues; - } - - /** \brief Computes the positive-definite square root of the matrix. - * - * \returns the positive-definite square root of the matrix - * - * \pre The eigenvalues and eigenvectors of a positive-definite matrix - * have been computed before. - * - * The square root of a positive-definite matrix \f$ A \f$ is the - * positive-definite matrix whose square equals \f$ A \f$. This function - * uses the eigendecomposition \f$ A = V D V^{-1} \f$ to compute the - * square root as \f$ A^{1/2} = V D^{1/2} V^{-1} \f$. - * - * Example: \include SelfAdjointEigenSolver_operatorSqrt.cpp - * Output: \verbinclude SelfAdjointEigenSolver_operatorSqrt.out - * - * \sa operatorInverseSqrt(), - * \ref MatrixFunctions_Module "MatrixFunctions Module" - */ - Matrix<Scalar, Dynamic, Dynamic> operatorSqrt() const - { - eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); - eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); - return m_eivec * m_eivalues.cwiseSqrt().asDiagonal() * m_eivec.adjoint(); - } - - /** \brief Computes the inverse square root of the matrix. - * - * \returns the inverse positive-definite square root of the matrix - * - * \pre The eigenvalues and eigenvectors of a positive-definite matrix - * have been computed before. - * - * This function uses the eigendecomposition \f$ A = V D V^{-1} \f$ to - * compute the inverse square root as \f$ V D^{-1/2} V^{-1} \f$. This is - * cheaper than first computing the square root with operatorSqrt() and - * then its inverse with MatrixBase::inverse(). - * - * Example: \include SelfAdjointEigenSolver_operatorInverseSqrt.cpp - * Output: \verbinclude SelfAdjointEigenSolver_operatorInverseSqrt.out - * - * \sa operatorSqrt(), MatrixBase::inverse(), - * \ref MatrixFunctions_Module "MatrixFunctions Module" - */ - Matrix<Scalar, Dynamic, Dynamic> operatorInverseSqrt() const - { - eigen_assert(m_isInitialized && "SelfAdjointEigenSolver is not initialized."); - eigen_assert(m_eigenvectorsOk && "The eigenvectors have not been computed together with the eigenvalues."); - return m_eivec * m_eivalues.cwiseInverse().cwiseSqrt().asDiagonal() * m_eivec.adjoint(); - } - - /** \brief Reports whether previous computation was successful. - * - * \returns \c Success if computation was succesful, \c NoConvergence otherwise. - */ - ComputationInfo info() const - { - eigen_assert(m_isInitialized && "ArpackGeneralizedSelfAdjointEigenSolver is not initialized."); - return m_info; - } - - size_t getNbrConvergedEigenValues() const - { return m_nbrConverged; } - - size_t getNbrIterations() const - { return m_nbrIterations; } - -protected: - Matrix<Scalar, Dynamic, Dynamic> m_eivec; - Matrix<Scalar, Dynamic, 1> m_eivalues; - ComputationInfo m_info; - bool m_isInitialized; - bool m_eigenvectorsOk; - - size_t m_nbrConverged; - size_t m_nbrIterations; -}; - - - - - -template<typename MatrixType, typename MatrixSolver, bool BisSPD> -ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>& - ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD> -::compute(const MatrixType& A, Index nbrEigenvalues, - std::string eigs_sigma, int options, RealScalar tol) -{ - MatrixType B(0,0); - compute(A, B, nbrEigenvalues, eigs_sigma, options, tol); - - return *this; -} - - -template<typename MatrixType, typename MatrixSolver, bool BisSPD> -ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD>& - ArpackGeneralizedSelfAdjointEigenSolver<MatrixType, MatrixSolver, BisSPD> -::compute(const MatrixType& A, const MatrixType& B, Index nbrEigenvalues, - std::string eigs_sigma, int options, RealScalar tol) -{ - eigen_assert(A.cols() == A.rows()); - eigen_assert(B.cols() == B.rows()); - eigen_assert(B.rows() == 0 || A.cols() == B.rows()); - eigen_assert((options &~ (EigVecMask | GenEigMask)) == 0 - && (options & EigVecMask) != EigVecMask - && "invalid option parameter"); - - bool isBempty = (B.rows() == 0) || (B.cols() == 0); - - // For clarity, all parameters match their ARPACK name - // - // Always 0 on the first call - // - int ido = 0; - - int n = (int)A.cols(); - - // User options: "LA", "SA", "SM", "LM", "BE" - // - char whch[3] = "LM"; - - // Specifies the shift if iparam[6] = { 3, 4, 5 }, not used if iparam[6] = { 1, 2 } - // - RealScalar sigma = 0.0; - - if (eigs_sigma.length() >= 2 && isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1])) - { - eigs_sigma[0] = toupper(eigs_sigma[0]); - eigs_sigma[1] = toupper(eigs_sigma[1]); - - // In the following special case we're going to invert the problem, since solving - // for larger magnitude is much much faster - // i.e., if 'SM' is specified, we're going to really use 'LM', the default - // - if (eigs_sigma.substr(0,2) != "SM") - { - whch[0] = eigs_sigma[0]; - whch[1] = eigs_sigma[1]; - } - } - else - { - eigen_assert(false && "Specifying clustered eigenvalues is not yet supported!"); - - // If it's not scalar values, then the user may be explicitly - // specifying the sigma value to cluster the evs around - // - sigma = atof(eigs_sigma.c_str()); - - // If atof fails, it returns 0.0, which is a fine default - // - } - - // "I" means normal eigenvalue problem, "G" means generalized - // - char bmat[2] = "I"; - if (eigs_sigma.substr(0,2) == "SM" || !(isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1])) || (!isBempty && !BisSPD)) - bmat[0] = 'G'; - - // Now we determine the mode to use - // - int mode = (bmat[0] == 'G') + 1; - if (eigs_sigma.substr(0,2) == "SM" || !(isalpha(eigs_sigma[0]) && isalpha(eigs_sigma[1]))) - { - // We're going to use shift-and-invert mode, and basically find - // the largest eigenvalues of the inverse operator - // - mode = 3; - } - - // The user-specified number of eigenvalues/vectors to compute - // - int nev = (int)nbrEigenvalues; - - // Allocate space for ARPACK to store the residual - // - Scalar *resid = new Scalar[n]; - - // Number of Lanczos vectors, must satisfy nev < ncv <= n - // Note that this indicates that nev != n, and we cannot compute - // all eigenvalues of a mtrix - // - int ncv = std::min(std::max(2*nev, 20), n); - - // The working n x ncv matrix, also store the final eigenvectors (if computed) - // - Scalar *v = new Scalar[n*ncv]; - int ldv = n; - - // Working space - // - Scalar *workd = new Scalar[3*n]; - int lworkl = ncv*ncv+8*ncv; // Must be at least this length - Scalar *workl = new Scalar[lworkl]; - - int *iparam= new int[11]; - iparam[0] = 1; // 1 means we let ARPACK perform the shifts, 0 means we'd have to do it - iparam[2] = std::max(300, (int)std::ceil(2*n/std::max(ncv,1))); - iparam[6] = mode; // The mode, 1 is standard ev problem, 2 for generalized ev, 3 for shift-and-invert - - // Used during reverse communicate to notify where arrays start - // - int *ipntr = new int[11]; - - // Error codes are returned in here, initial value of 0 indicates a random initial - // residual vector is used, any other values means resid contains the initial residual - // vector, possibly from a previous run - // - int info = 0; - - Scalar scale = 1.0; - //if (!isBempty) - //{ - //Scalar scale = B.norm() / std::sqrt(n); - //scale = std::pow(2, std::floor(std::log(scale+1))); - ////M /= scale; - //for (size_t i=0; i<(size_t)B.outerSize(); i++) - // for (typename MatrixType::InnerIterator it(B, i); it; ++it) - // it.valueRef() /= scale; - //} - - MatrixSolver OP; - if (mode == 1 || mode == 2) - { - if (!isBempty) - OP.compute(B); - } - else if (mode == 3) - { - if (sigma == 0.0) - { - OP.compute(A); - } - else - { - // Note: We will never enter here because sigma must be 0.0 - // - if (isBempty) - { - MatrixType AminusSigmaB(A); - for (Index i=0; i<A.rows(); ++i) - AminusSigmaB.coeffRef(i,i) -= sigma; - - OP.compute(AminusSigmaB); - } - else - { - MatrixType AminusSigmaB = A - sigma * B; - OP.compute(AminusSigmaB); - } - } - } - - if (!(mode == 1 && isBempty) && !(mode == 2 && isBempty) && OP.info() != Success) - std::cout << "Error factoring matrix" << std::endl; - - do - { - internal::arpack_wrapper<Scalar, RealScalar>::saupd(&ido, bmat, &n, whch, &nev, &tol, resid, - &ncv, v, &ldv, iparam, ipntr, workd, workl, - &lworkl, &info); - - if (ido == -1 || ido == 1) - { - Scalar *in = workd + ipntr[0] - 1; - Scalar *out = workd + ipntr[1] - 1; - - if (ido == 1 && mode != 2) - { - Scalar *out2 = workd + ipntr[2] - 1; - if (isBempty || mode == 1) - Matrix<Scalar, Dynamic, 1>::Map(out2, n) = Matrix<Scalar, Dynamic, 1>::Map(in, n); - else - Matrix<Scalar, Dynamic, 1>::Map(out2, n) = B * Matrix<Scalar, Dynamic, 1>::Map(in, n); - - in = workd + ipntr[2] - 1; - } - - if (mode == 1) - { - if (isBempty) - { - // OP = A - // - Matrix<Scalar, Dynamic, 1>::Map(out, n) = A * Matrix<Scalar, Dynamic, 1>::Map(in, n); - } - else - { - // OP = L^{-1}AL^{-T} - // - internal::OP<MatrixSolver, MatrixType, Scalar, BisSPD>::applyOP(OP, A, n, in, out); - } - } - else if (mode == 2) - { - if (ido == 1) - Matrix<Scalar, Dynamic, 1>::Map(in, n) = A * Matrix<Scalar, Dynamic, 1>::Map(in, n); - - // OP = B^{-1} A - // - Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(Matrix<Scalar, Dynamic, 1>::Map(in, n)); - } - else if (mode == 3) - { - // OP = (A-\sigmaB)B (\sigma could be 0, and B could be I) - // The B * in is already computed and stored at in if ido == 1 - // - if (ido == 1 || isBempty) - Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(Matrix<Scalar, Dynamic, 1>::Map(in, n)); - else - Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.solve(B * Matrix<Scalar, Dynamic, 1>::Map(in, n)); - } - } - else if (ido == 2) - { - Scalar *in = workd + ipntr[0] - 1; - Scalar *out = workd + ipntr[1] - 1; - - if (isBempty || mode == 1) - Matrix<Scalar, Dynamic, 1>::Map(out, n) = Matrix<Scalar, Dynamic, 1>::Map(in, n); - else - Matrix<Scalar, Dynamic, 1>::Map(out, n) = B * Matrix<Scalar, Dynamic, 1>::Map(in, n); - } - } while (ido != 99); - - if (info == 1) - m_info = NoConvergence; - else if (info == 3) - m_info = NumericalIssue; - else if (info < 0) - m_info = InvalidInput; - else if (info != 0) - eigen_assert(false && "Unknown ARPACK return value!"); - else - { - // Do we compute eigenvectors or not? - // - int rvec = (options & ComputeEigenvectors) == ComputeEigenvectors; - - // "A" means "All", use "S" to choose specific eigenvalues (not yet supported in ARPACK)) - // - char howmny[2] = "A"; - - // if howmny == "S", specifies the eigenvalues to compute (not implemented in ARPACK) - // - int *select = new int[ncv]; - - // Final eigenvalues - // - m_eivalues.resize(nev, 1); - - internal::arpack_wrapper<Scalar, RealScalar>::seupd(&rvec, howmny, select, m_eivalues.data(), v, &ldv, - &sigma, bmat, &n, whch, &nev, &tol, resid, &ncv, - v, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); - - if (info == -14) - m_info = NoConvergence; - else if (info != 0) - m_info = InvalidInput; - else - { - if (rvec) - { - m_eivec.resize(A.rows(), nev); - for (int i=0; i<nev; i++) - for (int j=0; j<n; j++) - m_eivec(j,i) = v[i*n+j] / scale; - - if (mode == 1 && !isBempty && BisSPD) - internal::OP<MatrixSolver, MatrixType, Scalar, BisSPD>::project(OP, n, nev, m_eivec.data()); - - m_eigenvectorsOk = true; - } - - m_nbrIterations = iparam[2]; - m_nbrConverged = iparam[4]; - - m_info = Success; - } - - delete[] select; - } - - delete[] v; - delete[] iparam; - delete[] ipntr; - delete[] workd; - delete[] workl; - delete[] resid; - - m_isInitialized = true; - - return *this; -} - - -// Single precision -// -extern "C" void ssaupd_(int *ido, char *bmat, int *n, char *which, - int *nev, float *tol, float *resid, int *ncv, - float *v, int *ldv, int *iparam, int *ipntr, - float *workd, float *workl, int *lworkl, - int *info); - -extern "C" void sseupd_(int *rvec, char *All, int *select, float *d, - float *z, int *ldz, float *sigma, - char *bmat, int *n, char *which, int *nev, - float *tol, float *resid, int *ncv, float *v, - int *ldv, int *iparam, int *ipntr, float *workd, - float *workl, int *lworkl, int *ierr); - -// Double precision -// -extern "C" void dsaupd_(int *ido, char *bmat, int *n, char *which, - int *nev, double *tol, double *resid, int *ncv, - double *v, int *ldv, int *iparam, int *ipntr, - double *workd, double *workl, int *lworkl, - int *info); - -extern "C" void dseupd_(int *rvec, char *All, int *select, double *d, - double *z, int *ldz, double *sigma, - char *bmat, int *n, char *which, int *nev, - double *tol, double *resid, int *ncv, double *v, - int *ldv, int *iparam, int *ipntr, double *workd, - double *workl, int *lworkl, int *ierr); - - -namespace internal { - -template<typename Scalar, typename RealScalar> struct arpack_wrapper -{ - static inline void saupd(int *ido, char *bmat, int *n, char *which, - int *nev, RealScalar *tol, Scalar *resid, int *ncv, - Scalar *v, int *ldv, int *iparam, int *ipntr, - Scalar *workd, Scalar *workl, int *lworkl, int *info) - { - EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL) - } - - static inline void seupd(int *rvec, char *All, int *select, Scalar *d, - Scalar *z, int *ldz, RealScalar *sigma, - char *bmat, int *n, char *which, int *nev, - RealScalar *tol, Scalar *resid, int *ncv, Scalar *v, - int *ldv, int *iparam, int *ipntr, Scalar *workd, - Scalar *workl, int *lworkl, int *ierr) - { - EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL) - } -}; - -template <> struct arpack_wrapper<float, float> -{ - static inline void saupd(int *ido, char *bmat, int *n, char *which, - int *nev, float *tol, float *resid, int *ncv, - float *v, int *ldv, int *iparam, int *ipntr, - float *workd, float *workl, int *lworkl, int *info) - { - ssaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info); - } - - static inline void seupd(int *rvec, char *All, int *select, float *d, - float *z, int *ldz, float *sigma, - char *bmat, int *n, char *which, int *nev, - float *tol, float *resid, int *ncv, float *v, - int *ldv, int *iparam, int *ipntr, float *workd, - float *workl, int *lworkl, int *ierr) - { - sseupd_(rvec, All, select, d, z, ldz, sigma, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, - workd, workl, lworkl, ierr); - } -}; - -template <> struct arpack_wrapper<double, double> -{ - static inline void saupd(int *ido, char *bmat, int *n, char *which, - int *nev, double *tol, double *resid, int *ncv, - double *v, int *ldv, int *iparam, int *ipntr, - double *workd, double *workl, int *lworkl, int *info) - { - dsaupd_(ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info); - } - - static inline void seupd(int *rvec, char *All, int *select, double *d, - double *z, int *ldz, double *sigma, - char *bmat, int *n, char *which, int *nev, - double *tol, double *resid, int *ncv, double *v, - int *ldv, int *iparam, int *ipntr, double *workd, - double *workl, int *lworkl, int *ierr) - { - dseupd_(rvec, All, select, d, v, ldv, sigma, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam, ipntr, - workd, workl, lworkl, ierr); - } -}; - - -template<typename MatrixSolver, typename MatrixType, typename Scalar, bool BisSPD> -struct OP -{ - static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out); - static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs); -}; - -template<typename MatrixSolver, typename MatrixType, typename Scalar> -struct OP<MatrixSolver, MatrixType, Scalar, true> -{ - static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out) -{ - // OP = L^{-1} A L^{-T} (B = LL^T) - // - // First solve L^T out = in - // - Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.matrixU().solve(Matrix<Scalar, Dynamic, 1>::Map(in, n)); - Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.permutationPinv() * Matrix<Scalar, Dynamic, 1>::Map(out, n); - - // Then compute out = A out - // - Matrix<Scalar, Dynamic, 1>::Map(out, n) = A * Matrix<Scalar, Dynamic, 1>::Map(out, n); - - // Then solve L out = out - // - Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.permutationP() * Matrix<Scalar, Dynamic, 1>::Map(out, n); - Matrix<Scalar, Dynamic, 1>::Map(out, n) = OP.matrixL().solve(Matrix<Scalar, Dynamic, 1>::Map(out, n)); -} - - static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs) -{ - // Solve L^T out = in - // - Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k) = OP.matrixU().solve(Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k)); - Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k) = OP.permutationPinv() * Matrix<Scalar, Dynamic, Dynamic>::Map(vecs, n, k); -} - -}; - -template<typename MatrixSolver, typename MatrixType, typename Scalar> -struct OP<MatrixSolver, MatrixType, Scalar, false> -{ - static inline void applyOP(MatrixSolver &OP, const MatrixType &A, int n, Scalar *in, Scalar *out) -{ - eigen_assert(false && "Should never be in here..."); -} - - static inline void project(MatrixSolver &OP, int n, int k, Scalar *vecs) -{ - eigen_assert(false && "Should never be in here..."); -} - -}; - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_ARPACKSELFADJOINTEIGENSOLVER_H - diff --git a/eigen/unsupported/Eigen/src/EulerAngles/CMakeLists.txt b/eigen/unsupported/Eigen/src/EulerAngles/CMakeLists.txt deleted file mode 100644 index 40af550..0000000 --- a/eigen/unsupported/Eigen/src/EulerAngles/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FILE(GLOB Eigen_EulerAngles_SRCS "*.h") - -INSTALL(FILES - ${Eigen_EulerAngles_SRCS} - DESTINATION ${INCLUDE_INSTALL_DIR}/unsupported/Eigen/src/EulerAngles COMPONENT Devel - ) diff --git a/eigen/unsupported/Eigen/src/EulerAngles/EulerAngles.h b/eigen/unsupported/Eigen/src/EulerAngles/EulerAngles.h deleted file mode 100644 index 13a0da1..0000000 --- a/eigen/unsupported/Eigen/src/EulerAngles/EulerAngles.h +++ /dev/null @@ -1,386 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2015 Tal Hadad <tal_hd@hotmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_EULERANGLESCLASS_H// TODO: Fix previous "EIGEN_EULERANGLES_H" definition? -#define EIGEN_EULERANGLESCLASS_H - -namespace Eigen -{ - /*template<typename Other, - int OtherRows=Other::RowsAtCompileTime, - int OtherCols=Other::ColsAtCompileTime> - struct ei_eulerangles_assign_impl;*/ - - /** \class EulerAngles - * - * \ingroup EulerAngles_Module - * - * \brief Represents a rotation in a 3 dimensional space as three Euler angles. - * - * Euler rotation is a set of three rotation of three angles over three fixed axes, defined by the EulerSystem given as a template parameter. - * - * Here is how intrinsic Euler angles works: - * - first, rotate the axes system over the alpha axis in angle alpha - * - then, rotate the axes system over the beta axis(which was rotated in the first stage) in angle beta - * - then, rotate the axes system over the gamma axis(which was rotated in the two stages above) in angle gamma - * - * \note This class support only intrinsic Euler angles for simplicity, - * see EulerSystem how to easily overcome this for extrinsic systems. - * - * ### Rotation representation and conversions ### - * - * It has been proved(see Wikipedia link below) that every rotation can be represented - * by Euler angles, but there is no singular representation (e.g. unlike rotation matrices). - * Therefore, you can convert from Eigen rotation and to them - * (including rotation matrices, which is not called "rotations" by Eigen design). - * - * Euler angles usually used for: - * - convenient human representation of rotation, especially in interactive GUI. - * - gimbal systems and robotics - * - efficient encoding(i.e. 3 floats only) of rotation for network protocols. - * - * However, Euler angles are slow comparing to quaternion or matrices, - * because their unnatural math definition, although it's simple for human. - * To overcome this, this class provide easy movement from the math friendly representation - * to the human friendly representation, and vise-versa. - * - * All the user need to do is a safe simple C++ type conversion, - * and this class take care for the math. - * Additionally, some axes related computation is done in compile time. - * - * #### Euler angles ranges in conversions #### - * - * When converting some rotation to Euler angles, there are some ways you can guarantee - * the Euler angles ranges. - * - * #### implicit ranges #### - * When using implicit ranges, all angles are guarantee to be in the range [-PI, +PI], - * unless you convert from some other Euler angles. - * In this case, the range is __undefined__ (might be even less than -PI or greater than +2*PI). - * \sa EulerAngles(const MatrixBase<Derived>&) - * \sa EulerAngles(const RotationBase<Derived, 3>&) - * - * #### explicit ranges #### - * When using explicit ranges, all angles are guarantee to be in the range you choose. - * In the range Boolean parameter, you're been ask whether you prefer the positive range or not: - * - _true_ - force the range between [0, +2*PI] - * - _false_ - force the range between [-PI, +PI] - * - * ##### compile time ranges ##### - * This is when you have compile time ranges and you prefer to - * use template parameter. (e.g. for performance) - * \sa FromRotation() - * - * ##### run-time time ranges ##### - * Run-time ranges are also supported. - * \sa EulerAngles(const MatrixBase<Derived>&, bool, bool, bool) - * \sa EulerAngles(const RotationBase<Derived, 3>&, bool, bool, bool) - * - * ### Convenient user typedefs ### - * - * Convenient typedefs for EulerAngles exist for float and double scalar, - * in a form of EulerAngles{A}{B}{C}{scalar}, - * e.g. \ref EulerAnglesXYZd, \ref EulerAnglesZYZf. - * - * Only for positive axes{+x,+y,+z} Euler systems are have convenient typedef. - * If you need negative axes{-x,-y,-z}, it is recommended to create you own typedef with - * a word that represent what you need. - * - * ### Example ### - * - * \include EulerAngles.cpp - * Output: \verbinclude EulerAngles.out - * - * ### Additional reading ### - * - * If you're want to get more idea about how Euler system work in Eigen see EulerSystem. - * - * More information about Euler angles: https://en.wikipedia.org/wiki/Euler_angles - * - * \tparam _Scalar the scalar type, i.e., the type of the angles. - * - * \tparam _System the EulerSystem to use, which represents the axes of rotation. - */ - template <typename _Scalar, class _System> - class EulerAngles : public RotationBase<EulerAngles<_Scalar, _System>, 3> - { - public: - /** the scalar type of the angles */ - typedef _Scalar Scalar; - - /** the EulerSystem to use, which represents the axes of rotation. */ - typedef _System System; - - typedef Matrix<Scalar,3,3> Matrix3; /*!< the equivalent rotation matrix type */ - typedef Matrix<Scalar,3,1> Vector3; /*!< the equivalent 3 dimension vector type */ - typedef Quaternion<Scalar> QuaternionType; /*!< the equivalent quaternion type */ - typedef AngleAxis<Scalar> AngleAxisType; /*!< the equivalent angle-axis type */ - - /** \returns the axis vector of the first (alpha) rotation */ - static Vector3 AlphaAxisVector() { - const Vector3& u = Vector3::Unit(System::AlphaAxisAbs - 1); - return System::IsAlphaOpposite ? -u : u; - } - - /** \returns the axis vector of the second (beta) rotation */ - static Vector3 BetaAxisVector() { - const Vector3& u = Vector3::Unit(System::BetaAxisAbs - 1); - return System::IsBetaOpposite ? -u : u; - } - - /** \returns the axis vector of the third (gamma) rotation */ - static Vector3 GammaAxisVector() { - const Vector3& u = Vector3::Unit(System::GammaAxisAbs - 1); - return System::IsGammaOpposite ? -u : u; - } - - private: - Vector3 m_angles; - - public: - /** Default constructor without initialization. */ - EulerAngles() {} - /** Constructs and initialize Euler angles(\p alpha, \p beta, \p gamma). */ - EulerAngles(const Scalar& alpha, const Scalar& beta, const Scalar& gamma) : - m_angles(alpha, beta, gamma) {} - - /** Constructs and initialize Euler angles from a 3x3 rotation matrix \p m. - * - * \note All angles will be in the range [-PI, PI]. - */ - template<typename Derived> - EulerAngles(const MatrixBase<Derived>& m) { *this = m; } - - /** Constructs and initialize Euler angles from a 3x3 rotation matrix \p m, - * with options to choose for each angle the requested range. - * - * If positive range is true, then the specified angle will be in the range [0, +2*PI]. - * Otherwise, the specified angle will be in the range [-PI, +PI]. - * - * \param m The 3x3 rotation matrix to convert - * \param positiveRangeAlpha If true, alpha will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \param positiveRangeBeta If true, beta will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \param positiveRangeGamma If true, gamma will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - */ - template<typename Derived> - EulerAngles( - const MatrixBase<Derived>& m, - bool positiveRangeAlpha, - bool positiveRangeBeta, - bool positiveRangeGamma) { - - System::CalcEulerAngles(*this, m, positiveRangeAlpha, positiveRangeBeta, positiveRangeGamma); - } - - /** Constructs and initialize Euler angles from a rotation \p rot. - * - * \note All angles will be in the range [-PI, PI], unless \p rot is an EulerAngles. - * If rot is an EulerAngles, expected EulerAngles range is __undefined__. - * (Use other functions here for enforcing range if this effect is desired) - */ - template<typename Derived> - EulerAngles(const RotationBase<Derived, 3>& rot) { *this = rot; } - - /** Constructs and initialize Euler angles from a rotation \p rot, - * with options to choose for each angle the requested range. - * - * If positive range is true, then the specified angle will be in the range [0, +2*PI]. - * Otherwise, the specified angle will be in the range [-PI, +PI]. - * - * \param rot The 3x3 rotation matrix to convert - * \param positiveRangeAlpha If true, alpha will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \param positiveRangeBeta If true, beta will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \param positiveRangeGamma If true, gamma will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - */ - template<typename Derived> - EulerAngles( - const RotationBase<Derived, 3>& rot, - bool positiveRangeAlpha, - bool positiveRangeBeta, - bool positiveRangeGamma) { - - System::CalcEulerAngles(*this, rot.toRotationMatrix(), positiveRangeAlpha, positiveRangeBeta, positiveRangeGamma); - } - - /** \returns The angle values stored in a vector (alpha, beta, gamma). */ - const Vector3& angles() const { return m_angles; } - /** \returns A read-write reference to the angle values stored in a vector (alpha, beta, gamma). */ - Vector3& angles() { return m_angles; } - - /** \returns The value of the first angle. */ - Scalar alpha() const { return m_angles[0]; } - /** \returns A read-write reference to the angle of the first angle. */ - Scalar& alpha() { return m_angles[0]; } - - /** \returns The value of the second angle. */ - Scalar beta() const { return m_angles[1]; } - /** \returns A read-write reference to the angle of the second angle. */ - Scalar& beta() { return m_angles[1]; } - - /** \returns The value of the third angle. */ - Scalar gamma() const { return m_angles[2]; } - /** \returns A read-write reference to the angle of the third angle. */ - Scalar& gamma() { return m_angles[2]; } - - /** \returns The Euler angles rotation inverse (which is as same as the negative), - * (-alpha, -beta, -gamma). - */ - EulerAngles inverse() const - { - EulerAngles res; - res.m_angles = -m_angles; - return res; - } - - /** \returns The Euler angles rotation negative (which is as same as the inverse), - * (-alpha, -beta, -gamma). - */ - EulerAngles operator -() const - { - return inverse(); - } - - /** Constructs and initialize Euler angles from a 3x3 rotation matrix \p m, - * with options to choose for each angle the requested range (__only in compile time__). - * - * If positive range is true, then the specified angle will be in the range [0, +2*PI]. - * Otherwise, the specified angle will be in the range [-PI, +PI]. - * - * \param m The 3x3 rotation matrix to convert - * \tparam positiveRangeAlpha If true, alpha will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \tparam positiveRangeBeta If true, beta will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \tparam positiveRangeGamma If true, gamma will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - */ - template< - bool PositiveRangeAlpha, - bool PositiveRangeBeta, - bool PositiveRangeGamma, - typename Derived> - static EulerAngles FromRotation(const MatrixBase<Derived>& m) - { - EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived, 3, 3) - - EulerAngles e; - System::template CalcEulerAngles< - PositiveRangeAlpha, PositiveRangeBeta, PositiveRangeGamma, _Scalar>(e, m); - return e; - } - - /** Constructs and initialize Euler angles from a rotation \p rot, - * with options to choose for each angle the requested range (__only in compile time__). - * - * If positive range is true, then the specified angle will be in the range [0, +2*PI]. - * Otherwise, the specified angle will be in the range [-PI, +PI]. - * - * \param rot The 3x3 rotation matrix to convert - * \tparam positiveRangeAlpha If true, alpha will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \tparam positiveRangeBeta If true, beta will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - * \tparam positiveRangeGamma If true, gamma will be in [0, 2*PI]. Otherwise, in [-PI, +PI]. - */ - template< - bool PositiveRangeAlpha, - bool PositiveRangeBeta, - bool PositiveRangeGamma, - typename Derived> - static EulerAngles FromRotation(const RotationBase<Derived, 3>& rot) - { - return FromRotation<PositiveRangeAlpha, PositiveRangeBeta, PositiveRangeGamma>(rot.toRotationMatrix()); - } - - /*EulerAngles& fromQuaternion(const QuaternionType& q) - { - // TODO: Implement it in a faster way for quaternions - // According to http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/ - // we can compute only the needed matrix cells and then convert to euler angles. (see ZYX example below) - // Currently we compute all matrix cells from quaternion. - - // Special case only for ZYX - //Scalar y2 = q.y() * q.y(); - //m_angles[0] = std::atan2(2*(q.w()*q.z() + q.x()*q.y()), (1 - 2*(y2 + q.z()*q.z()))); - //m_angles[1] = std::asin( 2*(q.w()*q.y() - q.z()*q.x())); - //m_angles[2] = std::atan2(2*(q.w()*q.x() + q.y()*q.z()), (1 - 2*(q.x()*q.x() + y2))); - }*/ - - /** Set \c *this from a rotation matrix(i.e. pure orthogonal matrix with determinant of +1). */ - template<typename Derived> - EulerAngles& operator=(const MatrixBase<Derived>& m) { - EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived, 3, 3) - - System::CalcEulerAngles(*this, m); - return *this; - } - - // TODO: Assign and construct from another EulerAngles (with different system) - - /** Set \c *this from a rotation. */ - template<typename Derived> - EulerAngles& operator=(const RotationBase<Derived, 3>& rot) { - System::CalcEulerAngles(*this, rot.toRotationMatrix()); - return *this; - } - - // TODO: Support isApprox function - - /** \returns an equivalent 3x3 rotation matrix. */ - Matrix3 toRotationMatrix() const - { - return static_cast<QuaternionType>(*this).toRotationMatrix(); - } - - /** Convert the Euler angles to quaternion. */ - operator QuaternionType() const - { - return - AngleAxisType(alpha(), AlphaAxisVector()) * - AngleAxisType(beta(), BetaAxisVector()) * - AngleAxisType(gamma(), GammaAxisVector()); - } - - friend std::ostream& operator<<(std::ostream& s, const EulerAngles<Scalar, System>& eulerAngles) - { - s << eulerAngles.angles().transpose(); - return s; - } - }; - -#define EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(AXES, SCALAR_TYPE, SCALAR_POSTFIX) \ - /** \ingroup EulerAngles_Module */ \ - typedef EulerAngles<SCALAR_TYPE, EulerSystem##AXES> EulerAngles##AXES##SCALAR_POSTFIX; - -#define EIGEN_EULER_ANGLES_TYPEDEFS(SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(XYZ, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(XYX, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(XZY, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(XZX, SCALAR_TYPE, SCALAR_POSTFIX) \ - \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(YZX, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(YZY, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(YXZ, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(YXY, SCALAR_TYPE, SCALAR_POSTFIX) \ - \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(ZXY, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(ZXZ, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(ZYX, SCALAR_TYPE, SCALAR_POSTFIX) \ - EIGEN_EULER_ANGLES_SINGLE_TYPEDEF(ZYZ, SCALAR_TYPE, SCALAR_POSTFIX) - -EIGEN_EULER_ANGLES_TYPEDEFS(float, f) -EIGEN_EULER_ANGLES_TYPEDEFS(double, d) - - namespace internal - { - template<typename _Scalar, class _System> - struct traits<EulerAngles<_Scalar, _System> > - { - typedef _Scalar Scalar; - }; - } - -} - -#endif // EIGEN_EULERANGLESCLASS_H diff --git a/eigen/unsupported/Eigen/src/EulerAngles/EulerSystem.h b/eigen/unsupported/Eigen/src/EulerAngles/EulerSystem.h deleted file mode 100644 index 98f9f64..0000000 --- a/eigen/unsupported/Eigen/src/EulerAngles/EulerSystem.h +++ /dev/null @@ -1,326 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2015 Tal Hadad <tal_hd@hotmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_EULERSYSTEM_H -#define EIGEN_EULERSYSTEM_H - -namespace Eigen -{ - // Forward declerations - template <typename _Scalar, class _System> - class EulerAngles; - - namespace internal - { - // TODO: Check if already exists on the rest API - template <int Num, bool IsPositive = (Num > 0)> - struct Abs - { - enum { value = Num }; - }; - - template <int Num> - struct Abs<Num, false> - { - enum { value = -Num }; - }; - - template <int Axis> - struct IsValidAxis - { - enum { value = Axis != 0 && Abs<Axis>::value <= 3 }; - }; - } - - #define EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1] - - /** \brief Representation of a fixed signed rotation axis for EulerSystem. - * - * \ingroup EulerAngles_Module - * - * Values here represent: - * - The axis of the rotation: X, Y or Z. - * - The sign (i.e. direction of the rotation along the axis): positive(+) or negative(-) - * - * Therefore, this could express all the axes {+X,+Y,+Z,-X,-Y,-Z} - * - * For positive axis, use +EULER_{axis}, and for negative axis use -EULER_{axis}. - */ - enum EulerAxis - { - EULER_X = 1, /*!< the X axis */ - EULER_Y = 2, /*!< the Y axis */ - EULER_Z = 3 /*!< the Z axis */ - }; - - /** \class EulerSystem - * - * \ingroup EulerAngles_Module - * - * \brief Represents a fixed Euler rotation system. - * - * This meta-class goal is to represent the Euler system in compilation time, for EulerAngles. - * - * You can use this class to get two things: - * - Build an Euler system, and then pass it as a template parameter to EulerAngles. - * - Query some compile time data about an Euler system. (e.g. Whether it's tait bryan) - * - * Euler rotation is a set of three rotation on fixed axes. (see \ref EulerAngles) - * This meta-class store constantly those signed axes. (see \ref EulerAxis) - * - * ### Types of Euler systems ### - * - * All and only valid 3 dimension Euler rotation over standard - * signed axes{+X,+Y,+Z,-X,-Y,-Z} are supported: - * - all axes X, Y, Z in each valid order (see below what order is valid) - * - rotation over the axis is supported both over the positive and negative directions. - * - both tait bryan and proper/classic Euler angles (i.e. the opposite). - * - * Since EulerSystem support both positive and negative directions, - * you may call this rotation distinction in other names: - * - _right handed_ or _left handed_ - * - _counterclockwise_ or _clockwise_ - * - * Notice all axed combination are valid, and would trigger a static assertion. - * Same unsigned axes can't be neighbors, e.g. {X,X,Y} is invalid. - * This yield two and only two classes: - * - _tait bryan_ - all unsigned axes are distinct, e.g. {X,Y,Z} - * - _proper/classic Euler angles_ - The first and the third unsigned axes is equal, - * and the second is different, e.g. {X,Y,X} - * - * ### Intrinsic vs extrinsic Euler systems ### - * - * Only intrinsic Euler systems are supported for simplicity. - * If you want to use extrinsic Euler systems, - * just use the equal intrinsic opposite order for axes and angles. - * I.e axes (A,B,C) becomes (C,B,A), and angles (a,b,c) becomes (c,b,a). - * - * ### Convenient user typedefs ### - * - * Convenient typedefs for EulerSystem exist (only for positive axes Euler systems), - * in a form of EulerSystem{A}{B}{C}, e.g. \ref EulerSystemXYZ. - * - * ### Additional reading ### - * - * More information about Euler angles: https://en.wikipedia.org/wiki/Euler_angles - * - * \tparam _AlphaAxis the first fixed EulerAxis - * - * \tparam _AlphaAxis the second fixed EulerAxis - * - * \tparam _AlphaAxis the third fixed EulerAxis - */ - template <int _AlphaAxis, int _BetaAxis, int _GammaAxis> - class EulerSystem - { - public: - // It's defined this way and not as enum, because I think - // that enum is not guerantee to support negative numbers - - /** The first rotation axis */ - static const int AlphaAxis = _AlphaAxis; - - /** The second rotation axis */ - static const int BetaAxis = _BetaAxis; - - /** The third rotation axis */ - static const int GammaAxis = _GammaAxis; - - enum - { - AlphaAxisAbs = internal::Abs<AlphaAxis>::value, /*!< the first rotation axis unsigned */ - BetaAxisAbs = internal::Abs<BetaAxis>::value, /*!< the second rotation axis unsigned */ - GammaAxisAbs = internal::Abs<GammaAxis>::value, /*!< the third rotation axis unsigned */ - - IsAlphaOpposite = (AlphaAxis < 0) ? 1 : 0, /*!< weather alpha axis is negative */ - IsBetaOpposite = (BetaAxis < 0) ? 1 : 0, /*!< weather beta axis is negative */ - IsGammaOpposite = (GammaAxis < 0) ? 1 : 0, /*!< weather gamma axis is negative */ - - IsOdd = ((AlphaAxisAbs)%3 == (BetaAxisAbs - 1)%3) ? 0 : 1, /*!< weather the Euler system is odd */ - IsEven = IsOdd ? 0 : 1, /*!< weather the Euler system is even */ - - IsTaitBryan = ((unsigned)AlphaAxisAbs != (unsigned)GammaAxisAbs) ? 1 : 0 /*!< weather the Euler system is tait bryan */ - }; - - private: - - EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(internal::IsValidAxis<AlphaAxis>::value, - ALPHA_AXIS_IS_INVALID); - - EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(internal::IsValidAxis<BetaAxis>::value, - BETA_AXIS_IS_INVALID); - - EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT(internal::IsValidAxis<GammaAxis>::value, - GAMMA_AXIS_IS_INVALID); - - EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT((unsigned)AlphaAxisAbs != (unsigned)BetaAxisAbs, - ALPHA_AXIS_CANT_BE_EQUAL_TO_BETA_AXIS); - - EIGEN_EULER_ANGLES_CLASS_STATIC_ASSERT((unsigned)BetaAxisAbs != (unsigned)GammaAxisAbs, - BETA_AXIS_CANT_BE_EQUAL_TO_GAMMA_AXIS); - - enum - { - // I, J, K are the pivot indexes permutation for the rotation matrix, that match this Euler system. - // They are used in this class converters. - // They are always different from each other, and their possible values are: 0, 1, or 2. - I = AlphaAxisAbs - 1, - J = (AlphaAxisAbs - 1 + 1 + IsOdd)%3, - K = (AlphaAxisAbs - 1 + 2 - IsOdd)%3 - }; - - // TODO: Get @mat parameter in form that avoids double evaluation. - template <typename Derived> - static void CalcEulerAngles_imp(Matrix<typename MatrixBase<Derived>::Scalar, 3, 1>& res, const MatrixBase<Derived>& mat, internal::true_type /*isTaitBryan*/) - { - using std::atan2; - using std::sin; - using std::cos; - - typedef typename Derived::Scalar Scalar; - typedef Matrix<Scalar,2,1> Vector2; - - res[0] = atan2(mat(J,K), mat(K,K)); - Scalar c2 = Vector2(mat(I,I), mat(I,J)).norm(); - if((IsOdd && res[0]<Scalar(0)) || ((!IsOdd) && res[0]>Scalar(0))) { - if(res[0] > Scalar(0)) { - res[0] -= Scalar(EIGEN_PI); - } - else { - res[0] += Scalar(EIGEN_PI); - } - res[1] = atan2(-mat(I,K), -c2); - } - else - res[1] = atan2(-mat(I,K), c2); - Scalar s1 = sin(res[0]); - Scalar c1 = cos(res[0]); - res[2] = atan2(s1*mat(K,I)-c1*mat(J,I), c1*mat(J,J) - s1 * mat(K,J)); - } - - template <typename Derived> - static void CalcEulerAngles_imp(Matrix<typename MatrixBase<Derived>::Scalar,3,1>& res, const MatrixBase<Derived>& mat, internal::false_type /*isTaitBryan*/) - { - using std::atan2; - using std::sin; - using std::cos; - - typedef typename Derived::Scalar Scalar; - typedef Matrix<Scalar,2,1> Vector2; - - res[0] = atan2(mat(J,I), mat(K,I)); - if((IsOdd && res[0]<Scalar(0)) || ((!IsOdd) && res[0]>Scalar(0))) - { - if(res[0] > Scalar(0)) { - res[0] -= Scalar(EIGEN_PI); - } - else { - res[0] += Scalar(EIGEN_PI); - } - Scalar s2 = Vector2(mat(J,I), mat(K,I)).norm(); - res[1] = -atan2(s2, mat(I,I)); - } - else - { - Scalar s2 = Vector2(mat(J,I), mat(K,I)).norm(); - res[1] = atan2(s2, mat(I,I)); - } - - // With a=(0,1,0), we have i=0; j=1; k=2, and after computing the first two angles, - // we can compute their respective rotation, and apply its inverse to M. Since the result must - // be a rotation around x, we have: - // - // c2 s1.s2 c1.s2 1 0 0 - // 0 c1 -s1 * M = 0 c3 s3 - // -s2 s1.c2 c1.c2 0 -s3 c3 - // - // Thus: m11.c1 - m21.s1 = c3 & m12.c1 - m22.s1 = s3 - - Scalar s1 = sin(res[0]); - Scalar c1 = cos(res[0]); - res[2] = atan2(c1*mat(J,K)-s1*mat(K,K), c1*mat(J,J) - s1 * mat(K,J)); - } - - template<typename Scalar> - static void CalcEulerAngles( - EulerAngles<Scalar, EulerSystem>& res, - const typename EulerAngles<Scalar, EulerSystem>::Matrix3& mat) - { - CalcEulerAngles(res, mat, false, false, false); - } - - template< - bool PositiveRangeAlpha, - bool PositiveRangeBeta, - bool PositiveRangeGamma, - typename Scalar> - static void CalcEulerAngles( - EulerAngles<Scalar, EulerSystem>& res, - const typename EulerAngles<Scalar, EulerSystem>::Matrix3& mat) - { - CalcEulerAngles(res, mat, PositiveRangeAlpha, PositiveRangeBeta, PositiveRangeGamma); - } - - template<typename Scalar> - static void CalcEulerAngles( - EulerAngles<Scalar, EulerSystem>& res, - const typename EulerAngles<Scalar, EulerSystem>::Matrix3& mat, - bool PositiveRangeAlpha, - bool PositiveRangeBeta, - bool PositiveRangeGamma) - { - CalcEulerAngles_imp( - res.angles(), mat, - typename internal::conditional<IsTaitBryan, internal::true_type, internal::false_type>::type()); - - if (IsAlphaOpposite == IsOdd) - res.alpha() = -res.alpha(); - - if (IsBetaOpposite == IsOdd) - res.beta() = -res.beta(); - - if (IsGammaOpposite == IsOdd) - res.gamma() = -res.gamma(); - - // Saturate results to the requested range - if (PositiveRangeAlpha && (res.alpha() < 0)) - res.alpha() += Scalar(2 * EIGEN_PI); - - if (PositiveRangeBeta && (res.beta() < 0)) - res.beta() += Scalar(2 * EIGEN_PI); - - if (PositiveRangeGamma && (res.gamma() < 0)) - res.gamma() += Scalar(2 * EIGEN_PI); - } - - template <typename _Scalar, class _System> - friend class Eigen::EulerAngles; - }; - -#define EIGEN_EULER_SYSTEM_TYPEDEF(A, B, C) \ - /** \ingroup EulerAngles_Module */ \ - typedef EulerSystem<EULER_##A, EULER_##B, EULER_##C> EulerSystem##A##B##C; - - EIGEN_EULER_SYSTEM_TYPEDEF(X,Y,Z) - EIGEN_EULER_SYSTEM_TYPEDEF(X,Y,X) - EIGEN_EULER_SYSTEM_TYPEDEF(X,Z,Y) - EIGEN_EULER_SYSTEM_TYPEDEF(X,Z,X) - - EIGEN_EULER_SYSTEM_TYPEDEF(Y,Z,X) - EIGEN_EULER_SYSTEM_TYPEDEF(Y,Z,Y) - EIGEN_EULER_SYSTEM_TYPEDEF(Y,X,Z) - EIGEN_EULER_SYSTEM_TYPEDEF(Y,X,Y) - - EIGEN_EULER_SYSTEM_TYPEDEF(Z,X,Y) - EIGEN_EULER_SYSTEM_TYPEDEF(Z,X,Z) - EIGEN_EULER_SYSTEM_TYPEDEF(Z,Y,X) - EIGEN_EULER_SYSTEM_TYPEDEF(Z,Y,Z) -} - -#endif // EIGEN_EULERSYSTEM_H diff --git a/eigen/unsupported/Eigen/src/FFT/ei_fftw_impl.h b/eigen/unsupported/Eigen/src/FFT/ei_fftw_impl.h deleted file mode 100644 index d49aa17..0000000 --- a/eigen/unsupported/Eigen/src/FFT/ei_fftw_impl.h +++ /dev/null @@ -1,261 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Mark Borgerding mark a borgerding net -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -namespace Eigen { - -namespace internal { - - // FFTW uses non-const arguments - // so we must use ugly const_cast calls for all the args it uses - // - // This should be safe as long as - // 1. we use FFTW_ESTIMATE for all our planning - // see the FFTW docs section 4.3.2 "Planner Flags" - // 2. fftw_complex is compatible with std::complex - // This assumes std::complex<T> layout is array of size 2 with real,imag - template <typename T> - inline - T * fftw_cast(const T* p) - { - return const_cast<T*>( p); - } - - inline - fftw_complex * fftw_cast( const std::complex<double> * p) - { - return const_cast<fftw_complex*>( reinterpret_cast<const fftw_complex*>(p) ); - } - - inline - fftwf_complex * fftw_cast( const std::complex<float> * p) - { - return const_cast<fftwf_complex*>( reinterpret_cast<const fftwf_complex*>(p) ); - } - - inline - fftwl_complex * fftw_cast( const std::complex<long double> * p) - { - return const_cast<fftwl_complex*>( reinterpret_cast<const fftwl_complex*>(p) ); - } - - template <typename T> - struct fftw_plan {}; - - template <> - struct fftw_plan<float> - { - typedef float scalar_type; - typedef fftwf_complex complex_type; - fftwf_plan m_plan; - fftw_plan() :m_plan(NULL) {} - ~fftw_plan() {if (m_plan) fftwf_destroy_plan(m_plan);} - - inline - void fwd(complex_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftwf_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwf_execute_dft( m_plan, src,dst); - } - inline - void inv(complex_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftwf_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwf_execute_dft( m_plan, src,dst); - } - inline - void fwd(complex_type * dst,scalar_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftwf_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwf_execute_dft_r2c( m_plan,src,dst); - } - inline - void inv(scalar_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) - m_plan = fftwf_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwf_execute_dft_c2r( m_plan, src,dst); - } - - inline - void fwd2( complex_type * dst,complex_type * src,int n0,int n1) { - if (m_plan==NULL) m_plan = fftwf_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwf_execute_dft( m_plan, src,dst); - } - inline - void inv2( complex_type * dst,complex_type * src,int n0,int n1) { - if (m_plan==NULL) m_plan = fftwf_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwf_execute_dft( m_plan, src,dst); - } - - }; - template <> - struct fftw_plan<double> - { - typedef double scalar_type; - typedef fftw_complex complex_type; - ::fftw_plan m_plan; - fftw_plan() :m_plan(NULL) {} - ~fftw_plan() {if (m_plan) fftw_destroy_plan(m_plan);} - - inline - void fwd(complex_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftw_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftw_execute_dft( m_plan, src,dst); - } - inline - void inv(complex_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftw_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftw_execute_dft( m_plan, src,dst); - } - inline - void fwd(complex_type * dst,scalar_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftw_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftw_execute_dft_r2c( m_plan,src,dst); - } - inline - void inv(scalar_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) - m_plan = fftw_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftw_execute_dft_c2r( m_plan, src,dst); - } - inline - void fwd2( complex_type * dst,complex_type * src,int n0,int n1) { - if (m_plan==NULL) m_plan = fftw_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftw_execute_dft( m_plan, src,dst); - } - inline - void inv2( complex_type * dst,complex_type * src,int n0,int n1) { - if (m_plan==NULL) m_plan = fftw_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftw_execute_dft( m_plan, src,dst); - } - }; - template <> - struct fftw_plan<long double> - { - typedef long double scalar_type; - typedef fftwl_complex complex_type; - fftwl_plan m_plan; - fftw_plan() :m_plan(NULL) {} - ~fftw_plan() {if (m_plan) fftwl_destroy_plan(m_plan);} - - inline - void fwd(complex_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftwl_plan_dft_1d(nfft,src,dst, FFTW_FORWARD, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwl_execute_dft( m_plan, src,dst); - } - inline - void inv(complex_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftwl_plan_dft_1d(nfft,src,dst, FFTW_BACKWARD , FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwl_execute_dft( m_plan, src,dst); - } - inline - void fwd(complex_type * dst,scalar_type * src,int nfft) { - if (m_plan==NULL) m_plan = fftwl_plan_dft_r2c_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwl_execute_dft_r2c( m_plan,src,dst); - } - inline - void inv(scalar_type * dst,complex_type * src,int nfft) { - if (m_plan==NULL) - m_plan = fftwl_plan_dft_c2r_1d(nfft,src,dst,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwl_execute_dft_c2r( m_plan, src,dst); - } - inline - void fwd2( complex_type * dst,complex_type * src,int n0,int n1) { - if (m_plan==NULL) m_plan = fftwl_plan_dft_2d(n0,n1,src,dst,FFTW_FORWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwl_execute_dft( m_plan, src,dst); - } - inline - void inv2( complex_type * dst,complex_type * src,int n0,int n1) { - if (m_plan==NULL) m_plan = fftwl_plan_dft_2d(n0,n1,src,dst,FFTW_BACKWARD,FFTW_ESTIMATE|FFTW_PRESERVE_INPUT); - fftwl_execute_dft( m_plan, src,dst); - } - }; - - template <typename _Scalar> - struct fftw_impl - { - typedef _Scalar Scalar; - typedef std::complex<Scalar> Complex; - - inline - void clear() - { - m_plans.clear(); - } - - // complex-to-complex forward FFT - inline - void fwd( Complex * dst,const Complex *src,int nfft) - { - get_plan(nfft,false,dst,src).fwd(fftw_cast(dst), fftw_cast(src),nfft ); - } - - // real-to-complex forward FFT - inline - void fwd( Complex * dst,const Scalar * src,int nfft) - { - get_plan(nfft,false,dst,src).fwd(fftw_cast(dst), fftw_cast(src) ,nfft); - } - - // 2-d complex-to-complex - inline - void fwd2(Complex * dst, const Complex * src, int n0,int n1) - { - get_plan(n0,n1,false,dst,src).fwd2(fftw_cast(dst), fftw_cast(src) ,n0,n1); - } - - // inverse complex-to-complex - inline - void inv(Complex * dst,const Complex *src,int nfft) - { - get_plan(nfft,true,dst,src).inv(fftw_cast(dst), fftw_cast(src),nfft ); - } - - // half-complex to scalar - inline - void inv( Scalar * dst,const Complex * src,int nfft) - { - get_plan(nfft,true,dst,src).inv(fftw_cast(dst), fftw_cast(src),nfft ); - } - - // 2-d complex-to-complex - inline - void inv2(Complex * dst, const Complex * src, int n0,int n1) - { - get_plan(n0,n1,true,dst,src).inv2(fftw_cast(dst), fftw_cast(src) ,n0,n1); - } - - - protected: - typedef fftw_plan<Scalar> PlanData; - - typedef std::map<int64_t,PlanData> PlanMap; - - PlanMap m_plans; - - inline - PlanData & get_plan(int nfft,bool inverse,void * dst,const void * src) - { - bool inplace = (dst==src); - bool aligned = ( (reinterpret_cast<size_t>(src)&15) | (reinterpret_cast<size_t>(dst)&15) ) == 0; - int64_t key = ( (nfft<<3 ) | (inverse<<2) | (inplace<<1) | aligned ) << 1; - return m_plans[key]; - } - - inline - PlanData & get_plan(int n0,int n1,bool inverse,void * dst,const void * src) - { - bool inplace = (dst==src); - bool aligned = ( (reinterpret_cast<size_t>(src)&15) | (reinterpret_cast<size_t>(dst)&15) ) == 0; - int64_t key = ( ( (((int64_t)n0) << 30)|(n1<<3 ) | (inverse<<2) | (inplace<<1) | aligned ) << 1 ) + 1; - return m_plans[key]; - } - }; - -} // end namespace internal - -} // end namespace Eigen - -/* vim: set filetype=cpp et sw=2 ts=2 ai: */ diff --git a/eigen/unsupported/Eigen/src/FFT/ei_kissfft_impl.h b/eigen/unsupported/Eigen/src/FFT/ei_kissfft_impl.h deleted file mode 100644 index be51b4e..0000000 --- a/eigen/unsupported/Eigen/src/FFT/ei_kissfft_impl.h +++ /dev/null @@ -1,420 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Mark Borgerding mark a borgerding net -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -namespace Eigen { - -namespace internal { - - // This FFT implementation was derived from kissfft http:sourceforge.net/projects/kissfft - // Copyright 2003-2009 Mark Borgerding - -template <typename _Scalar> -struct kiss_cpx_fft -{ - typedef _Scalar Scalar; - typedef std::complex<Scalar> Complex; - std::vector<Complex> m_twiddles; - std::vector<int> m_stageRadix; - std::vector<int> m_stageRemainder; - std::vector<Complex> m_scratchBuf; - bool m_inverse; - - inline - void make_twiddles(int nfft,bool inverse) - { - using std::acos; - m_inverse = inverse; - m_twiddles.resize(nfft); - Scalar phinc = (inverse?2:-2)* acos( (Scalar) -1) / nfft; - for (int i=0;i<nfft;++i) - m_twiddles[i] = exp( Complex(0,i*phinc) ); - } - - void factorize(int nfft) - { - //start factoring out 4's, then 2's, then 3,5,7,9,... - int n= nfft; - int p=4; - do { - while (n % p) { - switch (p) { - case 4: p = 2; break; - case 2: p = 3; break; - default: p += 2; break; - } - if (p*p>n) - p=n;// impossible to have a factor > sqrt(n) - } - n /= p; - m_stageRadix.push_back(p); - m_stageRemainder.push_back(n); - if ( p > 5 ) - m_scratchBuf.resize(p); // scratchbuf will be needed in bfly_generic - }while(n>1); - } - - template <typename _Src> - inline - void work( int stage,Complex * xout, const _Src * xin, size_t fstride,size_t in_stride) - { - int p = m_stageRadix[stage]; - int m = m_stageRemainder[stage]; - Complex * Fout_beg = xout; - Complex * Fout_end = xout + p*m; - - if (m>1) { - do{ - // recursive call: - // DFT of size m*p performed by doing - // p instances of smaller DFTs of size m, - // each one takes a decimated version of the input - work(stage+1, xout , xin, fstride*p,in_stride); - xin += fstride*in_stride; - }while( (xout += m) != Fout_end ); - }else{ - do{ - *xout = *xin; - xin += fstride*in_stride; - }while(++xout != Fout_end ); - } - xout=Fout_beg; - - // recombine the p smaller DFTs - switch (p) { - case 2: bfly2(xout,fstride,m); break; - case 3: bfly3(xout,fstride,m); break; - case 4: bfly4(xout,fstride,m); break; - case 5: bfly5(xout,fstride,m); break; - default: bfly_generic(xout,fstride,m,p); break; - } - } - - inline - void bfly2( Complex * Fout, const size_t fstride, int m) - { - for (int k=0;k<m;++k) { - Complex t = Fout[m+k] * m_twiddles[k*fstride]; - Fout[m+k] = Fout[k] - t; - Fout[k] += t; - } - } - - inline - void bfly4( Complex * Fout, const size_t fstride, const size_t m) - { - Complex scratch[6]; - int negative_if_inverse = m_inverse * -2 +1; - for (size_t k=0;k<m;++k) { - scratch[0] = Fout[k+m] * m_twiddles[k*fstride]; - scratch[1] = Fout[k+2*m] * m_twiddles[k*fstride*2]; - scratch[2] = Fout[k+3*m] * m_twiddles[k*fstride*3]; - scratch[5] = Fout[k] - scratch[1]; - - Fout[k] += scratch[1]; - scratch[3] = scratch[0] + scratch[2]; - scratch[4] = scratch[0] - scratch[2]; - scratch[4] = Complex( scratch[4].imag()*negative_if_inverse , -scratch[4].real()* negative_if_inverse ); - - Fout[k+2*m] = Fout[k] - scratch[3]; - Fout[k] += scratch[3]; - Fout[k+m] = scratch[5] + scratch[4]; - Fout[k+3*m] = scratch[5] - scratch[4]; - } - } - - inline - void bfly3( Complex * Fout, const size_t fstride, const size_t m) - { - size_t k=m; - const size_t m2 = 2*m; - Complex *tw1,*tw2; - Complex scratch[5]; - Complex epi3; - epi3 = m_twiddles[fstride*m]; - - tw1=tw2=&m_twiddles[0]; - - do{ - scratch[1]=Fout[m] * *tw1; - scratch[2]=Fout[m2] * *tw2; - - scratch[3]=scratch[1]+scratch[2]; - scratch[0]=scratch[1]-scratch[2]; - tw1 += fstride; - tw2 += fstride*2; - Fout[m] = Complex( Fout->real() - Scalar(.5)*scratch[3].real() , Fout->imag() - Scalar(.5)*scratch[3].imag() ); - scratch[0] *= epi3.imag(); - *Fout += scratch[3]; - Fout[m2] = Complex( Fout[m].real() + scratch[0].imag() , Fout[m].imag() - scratch[0].real() ); - Fout[m] += Complex( -scratch[0].imag(),scratch[0].real() ); - ++Fout; - }while(--k); - } - - inline - void bfly5( Complex * Fout, const size_t fstride, const size_t m) - { - Complex *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; - size_t u; - Complex scratch[13]; - Complex * twiddles = &m_twiddles[0]; - Complex *tw; - Complex ya,yb; - ya = twiddles[fstride*m]; - yb = twiddles[fstride*2*m]; - - Fout0=Fout; - Fout1=Fout0+m; - Fout2=Fout0+2*m; - Fout3=Fout0+3*m; - Fout4=Fout0+4*m; - - tw=twiddles; - for ( u=0; u<m; ++u ) { - scratch[0] = *Fout0; - - scratch[1] = *Fout1 * tw[u*fstride]; - scratch[2] = *Fout2 * tw[2*u*fstride]; - scratch[3] = *Fout3 * tw[3*u*fstride]; - scratch[4] = *Fout4 * tw[4*u*fstride]; - - scratch[7] = scratch[1] + scratch[4]; - scratch[10] = scratch[1] - scratch[4]; - scratch[8] = scratch[2] + scratch[3]; - scratch[9] = scratch[2] - scratch[3]; - - *Fout0 += scratch[7]; - *Fout0 += scratch[8]; - - scratch[5] = scratch[0] + Complex( - (scratch[7].real()*ya.real() ) + (scratch[8].real() *yb.real() ), - (scratch[7].imag()*ya.real()) + (scratch[8].imag()*yb.real()) - ); - - scratch[6] = Complex( - (scratch[10].imag()*ya.imag()) + (scratch[9].imag()*yb.imag()), - -(scratch[10].real()*ya.imag()) - (scratch[9].real()*yb.imag()) - ); - - *Fout1 = scratch[5] - scratch[6]; - *Fout4 = scratch[5] + scratch[6]; - - scratch[11] = scratch[0] + - Complex( - (scratch[7].real()*yb.real()) + (scratch[8].real()*ya.real()), - (scratch[7].imag()*yb.real()) + (scratch[8].imag()*ya.real()) - ); - - scratch[12] = Complex( - -(scratch[10].imag()*yb.imag()) + (scratch[9].imag()*ya.imag()), - (scratch[10].real()*yb.imag()) - (scratch[9].real()*ya.imag()) - ); - - *Fout2=scratch[11]+scratch[12]; - *Fout3=scratch[11]-scratch[12]; - - ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; - } - } - - /* perform the butterfly for one stage of a mixed radix FFT */ - inline - void bfly_generic( - Complex * Fout, - const size_t fstride, - int m, - int p - ) - { - int u,k,q1,q; - Complex * twiddles = &m_twiddles[0]; - Complex t; - int Norig = static_cast<int>(m_twiddles.size()); - Complex * scratchbuf = &m_scratchBuf[0]; - - for ( u=0; u<m; ++u ) { - k=u; - for ( q1=0 ; q1<p ; ++q1 ) { - scratchbuf[q1] = Fout[ k ]; - k += m; - } - - k=u; - for ( q1=0 ; q1<p ; ++q1 ) { - int twidx=0; - Fout[ k ] = scratchbuf[0]; - for (q=1;q<p;++q ) { - twidx += static_cast<int>(fstride) * k; - if (twidx>=Norig) twidx-=Norig; - t=scratchbuf[q] * twiddles[twidx]; - Fout[ k ] += t; - } - k += m; - } - } - } -}; - -template <typename _Scalar> -struct kissfft_impl -{ - typedef _Scalar Scalar; - typedef std::complex<Scalar> Complex; - - void clear() - { - m_plans.clear(); - m_realTwiddles.clear(); - } - - inline - void fwd( Complex * dst,const Complex *src,int nfft) - { - get_plan(nfft,false).work(0, dst, src, 1,1); - } - - inline - void fwd2( Complex * dst,const Complex *src,int n0,int n1) - { - EIGEN_UNUSED_VARIABLE(dst); - EIGEN_UNUSED_VARIABLE(src); - EIGEN_UNUSED_VARIABLE(n0); - EIGEN_UNUSED_VARIABLE(n1); - } - - inline - void inv2( Complex * dst,const Complex *src,int n0,int n1) - { - EIGEN_UNUSED_VARIABLE(dst); - EIGEN_UNUSED_VARIABLE(src); - EIGEN_UNUSED_VARIABLE(n0); - EIGEN_UNUSED_VARIABLE(n1); - } - - // real-to-complex forward FFT - // perform two FFTs of src even and src odd - // then twiddle to recombine them into the half-spectrum format - // then fill in the conjugate symmetric half - inline - void fwd( Complex * dst,const Scalar * src,int nfft) - { - if ( nfft&3 ) { - // use generic mode for odd - m_tmpBuf1.resize(nfft); - get_plan(nfft,false).work(0, &m_tmpBuf1[0], src, 1,1); - std::copy(m_tmpBuf1.begin(),m_tmpBuf1.begin()+(nfft>>1)+1,dst ); - }else{ - int ncfft = nfft>>1; - int ncfft2 = nfft>>2; - Complex * rtw = real_twiddles(ncfft2); - - // use optimized mode for even real - fwd( dst, reinterpret_cast<const Complex*> (src), ncfft); - Complex dc = dst[0].real() + dst[0].imag(); - Complex nyquist = dst[0].real() - dst[0].imag(); - int k; - for ( k=1;k <= ncfft2 ; ++k ) { - Complex fpk = dst[k]; - Complex fpnk = conj(dst[ncfft-k]); - Complex f1k = fpk + fpnk; - Complex f2k = fpk - fpnk; - Complex tw= f2k * rtw[k-1]; - dst[k] = (f1k + tw) * Scalar(.5); - dst[ncfft-k] = conj(f1k -tw)*Scalar(.5); - } - dst[0] = dc; - dst[ncfft] = nyquist; - } - } - - // inverse complex-to-complex - inline - void inv(Complex * dst,const Complex *src,int nfft) - { - get_plan(nfft,true).work(0, dst, src, 1,1); - } - - // half-complex to scalar - inline - void inv( Scalar * dst,const Complex * src,int nfft) - { - if (nfft&3) { - m_tmpBuf1.resize(nfft); - m_tmpBuf2.resize(nfft); - std::copy(src,src+(nfft>>1)+1,m_tmpBuf1.begin() ); - for (int k=1;k<(nfft>>1)+1;++k) - m_tmpBuf1[nfft-k] = conj(m_tmpBuf1[k]); - inv(&m_tmpBuf2[0],&m_tmpBuf1[0],nfft); - for (int k=0;k<nfft;++k) - dst[k] = m_tmpBuf2[k].real(); - }else{ - // optimized version for multiple of 4 - int ncfft = nfft>>1; - int ncfft2 = nfft>>2; - Complex * rtw = real_twiddles(ncfft2); - m_tmpBuf1.resize(ncfft); - m_tmpBuf1[0] = Complex( src[0].real() + src[ncfft].real(), src[0].real() - src[ncfft].real() ); - for (int k = 1; k <= ncfft / 2; ++k) { - Complex fk = src[k]; - Complex fnkc = conj(src[ncfft-k]); - Complex fek = fk + fnkc; - Complex tmp = fk - fnkc; - Complex fok = tmp * conj(rtw[k-1]); - m_tmpBuf1[k] = fek + fok; - m_tmpBuf1[ncfft-k] = conj(fek - fok); - } - get_plan(ncfft,true).work(0, reinterpret_cast<Complex*>(dst), &m_tmpBuf1[0], 1,1); - } - } - - protected: - typedef kiss_cpx_fft<Scalar> PlanData; - typedef std::map<int,PlanData> PlanMap; - - PlanMap m_plans; - std::map<int, std::vector<Complex> > m_realTwiddles; - std::vector<Complex> m_tmpBuf1; - std::vector<Complex> m_tmpBuf2; - - inline - int PlanKey(int nfft, bool isinverse) const { return (nfft<<1) | int(isinverse); } - - inline - PlanData & get_plan(int nfft, bool inverse) - { - // TODO look for PlanKey(nfft, ! inverse) and conjugate the twiddles - PlanData & pd = m_plans[ PlanKey(nfft,inverse) ]; - if ( pd.m_twiddles.size() == 0 ) { - pd.make_twiddles(nfft,inverse); - pd.factorize(nfft); - } - return pd; - } - - inline - Complex * real_twiddles(int ncfft2) - { - using std::acos; - std::vector<Complex> & twidref = m_realTwiddles[ncfft2];// creates new if not there - if ( (int)twidref.size() != ncfft2 ) { - twidref.resize(ncfft2); - int ncfft= ncfft2<<1; - Scalar pi = acos( Scalar(-1) ); - for (int k=1;k<=ncfft2;++k) - twidref[k-1] = exp( Complex(0,-pi * (Scalar(k) / ncfft + Scalar(.5)) ) ); - } - return &twidref[0]; - } -}; - -} // end namespace internal - -} // end namespace Eigen - -/* vim: set filetype=cpp et sw=2 ts=2 ai: */ diff --git a/eigen/unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h b/eigen/unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h deleted file mode 100644 index dc0093e..0000000 --- a/eigen/unsupported/Eigen/src/IterativeSolvers/ConstrainedConjGrad.h +++ /dev/null @@ -1,189 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> - -/* NOTE The functions of this file have been adapted from the GMM++ library */ - -//======================================================================== -// -// Copyright (C) 2002-2007 Yves Renard -// -// This file is a part of GETFEM++ -// -// Getfem++ 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; version 2.1 of the License. -// -// This program 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 for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, -// USA. -// -//======================================================================== - -#include "../../../../Eigen/src/Core/util/NonMPL2.h" - -#ifndef EIGEN_CONSTRAINEDCG_H -#define EIGEN_CONSTRAINEDCG_H - -#include <Eigen/Core> - -namespace Eigen { - -namespace internal { - -/** \ingroup IterativeSolvers_Module - * Compute the pseudo inverse of the non-square matrix C such that - * \f$ CINV = (C * C^T)^{-1} * C \f$ based on a conjugate gradient method. - * - * This function is internally used by constrained_cg. - */ -template <typename CMatrix, typename CINVMatrix> -void pseudo_inverse(const CMatrix &C, CINVMatrix &CINV) -{ - // optimisable : copie de la ligne, precalcul de C * trans(C). - typedef typename CMatrix::Scalar Scalar; - typedef typename CMatrix::Index Index; - // FIXME use sparse vectors ? - typedef Matrix<Scalar,Dynamic,1> TmpVec; - - Index rows = C.rows(), cols = C.cols(); - - TmpVec d(rows), e(rows), l(cols), p(rows), q(rows), r(rows); - Scalar rho, rho_1, alpha; - d.setZero(); - - typedef Triplet<double> T; - std::vector<T> tripletList; - - for (Index i = 0; i < rows; ++i) - { - d[i] = 1.0; - rho = 1.0; - e.setZero(); - r = d; - p = d; - - while (rho >= 1e-38) - { /* conjugate gradient to compute e */ - /* which is the i-th row of inv(C * trans(C)) */ - l = C.transpose() * p; - q = C * l; - alpha = rho / p.dot(q); - e += alpha * p; - r += -alpha * q; - rho_1 = rho; - rho = r.dot(r); - p = (rho/rho_1) * p + r; - } - - l = C.transpose() * e; // l is the i-th row of CINV - // FIXME add a generic "prune/filter" expression for both dense and sparse object to sparse - for (Index j=0; j<l.size(); ++j) - if (l[j]<1e-15) - tripletList.push_back(T(i,j,l(j))); - - - d[i] = 0.0; - } - CINV.setFromTriplets(tripletList.begin(), tripletList.end()); -} - - - -/** \ingroup IterativeSolvers_Module - * Constrained conjugate gradient - * - * Computes the minimum of \f$ 1/2((Ax).x) - bx \f$ under the contraint \f$ Cx \le f \f$ - */ -template<typename TMatrix, typename CMatrix, - typename VectorX, typename VectorB, typename VectorF> -void constrained_cg(const TMatrix& A, const CMatrix& C, VectorX& x, - const VectorB& b, const VectorF& f, IterationController &iter) -{ - using std::sqrt; - typedef typename TMatrix::Scalar Scalar; - typedef typename TMatrix::Index Index; - typedef Matrix<Scalar,Dynamic,1> TmpVec; - - Scalar rho = 1.0, rho_1, lambda, gamma; - Index xSize = x.size(); - TmpVec p(xSize), q(xSize), q2(xSize), - r(xSize), old_z(xSize), z(xSize), - memox(xSize); - std::vector<bool> satured(C.rows()); - p.setZero(); - iter.setRhsNorm(sqrt(b.dot(b))); // gael vect_sp(PS, b, b) - if (iter.rhsNorm() == 0.0) iter.setRhsNorm(1.0); - - SparseMatrix<Scalar,RowMajor> CINV(C.rows(), C.cols()); - pseudo_inverse(C, CINV); - - while(true) - { - // computation of residual - old_z = z; - memox = x; - r = b; - r += A * -x; - z = r; - bool transition = false; - for (Index i = 0; i < C.rows(); ++i) - { - Scalar al = C.row(i).dot(x) - f.coeff(i); - if (al >= -1.0E-15) - { - if (!satured[i]) - { - satured[i] = true; - transition = true; - } - Scalar bb = CINV.row(i).dot(z); - if (bb > 0.0) - // FIXME: we should allow that: z += -bb * C.row(i); - for (typename CMatrix::InnerIterator it(C,i); it; ++it) - z.coeffRef(it.index()) -= bb*it.value(); - } - else - satured[i] = false; - } - - // descent direction - rho_1 = rho; - rho = r.dot(z); - - if (iter.finished(rho)) break; - - if (iter.noiseLevel() > 0 && transition) std::cerr << "CCG: transition\n"; - if (transition || iter.first()) gamma = 0.0; - else gamma = (std::max)(0.0, (rho - old_z.dot(z)) / rho_1); - p = z + gamma*p; - - ++iter; - // one dimensionnal optimization - q = A * p; - lambda = rho / q.dot(p); - for (Index i = 0; i < C.rows(); ++i) - { - if (!satured[i]) - { - Scalar bb = C.row(i).dot(p) - f[i]; - if (bb > 0.0) - lambda = (std::min)(lambda, (f.coeff(i)-C.row(i).dot(x)) / bb); - } - } - x += lambda * p; - memox -= x; - } -} - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_CONSTRAINEDCG_H diff --git a/eigen/unsupported/Eigen/src/IterativeSolvers/DGMRES.h b/eigen/unsupported/Eigen/src/IterativeSolvers/DGMRES.h deleted file mode 100644 index 4079e23..0000000 --- a/eigen/unsupported/Eigen/src/IterativeSolvers/DGMRES.h +++ /dev/null @@ -1,510 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_DGMRES_H -#define EIGEN_DGMRES_H - -#include <Eigen/Eigenvalues> - -namespace Eigen { - -template< typename _MatrixType, - typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> > -class DGMRES; - -namespace internal { - -template< typename _MatrixType, typename _Preconditioner> -struct traits<DGMRES<_MatrixType,_Preconditioner> > -{ - typedef _MatrixType MatrixType; - typedef _Preconditioner Preconditioner; -}; - -/** \brief Computes a permutation vector to have a sorted sequence - * \param vec The vector to reorder. - * \param perm gives the sorted sequence on output. Must be initialized with 0..n-1 - * \param ncut Put the ncut smallest elements at the end of the vector - * WARNING This is an expensive sort, so should be used only - * for small size vectors - * TODO Use modified QuickSplit or std::nth_element to get the smallest values - */ -template <typename VectorType, typename IndexType> -void sortWithPermutation (VectorType& vec, IndexType& perm, typename IndexType::Scalar& ncut) -{ - eigen_assert(vec.size() == perm.size()); - bool flag; - for (Index k = 0; k < ncut; k++) - { - flag = false; - for (Index j = 0; j < vec.size()-1; j++) - { - if ( vec(perm(j)) < vec(perm(j+1)) ) - { - std::swap(perm(j),perm(j+1)); - flag = true; - } - if (!flag) break; // The vector is in sorted order - } - } -} - -} -/** - * \ingroup IterativeLInearSolvers_Module - * \brief A Restarted GMRES with deflation. - * This class implements a modification of the GMRES solver for - * sparse linear systems. The basis is built with modified - * Gram-Schmidt. At each restart, a few approximated eigenvectors - * corresponding to the smallest eigenvalues are used to build a - * preconditioner for the next cycle. This preconditioner - * for deflation can be combined with any other preconditioner, - * the IncompleteLUT for instance. The preconditioner is applied - * at right of the matrix and the combination is multiplicative. - * - * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix. - * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner - * Typical usage : - * \code - * SparseMatrix<double> A; - * VectorXd x, b; - * //Fill A and b ... - * DGMRES<SparseMatrix<double> > solver; - * solver.set_restart(30); // Set restarting value - * solver.setEigenv(1); // Set the number of eigenvalues to deflate - * solver.compute(A); - * x = solver.solve(b); - * \endcode - * - * DGMRES can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink. - * - * References : - * [1] D. NUENTSA WAKAM and F. PACULL, Memory Efficient Hybrid - * Algebraic Solvers for Linear Systems Arising from Compressible - * Flows, Computers and Fluids, In Press, - * http://dx.doi.org/10.1016/j.compfluid.2012.03.023 - * [2] K. Burrage and J. Erhel, On the performance of various - * adaptive preconditioned GMRES strategies, 5(1998), 101-121. - * [3] J. Erhel, K. Burrage and B. Pohl, Restarted GMRES - * preconditioned by deflation,J. Computational and Applied - * Mathematics, 69(1996), 303-318. - - * - */ -template< typename _MatrixType, typename _Preconditioner> -class DGMRES : public IterativeSolverBase<DGMRES<_MatrixType,_Preconditioner> > -{ - typedef IterativeSolverBase<DGMRES> Base; - using Base::matrix; - using Base::m_error; - using Base::m_iterations; - using Base::m_info; - using Base::m_isInitialized; - using Base::m_tolerance; - public: - using Base::_solve_impl; - typedef _MatrixType MatrixType; - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::StorageIndex StorageIndex; - typedef typename MatrixType::RealScalar RealScalar; - typedef _Preconditioner Preconditioner; - typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix; - typedef Matrix<RealScalar,Dynamic,Dynamic> DenseRealMatrix; - typedef Matrix<Scalar,Dynamic,1> DenseVector; - typedef Matrix<RealScalar,Dynamic,1> DenseRealVector; - typedef Matrix<std::complex<RealScalar>, Dynamic, 1> ComplexVector; - - - /** Default constructor. */ - DGMRES() : Base(),m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false) {} - - /** Initialize the solver with matrix \a A for further \c Ax=b solving. - * - * This constructor is a shortcut for the default constructor followed - * by a call to compute(). - * - * \warning this class stores a reference to the matrix A as well as some - * precomputed values that depend on it. Therefore, if \a A is changed - * this class becomes invalid. Call compute() to update it with the new - * matrix A, or modify a copy of A. - */ - template<typename MatrixDerived> - explicit DGMRES(const EigenBase<MatrixDerived>& A) : Base(A.derived()), m_restart(30),m_neig(0),m_r(0),m_maxNeig(5),m_isDeflAllocated(false),m_isDeflInitialized(false) {} - - ~DGMRES() {} - - /** \internal */ - template<typename Rhs,typename Dest> - void _solve_with_guess_impl(const Rhs& b, Dest& x) const - { - bool failed = false; - for(Index j=0; j<b.cols(); ++j) - { - m_iterations = Base::maxIterations(); - m_error = Base::m_tolerance; - - typename Dest::ColXpr xj(x,j); - dgmres(matrix(), b.col(j), xj, Base::m_preconditioner); - } - m_info = failed ? NumericalIssue - : m_error <= Base::m_tolerance ? Success - : NoConvergence; - m_isInitialized = true; - } - - /** \internal */ - template<typename Rhs,typename Dest> - void _solve_impl(const Rhs& b, MatrixBase<Dest>& x) const - { - x = b; - _solve_with_guess_impl(b,x.derived()); - } - /** - * Get the restart value - */ - Index restart() { return m_restart; } - - /** - * Set the restart value (default is 30) - */ - void set_restart(const Index restart) { m_restart=restart; } - - /** - * Set the number of eigenvalues to deflate at each restart - */ - void setEigenv(const Index neig) - { - m_neig = neig; - if (neig+1 > m_maxNeig) m_maxNeig = neig+1; // To allow for complex conjugates - } - - /** - * Get the size of the deflation subspace size - */ - Index deflSize() {return m_r; } - - /** - * Set the maximum size of the deflation subspace - */ - void setMaxEigenv(const Index maxNeig) { m_maxNeig = maxNeig; } - - protected: - // DGMRES algorithm - template<typename Rhs, typename Dest> - void dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x, const Preconditioner& precond) const; - // Perform one cycle of GMRES - template<typename Dest> - Index dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, Index& nbIts) const; - // Compute data to use for deflation - Index dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, StorageIndex& neig) const; - // Apply deflation to a vector - template<typename RhsType, typename DestType> - Index dgmresApplyDeflation(const RhsType& In, DestType& Out) const; - ComplexVector schurValues(const ComplexSchur<DenseMatrix>& schurofH) const; - ComplexVector schurValues(const RealSchur<DenseMatrix>& schurofH) const; - // Init data for deflation - void dgmresInitDeflation(Index& rows) const; - mutable DenseMatrix m_V; // Krylov basis vectors - mutable DenseMatrix m_H; // Hessenberg matrix - mutable DenseMatrix m_Hes; // Initial hessenberg matrix wihout Givens rotations applied - mutable Index m_restart; // Maximum size of the Krylov subspace - mutable DenseMatrix m_U; // Vectors that form the basis of the invariant subspace - mutable DenseMatrix m_MU; // matrix operator applied to m_U (for next cycles) - mutable DenseMatrix m_T; /* T=U^T*M^{-1}*A*U */ - mutable PartialPivLU<DenseMatrix> m_luT; // LU factorization of m_T - mutable StorageIndex m_neig; //Number of eigenvalues to extract at each restart - mutable Index m_r; // Current number of deflated eigenvalues, size of m_U - mutable Index m_maxNeig; // Maximum number of eigenvalues to deflate - mutable RealScalar m_lambdaN; //Modulus of the largest eigenvalue of A - mutable bool m_isDeflAllocated; - mutable bool m_isDeflInitialized; - - //Adaptive strategy - mutable RealScalar m_smv; // Smaller multiple of the remaining number of steps allowed - mutable bool m_force; // Force the use of deflation at each restart - -}; -/** - * \brief Perform several cycles of restarted GMRES with modified Gram Schmidt, - * - * A right preconditioner is used combined with deflation. - * - */ -template< typename _MatrixType, typename _Preconditioner> -template<typename Rhs, typename Dest> -void DGMRES<_MatrixType, _Preconditioner>::dgmres(const MatrixType& mat,const Rhs& rhs, Dest& x, - const Preconditioner& precond) const -{ - //Initialization - Index n = mat.rows(); - DenseVector r0(n); - Index nbIts = 0; - m_H.resize(m_restart+1, m_restart); - m_Hes.resize(m_restart, m_restart); - m_V.resize(n,m_restart+1); - //Initial residual vector and intial norm - x = precond.solve(x); - r0 = rhs - mat * x; - RealScalar beta = r0.norm(); - RealScalar normRhs = rhs.norm(); - m_error = beta/normRhs; - if(m_error < m_tolerance) - m_info = Success; - else - m_info = NoConvergence; - - // Iterative process - while (nbIts < m_iterations && m_info == NoConvergence) - { - dgmresCycle(mat, precond, x, r0, beta, normRhs, nbIts); - - // Compute the new residual vector for the restart - if (nbIts < m_iterations && m_info == NoConvergence) - r0 = rhs - mat * x; - } -} - -/** - * \brief Perform one restart cycle of DGMRES - * \param mat The coefficient matrix - * \param precond The preconditioner - * \param x the new approximated solution - * \param r0 The initial residual vector - * \param beta The norm of the residual computed so far - * \param normRhs The norm of the right hand side vector - * \param nbIts The number of iterations - */ -template< typename _MatrixType, typename _Preconditioner> -template<typename Dest> -Index DGMRES<_MatrixType, _Preconditioner>::dgmresCycle(const MatrixType& mat, const Preconditioner& precond, Dest& x, DenseVector& r0, RealScalar& beta, const RealScalar& normRhs, Index& nbIts) const -{ - //Initialization - DenseVector g(m_restart+1); // Right hand side of the least square problem - g.setZero(); - g(0) = Scalar(beta); - m_V.col(0) = r0/beta; - m_info = NoConvergence; - std::vector<JacobiRotation<Scalar> >gr(m_restart); // Givens rotations - Index it = 0; // Number of inner iterations - Index n = mat.rows(); - DenseVector tv1(n), tv2(n); //Temporary vectors - while (m_info == NoConvergence && it < m_restart && nbIts < m_iterations) - { - // Apply preconditioner(s) at right - if (m_isDeflInitialized ) - { - dgmresApplyDeflation(m_V.col(it), tv1); // Deflation - tv2 = precond.solve(tv1); - } - else - { - tv2 = precond.solve(m_V.col(it)); // User's selected preconditioner - } - tv1 = mat * tv2; - - // Orthogonalize it with the previous basis in the basis using modified Gram-Schmidt - Scalar coef; - for (Index i = 0; i <= it; ++i) - { - coef = tv1.dot(m_V.col(i)); - tv1 = tv1 - coef * m_V.col(i); - m_H(i,it) = coef; - m_Hes(i,it) = coef; - } - // Normalize the vector - coef = tv1.norm(); - m_V.col(it+1) = tv1/coef; - m_H(it+1, it) = coef; -// m_Hes(it+1,it) = coef; - - // FIXME Check for happy breakdown - - // Update Hessenberg matrix with Givens rotations - for (Index i = 1; i <= it; ++i) - { - m_H.col(it).applyOnTheLeft(i-1,i,gr[i-1].adjoint()); - } - // Compute the new plane rotation - gr[it].makeGivens(m_H(it, it), m_H(it+1,it)); - // Apply the new rotation - m_H.col(it).applyOnTheLeft(it,it+1,gr[it].adjoint()); - g.applyOnTheLeft(it,it+1, gr[it].adjoint()); - - beta = std::abs(g(it+1)); - m_error = beta/normRhs; - // std::cerr << nbIts << " Relative Residual Norm " << m_error << std::endl; - it++; nbIts++; - - if (m_error < m_tolerance) - { - // The method has converged - m_info = Success; - break; - } - } - - // Compute the new coefficients by solving the least square problem -// it++; - //FIXME Check first if the matrix is singular ... zero diagonal - DenseVector nrs(m_restart); - nrs = m_H.topLeftCorner(it,it).template triangularView<Upper>().solve(g.head(it)); - - // Form the new solution - if (m_isDeflInitialized) - { - tv1 = m_V.leftCols(it) * nrs; - dgmresApplyDeflation(tv1, tv2); - x = x + precond.solve(tv2); - } - else - x = x + precond.solve(m_V.leftCols(it) * nrs); - - // Go for a new cycle and compute data for deflation - if(nbIts < m_iterations && m_info == NoConvergence && m_neig > 0 && (m_r+m_neig) < m_maxNeig) - dgmresComputeDeflationData(mat, precond, it, m_neig); - return 0; - -} - - -template< typename _MatrixType, typename _Preconditioner> -void DGMRES<_MatrixType, _Preconditioner>::dgmresInitDeflation(Index& rows) const -{ - m_U.resize(rows, m_maxNeig); - m_MU.resize(rows, m_maxNeig); - m_T.resize(m_maxNeig, m_maxNeig); - m_lambdaN = 0.0; - m_isDeflAllocated = true; -} - -template< typename _MatrixType, typename _Preconditioner> -inline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const ComplexSchur<DenseMatrix>& schurofH) const -{ - return schurofH.matrixT().diagonal(); -} - -template< typename _MatrixType, typename _Preconditioner> -inline typename DGMRES<_MatrixType, _Preconditioner>::ComplexVector DGMRES<_MatrixType, _Preconditioner>::schurValues(const RealSchur<DenseMatrix>& schurofH) const -{ - const DenseMatrix& T = schurofH.matrixT(); - Index it = T.rows(); - ComplexVector eig(it); - Index j = 0; - while (j < it-1) - { - if (T(j+1,j) ==Scalar(0)) - { - eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0)); - j++; - } - else - { - eig(j) = std::complex<RealScalar>(T(j,j),T(j+1,j)); - eig(j+1) = std::complex<RealScalar>(T(j,j+1),T(j+1,j+1)); - j++; - } - } - if (j < it-1) eig(j) = std::complex<RealScalar>(T(j,j),RealScalar(0)); - return eig; -} - -template< typename _MatrixType, typename _Preconditioner> -Index DGMRES<_MatrixType, _Preconditioner>::dgmresComputeDeflationData(const MatrixType& mat, const Preconditioner& precond, const Index& it, StorageIndex& neig) const -{ - // First, find the Schur form of the Hessenberg matrix H - typename internal::conditional<NumTraits<Scalar>::IsComplex, ComplexSchur<DenseMatrix>, RealSchur<DenseMatrix> >::type schurofH; - bool computeU = true; - DenseMatrix matrixQ(it,it); - matrixQ.setIdentity(); - schurofH.computeFromHessenberg(m_Hes.topLeftCorner(it,it), matrixQ, computeU); - - ComplexVector eig(it); - Matrix<StorageIndex,Dynamic,1>perm(it); - eig = this->schurValues(schurofH); - - // Reorder the absolute values of Schur values - DenseRealVector modulEig(it); - for (Index j=0; j<it; ++j) modulEig(j) = std::abs(eig(j)); - perm.setLinSpaced(it,0,internal::convert_index<StorageIndex>(it-1)); - internal::sortWithPermutation(modulEig, perm, neig); - - if (!m_lambdaN) - { - m_lambdaN = (std::max)(modulEig.maxCoeff(), m_lambdaN); - } - //Count the real number of extracted eigenvalues (with complex conjugates) - Index nbrEig = 0; - while (nbrEig < neig) - { - if(eig(perm(it-nbrEig-1)).imag() == RealScalar(0)) nbrEig++; - else nbrEig += 2; - } - // Extract the Schur vectors corresponding to the smallest Ritz values - DenseMatrix Sr(it, nbrEig); - Sr.setZero(); - for (Index j = 0; j < nbrEig; j++) - { - Sr.col(j) = schurofH.matrixU().col(perm(it-j-1)); - } - - // Form the Schur vectors of the initial matrix using the Krylov basis - DenseMatrix X; - X = m_V.leftCols(it) * Sr; - if (m_r) - { - // Orthogonalize X against m_U using modified Gram-Schmidt - for (Index j = 0; j < nbrEig; j++) - for (Index k =0; k < m_r; k++) - X.col(j) = X.col(j) - (m_U.col(k).dot(X.col(j)))*m_U.col(k); - } - - // Compute m_MX = A * M^-1 * X - Index m = m_V.rows(); - if (!m_isDeflAllocated) - dgmresInitDeflation(m); - DenseMatrix MX(m, nbrEig); - DenseVector tv1(m); - for (Index j = 0; j < nbrEig; j++) - { - tv1 = mat * X.col(j); - MX.col(j) = precond.solve(tv1); - } - - //Update m_T = [U'MU U'MX; X'MU X'MX] - m_T.block(m_r, m_r, nbrEig, nbrEig) = X.transpose() * MX; - if(m_r) - { - m_T.block(0, m_r, m_r, nbrEig) = m_U.leftCols(m_r).transpose() * MX; - m_T.block(m_r, 0, nbrEig, m_r) = X.transpose() * m_MU.leftCols(m_r); - } - - // Save X into m_U and m_MX in m_MU - for (Index j = 0; j < nbrEig; j++) m_U.col(m_r+j) = X.col(j); - for (Index j = 0; j < nbrEig; j++) m_MU.col(m_r+j) = MX.col(j); - // Increase the size of the invariant subspace - m_r += nbrEig; - - // Factorize m_T into m_luT - m_luT.compute(m_T.topLeftCorner(m_r, m_r)); - - //FIXME CHeck if the factorization was correctly done (nonsingular matrix) - m_isDeflInitialized = true; - return 0; -} -template<typename _MatrixType, typename _Preconditioner> -template<typename RhsType, typename DestType> -Index DGMRES<_MatrixType, _Preconditioner>::dgmresApplyDeflation(const RhsType &x, DestType &y) const -{ - DenseVector x1 = m_U.leftCols(m_r).transpose() * x; - y = x + m_U.leftCols(m_r) * ( m_lambdaN * m_luT.solve(x1) - x1); - return 0; -} - -} // end namespace Eigen -#endif diff --git a/eigen/unsupported/Eigen/src/IterativeSolvers/GMRES.h b/eigen/unsupported/Eigen/src/IterativeSolvers/GMRES.h deleted file mode 100644 index 92618b1..0000000 --- a/eigen/unsupported/Eigen/src/IterativeSolvers/GMRES.h +++ /dev/null @@ -1,343 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr> -// Copyright (C) 2012, 2014 Kolja Brix <brix@igpm.rwth-aaachen.de> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_GMRES_H -#define EIGEN_GMRES_H - -namespace Eigen { - -namespace internal { - -/** -* Generalized Minimal Residual Algorithm based on the -* Arnoldi algorithm implemented with Householder reflections. -* -* Parameters: -* \param mat matrix of linear system of equations -* \param rhs right hand side vector of linear system of equations -* \param x on input: initial guess, on output: solution -* \param precond preconditioner used -* \param iters on input: maximum number of iterations to perform -* on output: number of iterations performed -* \param restart number of iterations for a restart -* \param tol_error on input: relative residual tolerance -* on output: residuum achieved -* -* \sa IterativeMethods::bicgstab() -* -* -* For references, please see: -* -* Saad, Y. and Schultz, M. H. -* GMRES: A Generalized Minimal Residual Algorithm for Solving Nonsymmetric Linear Systems. -* SIAM J.Sci.Stat.Comp. 7, 1986, pp. 856 - 869. -* -* Saad, Y. -* Iterative Methods for Sparse Linear Systems. -* Society for Industrial and Applied Mathematics, Philadelphia, 2003. -* -* Walker, H. F. -* Implementations of the GMRES method. -* Comput.Phys.Comm. 53, 1989, pp. 311 - 320. -* -* Walker, H. F. -* Implementation of the GMRES Method using Householder Transformations. -* SIAM J.Sci.Stat.Comp. 9, 1988, pp. 152 - 163. -* -*/ -template<typename MatrixType, typename Rhs, typename Dest, typename Preconditioner> -bool gmres(const MatrixType & mat, const Rhs & rhs, Dest & x, const Preconditioner & precond, - Index &iters, const Index &restart, typename Dest::RealScalar & tol_error) { - - using std::sqrt; - using std::abs; - - typedef typename Dest::RealScalar RealScalar; - typedef typename Dest::Scalar Scalar; - typedef Matrix < Scalar, Dynamic, 1 > VectorType; - typedef Matrix < Scalar, Dynamic, Dynamic, ColMajor> FMatrixType; - - RealScalar tol = tol_error; - const Index maxIters = iters; - iters = 0; - - const Index m = mat.rows(); - - // residual and preconditioned residual - VectorType p0 = rhs - mat*x; - VectorType r0 = precond.solve(p0); - - const RealScalar r0Norm = r0.norm(); - - // is initial guess already good enough? - if(r0Norm == 0) - { - tol_error = 0; - return true; - } - - // storage for Hessenberg matrix and Householder data - FMatrixType H = FMatrixType::Zero(m, restart + 1); - VectorType w = VectorType::Zero(restart + 1); - VectorType tau = VectorType::Zero(restart + 1); - - // storage for Jacobi rotations - std::vector < JacobiRotation < Scalar > > G(restart); - - // storage for temporaries - VectorType t(m), v(m), workspace(m), x_new(m); - - // generate first Householder vector - Ref<VectorType> H0_tail = H.col(0).tail(m - 1); - RealScalar beta; - r0.makeHouseholder(H0_tail, tau.coeffRef(0), beta); - w(0) = Scalar(beta); - - for (Index k = 1; k <= restart; ++k) - { - ++iters; - - v = VectorType::Unit(m, k - 1); - - // apply Householder reflections H_{1} ... H_{k-1} to v - // TODO: use a HouseholderSequence - for (Index i = k - 1; i >= 0; --i) { - v.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data()); - } - - // apply matrix M to v: v = mat * v; - t.noalias() = mat * v; - v = precond.solve(t); - - // apply Householder reflections H_{k-1} ... H_{1} to v - // TODO: use a HouseholderSequence - for (Index i = 0; i < k; ++i) { - v.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data()); - } - - if (v.tail(m - k).norm() != 0.0) - { - if (k <= restart) - { - // generate new Householder vector - Ref<VectorType> Hk_tail = H.col(k).tail(m - k - 1); - v.tail(m - k).makeHouseholder(Hk_tail, tau.coeffRef(k), beta); - - // apply Householder reflection H_{k} to v - v.tail(m - k).applyHouseholderOnTheLeft(Hk_tail, tau.coeffRef(k), workspace.data()); - } - } - - if (k > 1) - { - for (Index i = 0; i < k - 1; ++i) - { - // apply old Givens rotations to v - v.applyOnTheLeft(i, i + 1, G[i].adjoint()); - } - } - - if (k<m && v(k) != (Scalar) 0) - { - // determine next Givens rotation - G[k - 1].makeGivens(v(k - 1), v(k)); - - // apply Givens rotation to v and w - v.applyOnTheLeft(k - 1, k, G[k - 1].adjoint()); - w.applyOnTheLeft(k - 1, k, G[k - 1].adjoint()); - } - - // insert coefficients into upper matrix triangle - H.col(k-1).head(k) = v.head(k); - - tol_error = abs(w(k)) / r0Norm; - bool stop = (k==m || tol_error < tol || iters == maxIters); - - if (stop || k == restart) - { - // solve upper triangular system - Ref<VectorType> y = w.head(k); - H.topLeftCorner(k, k).template triangularView <Upper>().solveInPlace(y); - - // use Horner-like scheme to calculate solution vector - x_new.setZero(); - for (Index i = k - 1; i >= 0; --i) - { - x_new(i) += y(i); - // apply Householder reflection H_{i} to x_new - x_new.tail(m - i).applyHouseholderOnTheLeft(H.col(i).tail(m - i - 1), tau.coeffRef(i), workspace.data()); - } - - x += x_new; - - if(stop) - { - return true; - } - else - { - k=0; - - // reset data for restart - p0.noalias() = rhs - mat*x; - r0 = precond.solve(p0); - - // clear Hessenberg matrix and Householder data - H.setZero(); - w.setZero(); - tau.setZero(); - - // generate first Householder vector - r0.makeHouseholder(H0_tail, tau.coeffRef(0), beta); - w(0) = Scalar(beta); - } - } - } - - return false; - -} - -} - -template< typename _MatrixType, - typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar> > -class GMRES; - -namespace internal { - -template< typename _MatrixType, typename _Preconditioner> -struct traits<GMRES<_MatrixType,_Preconditioner> > -{ - typedef _MatrixType MatrixType; - typedef _Preconditioner Preconditioner; -}; - -} - -/** \ingroup IterativeLinearSolvers_Module - * \brief A GMRES solver for sparse square problems - * - * This class allows to solve for A.x = b sparse linear problems using a generalized minimal - * residual method. The vectors x and b can be either dense or sparse. - * - * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix. - * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner - * - * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations() - * and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations - * and NumTraits<Scalar>::epsilon() for the tolerance. - * - * This class can be used as the direct solver classes. Here is a typical usage example: - * \code - * int n = 10000; - * VectorXd x(n), b(n); - * SparseMatrix<double> A(n,n); - * // fill A and b - * GMRES<SparseMatrix<double> > solver(A); - * x = solver.solve(b); - * std::cout << "#iterations: " << solver.iterations() << std::endl; - * std::cout << "estimated error: " << solver.error() << std::endl; - * // update b, and solve again - * x = solver.solve(b); - * \endcode - * - * By default the iterations start with x=0 as an initial guess of the solution. - * One can control the start using the solveWithGuess() method. - * - * GMRES can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink. - * - * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner - */ -template< typename _MatrixType, typename _Preconditioner> -class GMRES : public IterativeSolverBase<GMRES<_MatrixType,_Preconditioner> > -{ - typedef IterativeSolverBase<GMRES> Base; - using Base::matrix; - using Base::m_error; - using Base::m_iterations; - using Base::m_info; - using Base::m_isInitialized; - -private: - Index m_restart; - -public: - using Base::_solve_impl; - typedef _MatrixType MatrixType; - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::RealScalar RealScalar; - typedef _Preconditioner Preconditioner; - -public: - - /** Default constructor. */ - GMRES() : Base(), m_restart(30) {} - - /** Initialize the solver with matrix \a A for further \c Ax=b solving. - * - * This constructor is a shortcut for the default constructor followed - * by a call to compute(). - * - * \warning this class stores a reference to the matrix A as well as some - * precomputed values that depend on it. Therefore, if \a A is changed - * this class becomes invalid. Call compute() to update it with the new - * matrix A, or modify a copy of A. - */ - template<typename MatrixDerived> - explicit GMRES(const EigenBase<MatrixDerived>& A) : Base(A.derived()), m_restart(30) {} - - ~GMRES() {} - - /** Get the number of iterations after that a restart is performed. - */ - Index get_restart() { return m_restart; } - - /** Set the number of iterations after that a restart is performed. - * \param restart number of iterations for a restarti, default is 30. - */ - void set_restart(const Index restart) { m_restart=restart; } - - /** \internal */ - template<typename Rhs,typename Dest> - void _solve_with_guess_impl(const Rhs& b, Dest& x) const - { - bool failed = false; - for(Index j=0; j<b.cols(); ++j) - { - m_iterations = Base::maxIterations(); - m_error = Base::m_tolerance; - - typename Dest::ColXpr xj(x,j); - if(!internal::gmres(matrix(), b.col(j), xj, Base::m_preconditioner, m_iterations, m_restart, m_error)) - failed = true; - } - m_info = failed ? NumericalIssue - : m_error <= Base::m_tolerance ? Success - : NoConvergence; - m_isInitialized = true; - } - - /** \internal */ - template<typename Rhs,typename Dest> - void _solve_impl(const Rhs& b, MatrixBase<Dest> &x) const - { - x = b; - if(x.squaredNorm() == 0) return; // Check Zero right hand side - _solve_with_guess_impl(b,x.derived()); - } - -protected: - -}; - -} // end namespace Eigen - -#endif // EIGEN_GMRES_H diff --git a/eigen/unsupported/Eigen/src/IterativeSolvers/IncompleteLU.h b/eigen/unsupported/Eigen/src/IterativeSolvers/IncompleteLU.h deleted file mode 100644 index 7d08c35..0000000 --- a/eigen/unsupported/Eigen/src/IterativeSolvers/IncompleteLU.h +++ /dev/null @@ -1,90 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_INCOMPLETE_LU_H -#define EIGEN_INCOMPLETE_LU_H - -namespace Eigen { - -template <typename _Scalar> -class IncompleteLU : public SparseSolverBase<IncompleteLU<_Scalar> > -{ - protected: - typedef SparseSolverBase<IncompleteLU<_Scalar> > Base; - using Base::m_isInitialized; - - typedef _Scalar Scalar; - typedef Matrix<Scalar,Dynamic,1> Vector; - typedef typename Vector::Index Index; - typedef SparseMatrix<Scalar,RowMajor> FactorType; - - public: - typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType; - - IncompleteLU() {} - - template<typename MatrixType> - IncompleteLU(const MatrixType& mat) - { - compute(mat); - } - - Index rows() const { return m_lu.rows(); } - Index cols() const { return m_lu.cols(); } - - template<typename MatrixType> - IncompleteLU& compute(const MatrixType& mat) - { - m_lu = mat; - int size = mat.cols(); - Vector diag(size); - for(int i=0; i<size; ++i) - { - typename FactorType::InnerIterator k_it(m_lu,i); - for(; k_it && k_it.index()<i; ++k_it) - { - int k = k_it.index(); - k_it.valueRef() /= diag(k); - - typename FactorType::InnerIterator j_it(k_it); - typename FactorType::InnerIterator kj_it(m_lu, k); - while(kj_it && kj_it.index()<=k) ++kj_it; - for(++j_it; j_it; ) - { - if(kj_it.index()==j_it.index()) - { - j_it.valueRef() -= k_it.value() * kj_it.value(); - ++j_it; - ++kj_it; - } - else if(kj_it.index()<j_it.index()) ++kj_it; - else ++j_it; - } - } - if(k_it && k_it.index()==i) diag(i) = k_it.value(); - else diag(i) = 1; - } - m_isInitialized = true; - return *this; - } - - template<typename Rhs, typename Dest> - void _solve_impl(const Rhs& b, Dest& x) const - { - x = m_lu.template triangularView<UnitLower>().solve(b); - x = m_lu.template triangularView<Upper>().solve(x); - } - - protected: - FactorType m_lu; -}; - -} // end namespace Eigen - -#endif // EIGEN_INCOMPLETE_LU_H diff --git a/eigen/unsupported/Eigen/src/IterativeSolvers/IterationController.h b/eigen/unsupported/Eigen/src/IterativeSolvers/IterationController.h deleted file mode 100644 index c9c1a4b..0000000 --- a/eigen/unsupported/Eigen/src/IterativeSolvers/IterationController.h +++ /dev/null @@ -1,154 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> - -/* NOTE The class IterationController has been adapted from the iteration - * class of the GMM++ and ITL libraries. - */ - -//======================================================================= -// Copyright (C) 1997-2001 -// Authors: Andrew Lumsdaine <lums@osl.iu.edu> -// Lie-Quan Lee <llee@osl.iu.edu> -// -// This file is part of the Iterative Template Library -// -// You should have received a copy of the License Agreement for the -// Iterative Template Library along with the software; see the -// file LICENSE. -// -// Permission to modify the code and to distribute modified code is -// granted, provided the text of this NOTICE is retained, a notice that -// the code was modified is included with the above COPYRIGHT NOTICE and -// with the COPYRIGHT NOTICE in the LICENSE file, and that the LICENSE -// file is distributed with the modified code. -// -// LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. -// By way of example, but not limitation, Licensor MAKES NO -// REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY -// PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS -// OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS -// OR OTHER RIGHTS. -//======================================================================= - -//======================================================================== -// -// Copyright (C) 2002-2007 Yves Renard -// -// This file is a part of GETFEM++ -// -// Getfem++ 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; version 2.1 of the License. -// -// This program 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 for more details. -// You should have received a copy of the GNU Lesser General Public -// License along with this program; if not, write to the Free Software -// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, -// USA. -// -//======================================================================== - -#include "../../../../Eigen/src/Core/util/NonMPL2.h" - -#ifndef EIGEN_ITERATION_CONTROLLER_H -#define EIGEN_ITERATION_CONTROLLER_H - -namespace Eigen { - -/** \ingroup IterativeSolvers_Module - * \class IterationController - * - * \brief Controls the iterations of the iterative solvers - * - * This class has been adapted from the iteration class of GMM++ and ITL libraries. - * - */ -class IterationController -{ - protected : - double m_rhsn; ///< Right hand side norm - size_t m_maxiter; ///< Max. number of iterations - int m_noise; ///< if noise > 0 iterations are printed - double m_resmax; ///< maximum residual - double m_resminreach, m_resadd; - size_t m_nit; ///< iteration number - double m_res; ///< last computed residual - bool m_written; - void (*m_callback)(const IterationController&); - public : - - void init() - { - m_nit = 0; m_res = 0.0; m_written = false; - m_resminreach = 1E50; m_resadd = 0.0; - m_callback = 0; - } - - IterationController(double r = 1.0E-8, int noi = 0, size_t mit = size_t(-1)) - : m_rhsn(1.0), m_maxiter(mit), m_noise(noi), m_resmax(r) { init(); } - - void operator ++(int) { m_nit++; m_written = false; m_resadd += m_res; } - void operator ++() { (*this)++; } - - bool first() { return m_nit == 0; } - - /* get/set the "noisyness" (verbosity) of the solvers */ - int noiseLevel() const { return m_noise; } - void setNoiseLevel(int n) { m_noise = n; } - void reduceNoiseLevel() { if (m_noise > 0) m_noise--; } - - double maxResidual() const { return m_resmax; } - void setMaxResidual(double r) { m_resmax = r; } - - double residual() const { return m_res; } - - /* change the user-definable callback, called after each iteration */ - void setCallback(void (*t)(const IterationController&)) - { - m_callback = t; - } - - size_t iteration() const { return m_nit; } - void setIteration(size_t i) { m_nit = i; } - - size_t maxIterarions() const { return m_maxiter; } - void setMaxIterations(size_t i) { m_maxiter = i; } - - double rhsNorm() const { return m_rhsn; } - void setRhsNorm(double r) { m_rhsn = r; } - - bool converged() const { return m_res <= m_rhsn * m_resmax; } - bool converged(double nr) - { - using std::abs; - m_res = abs(nr); - m_resminreach = (std::min)(m_resminreach, m_res); - return converged(); - } - template<typename VectorType> bool converged(const VectorType &v) - { return converged(v.squaredNorm()); } - - bool finished(double nr) - { - if (m_callback) m_callback(*this); - if (m_noise > 0 && !m_written) - { - converged(nr); - m_written = true; - } - return (m_nit >= m_maxiter || converged(nr)); - } - template <typename VectorType> - bool finished(const MatrixBase<VectorType> &v) - { return finished(double(v.squaredNorm())); } - -}; - -} // end namespace Eigen - -#endif // EIGEN_ITERATION_CONTROLLER_H diff --git a/eigen/unsupported/Eigen/src/IterativeSolvers/MINRES.h b/eigen/unsupported/Eigen/src/IterativeSolvers/MINRES.h deleted file mode 100644 index 256990c..0000000 --- a/eigen/unsupported/Eigen/src/IterativeSolvers/MINRES.h +++ /dev/null @@ -1,289 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2012 Giacomo Po <gpo@ucla.edu> -// Copyright (C) 2011-2014 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -#ifndef EIGEN_MINRES_H_ -#define EIGEN_MINRES_H_ - - -namespace Eigen { - - namespace internal { - - /** \internal Low-level MINRES algorithm - * \param mat The matrix A - * \param rhs The right hand side vector b - * \param x On input and initial solution, on output the computed solution. - * \param precond A right preconditioner being able to efficiently solve for an - * approximation of Ax=b (regardless of b) - * \param iters On input the max number of iteration, on output the number of performed iterations. - * \param tol_error On input the tolerance error, on output an estimation of the relative error. - */ - template<typename MatrixType, typename Rhs, typename Dest, typename Preconditioner> - EIGEN_DONT_INLINE - void minres(const MatrixType& mat, const Rhs& rhs, Dest& x, - const Preconditioner& precond, Index& iters, - typename Dest::RealScalar& tol_error) - { - using std::sqrt; - typedef typename Dest::RealScalar RealScalar; - typedef typename Dest::Scalar Scalar; - typedef Matrix<Scalar,Dynamic,1> VectorType; - - // Check for zero rhs - const RealScalar rhsNorm2(rhs.squaredNorm()); - if(rhsNorm2 == 0) - { - x.setZero(); - iters = 0; - tol_error = 0; - return; - } - - // initialize - const Index maxIters(iters); // initialize maxIters to iters - const Index N(mat.cols()); // the size of the matrix - const RealScalar threshold2(tol_error*tol_error*rhsNorm2); // convergence threshold (compared to residualNorm2) - - // Initialize preconditioned Lanczos - VectorType v_old(N); // will be initialized inside loop - VectorType v( VectorType::Zero(N) ); //initialize v - VectorType v_new(rhs-mat*x); //initialize v_new - RealScalar residualNorm2(v_new.squaredNorm()); - VectorType w(N); // will be initialized inside loop - VectorType w_new(precond.solve(v_new)); // initialize w_new -// RealScalar beta; // will be initialized inside loop - RealScalar beta_new2(v_new.dot(w_new)); - eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE"); - RealScalar beta_new(sqrt(beta_new2)); - const RealScalar beta_one(beta_new); - v_new /= beta_new; - w_new /= beta_new; - // Initialize other variables - RealScalar c(1.0); // the cosine of the Givens rotation - RealScalar c_old(1.0); - RealScalar s(0.0); // the sine of the Givens rotation - RealScalar s_old(0.0); // the sine of the Givens rotation - VectorType p_oold(N); // will be initialized in loop - VectorType p_old(VectorType::Zero(N)); // initialize p_old=0 - VectorType p(p_old); // initialize p=0 - RealScalar eta(1.0); - - iters = 0; // reset iters - while ( iters < maxIters ) - { - // Preconditioned Lanczos - /* Note that there are 4 variants on the Lanczos algorithm. These are - * described in Paige, C. C. (1972). Computational variants of - * the Lanczos method for the eigenproblem. IMA Journal of Applied - * Mathematics, 10(3), 373–381. The current implementation corresponds - * to the case A(2,7) in the paper. It also corresponds to - * algorithm 6.14 in Y. Saad, Iterative Methods for Sparse Linear - * Systems, 2003 p.173. For the preconditioned version see - * A. Greenbaum, Iterative Methods for Solving Linear Systems, SIAM (1987). - */ - const RealScalar beta(beta_new); - v_old = v; // update: at first time step, this makes v_old = 0 so value of beta doesn't matter -// const VectorType v_old(v); // NOT SURE IF CREATING v_old EVERY ITERATION IS EFFICIENT - v = v_new; // update - w = w_new; // update -// const VectorType w(w_new); // NOT SURE IF CREATING w EVERY ITERATION IS EFFICIENT - v_new.noalias() = mat*w - beta*v_old; // compute v_new - const RealScalar alpha = v_new.dot(w); - v_new -= alpha*v; // overwrite v_new - w_new = precond.solve(v_new); // overwrite w_new - beta_new2 = v_new.dot(w_new); // compute beta_new - eigen_assert(beta_new2 >= 0.0 && "PRECONDITIONER IS NOT POSITIVE DEFINITE"); - beta_new = sqrt(beta_new2); // compute beta_new - v_new /= beta_new; // overwrite v_new for next iteration - w_new /= beta_new; // overwrite w_new for next iteration - - // Givens rotation - const RealScalar r2 =s*alpha+c*c_old*beta; // s, s_old, c and c_old are still from previous iteration - const RealScalar r3 =s_old*beta; // s, s_old, c and c_old are still from previous iteration - const RealScalar r1_hat=c*alpha-c_old*s*beta; - const RealScalar r1 =sqrt( std::pow(r1_hat,2) + std::pow(beta_new,2) ); - c_old = c; // store for next iteration - s_old = s; // store for next iteration - c=r1_hat/r1; // new cosine - s=beta_new/r1; // new sine - - // Update solution - p_oold = p_old; -// const VectorType p_oold(p_old); // NOT SURE IF CREATING p_oold EVERY ITERATION IS EFFICIENT - p_old = p; - p.noalias()=(w-r2*p_old-r3*p_oold) /r1; // IS NOALIAS REQUIRED? - x += beta_one*c*eta*p; - - /* Update the squared residual. Note that this is the estimated residual. - The real residual |Ax-b|^2 may be slightly larger */ - residualNorm2 *= s*s; - - if ( residualNorm2 < threshold2) - { - break; - } - - eta=-s*eta; // update eta - iters++; // increment iteration number (for output purposes) - } - - /* Compute error. Note that this is the estimated error. The real - error |Ax-b|/|b| may be slightly larger */ - tol_error = std::sqrt(residualNorm2 / rhsNorm2); - } - - } - - template< typename _MatrixType, int _UpLo=Lower, - typename _Preconditioner = IdentityPreconditioner> - class MINRES; - - namespace internal { - - template< typename _MatrixType, int _UpLo, typename _Preconditioner> - struct traits<MINRES<_MatrixType,_UpLo,_Preconditioner> > - { - typedef _MatrixType MatrixType; - typedef _Preconditioner Preconditioner; - }; - - } - - /** \ingroup IterativeLinearSolvers_Module - * \brief A minimal residual solver for sparse symmetric problems - * - * This class allows to solve for A.x = b sparse linear problems using the MINRES algorithm - * of Paige and Saunders (1975). The sparse matrix A must be symmetric (possibly indefinite). - * The vectors x and b can be either dense or sparse. - * - * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix. - * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower, - * Upper, or Lower|Upper in which the full matrix entries will be considered. Default is Lower. - * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner - * - * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations() - * and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations - * and NumTraits<Scalar>::epsilon() for the tolerance. - * - * This class can be used as the direct solver classes. Here is a typical usage example: - * \code - * int n = 10000; - * VectorXd x(n), b(n); - * SparseMatrix<double> A(n,n); - * // fill A and b - * MINRES<SparseMatrix<double> > mr; - * mr.compute(A); - * x = mr.solve(b); - * std::cout << "#iterations: " << mr.iterations() << std::endl; - * std::cout << "estimated error: " << mr.error() << std::endl; - * // update b, and solve again - * x = mr.solve(b); - * \endcode - * - * By default the iterations start with x=0 as an initial guess of the solution. - * One can control the start using the solveWithGuess() method. - * - * MINRES can also be used in a matrix-free context, see the following \link MatrixfreeSolverExample example \endlink. - * - * \sa class ConjugateGradient, BiCGSTAB, SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner - */ - template< typename _MatrixType, int _UpLo, typename _Preconditioner> - class MINRES : public IterativeSolverBase<MINRES<_MatrixType,_UpLo,_Preconditioner> > - { - - typedef IterativeSolverBase<MINRES> Base; - using Base::matrix; - using Base::m_error; - using Base::m_iterations; - using Base::m_info; - using Base::m_isInitialized; - public: - using Base::_solve_impl; - typedef _MatrixType MatrixType; - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::RealScalar RealScalar; - typedef _Preconditioner Preconditioner; - - enum {UpLo = _UpLo}; - - public: - - /** Default constructor. */ - MINRES() : Base() {} - - /** Initialize the solver with matrix \a A for further \c Ax=b solving. - * - * This constructor is a shortcut for the default constructor followed - * by a call to compute(). - * - * \warning this class stores a reference to the matrix A as well as some - * precomputed values that depend on it. Therefore, if \a A is changed - * this class becomes invalid. Call compute() to update it with the new - * matrix A, or modify a copy of A. - */ - template<typename MatrixDerived> - explicit MINRES(const EigenBase<MatrixDerived>& A) : Base(A.derived()) {} - - /** Destructor. */ - ~MINRES(){} - - /** \internal */ - template<typename Rhs,typename Dest> - void _solve_with_guess_impl(const Rhs& b, Dest& x) const - { - typedef typename Base::MatrixWrapper MatrixWrapper; - typedef typename Base::ActualMatrixType ActualMatrixType; - enum { - TransposeInput = (!MatrixWrapper::MatrixFree) - && (UpLo==(Lower|Upper)) - && (!MatrixType::IsRowMajor) - && (!NumTraits<Scalar>::IsComplex) - }; - typedef typename internal::conditional<TransposeInput,Transpose<const ActualMatrixType>, ActualMatrixType const&>::type RowMajorWrapper; - EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(MatrixWrapper::MatrixFree,UpLo==(Lower|Upper)),MATRIX_FREE_CONJUGATE_GRADIENT_IS_COMPATIBLE_WITH_UPPER_UNION_LOWER_MODE_ONLY); - typedef typename internal::conditional<UpLo==(Lower|Upper), - RowMajorWrapper, - typename MatrixWrapper::template ConstSelfAdjointViewReturnType<UpLo>::Type - >::type SelfAdjointWrapper; - - m_iterations = Base::maxIterations(); - m_error = Base::m_tolerance; - RowMajorWrapper row_mat(matrix()); - for(int j=0; j<b.cols(); ++j) - { - m_iterations = Base::maxIterations(); - m_error = Base::m_tolerance; - - typename Dest::ColXpr xj(x,j); - internal::minres(SelfAdjointWrapper(row_mat), b.col(j), xj, - Base::m_preconditioner, m_iterations, m_error); - } - - m_isInitialized = true; - m_info = m_error <= Base::m_tolerance ? Success : NoConvergence; - } - - /** \internal */ - template<typename Rhs,typename Dest> - void _solve_impl(const Rhs& b, MatrixBase<Dest> &x) const - { - x.setZero(); - _solve_with_guess_impl(b,x.derived()); - } - - protected: - - }; - -} // end namespace Eigen - -#endif // EIGEN_MINRES_H - diff --git a/eigen/unsupported/Eigen/src/IterativeSolvers/Scaling.h b/eigen/unsupported/Eigen/src/IterativeSolvers/Scaling.h deleted file mode 100644 index d113e6e..0000000 --- a/eigen/unsupported/Eigen/src/IterativeSolvers/Scaling.h +++ /dev/null @@ -1,187 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2012 Desire NUENTSA WAKAM <desire.nuentsa_wakam@inria.fr -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_ITERSCALING_H -#define EIGEN_ITERSCALING_H - -namespace Eigen { - -/** - * \ingroup IterativeSolvers_Module - * \brief iterative scaling algorithm to equilibrate rows and column norms in matrices - * - * This class can be used as a preprocessing tool to accelerate the convergence of iterative methods - * - * This feature is useful to limit the pivoting amount during LU/ILU factorization - * The scaling strategy as presented here preserves the symmetry of the problem - * NOTE It is assumed that the matrix does not have empty row or column, - * - * Example with key steps - * \code - * VectorXd x(n), b(n); - * SparseMatrix<double> A; - * // fill A and b; - * IterScaling<SparseMatrix<double> > scal; - * // Compute the left and right scaling vectors. The matrix is equilibrated at output - * scal.computeRef(A); - * // Scale the right hand side - * b = scal.LeftScaling().cwiseProduct(b); - * // Now, solve the equilibrated linear system with any available solver - * - * // Scale back the computed solution - * x = scal.RightScaling().cwiseProduct(x); - * \endcode - * - * \tparam _MatrixType the type of the matrix. It should be a real square sparsematrix - * - * References : D. Ruiz and B. Ucar, A Symmetry Preserving Algorithm for Matrix Scaling, INRIA Research report RR-7552 - * - * \sa \ref IncompleteLUT - */ -template<typename _MatrixType> -class IterScaling -{ - public: - typedef _MatrixType MatrixType; - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::Index Index; - - public: - IterScaling() { init(); } - - IterScaling(const MatrixType& matrix) - { - init(); - compute(matrix); - } - - ~IterScaling() { } - - /** - * Compute the left and right diagonal matrices to scale the input matrix @p mat - * - * FIXME This algorithm will be modified such that the diagonal elements are permuted on the diagonal. - * - * \sa LeftScaling() RightScaling() - */ - void compute (const MatrixType& mat) - { - using std::abs; - int m = mat.rows(); - int n = mat.cols(); - eigen_assert((m>0 && m == n) && "Please give a non - empty matrix"); - m_left.resize(m); - m_right.resize(n); - m_left.setOnes(); - m_right.setOnes(); - m_matrix = mat; - VectorXd Dr, Dc, DrRes, DcRes; // Temporary Left and right scaling vectors - Dr.resize(m); Dc.resize(n); - DrRes.resize(m); DcRes.resize(n); - double EpsRow = 1.0, EpsCol = 1.0; - int its = 0; - do - { // Iterate until the infinite norm of each row and column is approximately 1 - // Get the maximum value in each row and column - Dr.setZero(); Dc.setZero(); - for (int k=0; k<m_matrix.outerSize(); ++k) - { - for (typename MatrixType::InnerIterator it(m_matrix, k); it; ++it) - { - if ( Dr(it.row()) < abs(it.value()) ) - Dr(it.row()) = abs(it.value()); - - if ( Dc(it.col()) < abs(it.value()) ) - Dc(it.col()) = abs(it.value()); - } - } - for (int i = 0; i < m; ++i) - { - Dr(i) = std::sqrt(Dr(i)); - Dc(i) = std::sqrt(Dc(i)); - } - // Save the scaling factors - for (int i = 0; i < m; ++i) - { - m_left(i) /= Dr(i); - m_right(i) /= Dc(i); - } - // Scale the rows and the columns of the matrix - DrRes.setZero(); DcRes.setZero(); - for (int k=0; k<m_matrix.outerSize(); ++k) - { - for (typename MatrixType::InnerIterator it(m_matrix, k); it; ++it) - { - it.valueRef() = it.value()/( Dr(it.row()) * Dc(it.col()) ); - // Accumulate the norms of the row and column vectors - if ( DrRes(it.row()) < abs(it.value()) ) - DrRes(it.row()) = abs(it.value()); - - if ( DcRes(it.col()) < abs(it.value()) ) - DcRes(it.col()) = abs(it.value()); - } - } - DrRes.array() = (1-DrRes.array()).abs(); - EpsRow = DrRes.maxCoeff(); - DcRes.array() = (1-DcRes.array()).abs(); - EpsCol = DcRes.maxCoeff(); - its++; - }while ( (EpsRow >m_tol || EpsCol > m_tol) && (its < m_maxits) ); - m_isInitialized = true; - } - /** Compute the left and right vectors to scale the vectors - * the input matrix is scaled with the computed vectors at output - * - * \sa compute() - */ - void computeRef (MatrixType& mat) - { - compute (mat); - mat = m_matrix; - } - /** Get the vector to scale the rows of the matrix - */ - VectorXd& LeftScaling() - { - return m_left; - } - - /** Get the vector to scale the columns of the matrix - */ - VectorXd& RightScaling() - { - return m_right; - } - - /** Set the tolerance for the convergence of the iterative scaling algorithm - */ - void setTolerance(double tol) - { - m_tol = tol; - } - - protected: - - void init() - { - m_tol = 1e-10; - m_maxits = 5; - m_isInitialized = false; - } - - MatrixType m_matrix; - mutable ComputationInfo m_info; - bool m_isInitialized; - VectorXd m_left; // Left scaling vector - VectorXd m_right; // m_right scaling vector - double m_tol; - int m_maxits; // Maximum number of iterations allowed -}; -} -#endif diff --git a/eigen/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h b/eigen/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h deleted file mode 100644 index 582fa85..0000000 --- a/eigen/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h +++ /dev/null @@ -1,305 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2011 Kolja Brix <brix@igpm.rwth-aachen.de> -// Copyright (C) 2011 Andreas Platen <andiplaten@gmx.de> -// Copyright (C) 2012 Chen-Pang He <jdh8@ms63.hinet.net> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef KRONECKER_TENSOR_PRODUCT_H -#define KRONECKER_TENSOR_PRODUCT_H - -namespace Eigen { - -/*! - * \ingroup KroneckerProduct_Module - * - * \brief The base class of dense and sparse Kronecker product. - * - * \tparam Derived is the derived type. - */ -template<typename Derived> -class KroneckerProductBase : public ReturnByValue<Derived> -{ - private: - typedef typename internal::traits<Derived> Traits; - typedef typename Traits::Scalar Scalar; - - protected: - typedef typename Traits::Lhs Lhs; - typedef typename Traits::Rhs Rhs; - - public: - /*! \brief Constructor. */ - KroneckerProductBase(const Lhs& A, const Rhs& B) - : m_A(A), m_B(B) - {} - - inline Index rows() const { return m_A.rows() * m_B.rows(); } - inline Index cols() const { return m_A.cols() * m_B.cols(); } - - /*! - * This overrides ReturnByValue::coeff because this function is - * efficient enough. - */ - Scalar coeff(Index row, Index col) const - { - return m_A.coeff(row / m_B.rows(), col / m_B.cols()) * - m_B.coeff(row % m_B.rows(), col % m_B.cols()); - } - - /*! - * This overrides ReturnByValue::coeff because this function is - * efficient enough. - */ - Scalar coeff(Index i) const - { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); - return m_A.coeff(i / m_A.size()) * m_B.coeff(i % m_A.size()); - } - - protected: - typename Lhs::Nested m_A; - typename Rhs::Nested m_B; -}; - -/*! - * \ingroup KroneckerProduct_Module - * - * \brief Kronecker tensor product helper class for dense matrices - * - * This class is the return value of kroneckerProduct(MatrixBase, - * MatrixBase). Use the function rather than construct this class - * directly to avoid specifying template prarameters. - * - * \tparam Lhs Type of the left-hand side, a matrix expression. - * \tparam Rhs Type of the rignt-hand side, a matrix expression. - */ -template<typename Lhs, typename Rhs> -class KroneckerProduct : public KroneckerProductBase<KroneckerProduct<Lhs,Rhs> > -{ - private: - typedef KroneckerProductBase<KroneckerProduct> Base; - using Base::m_A; - using Base::m_B; - - public: - /*! \brief Constructor. */ - KroneckerProduct(const Lhs& A, const Rhs& B) - : Base(A, B) - {} - - /*! \brief Evaluate the Kronecker tensor product. */ - template<typename Dest> void evalTo(Dest& dst) const; -}; - -/*! - * \ingroup KroneckerProduct_Module - * - * \brief Kronecker tensor product helper class for sparse matrices - * - * If at least one of the operands is a sparse matrix expression, - * then this class is returned and evaluates into a sparse matrix. - * - * This class is the return value of kroneckerProduct(EigenBase, - * EigenBase). Use the function rather than construct this class - * directly to avoid specifying template prarameters. - * - * \tparam Lhs Type of the left-hand side, a matrix expression. - * \tparam Rhs Type of the rignt-hand side, a matrix expression. - */ -template<typename Lhs, typename Rhs> -class KroneckerProductSparse : public KroneckerProductBase<KroneckerProductSparse<Lhs,Rhs> > -{ - private: - typedef KroneckerProductBase<KroneckerProductSparse> Base; - using Base::m_A; - using Base::m_B; - - public: - /*! \brief Constructor. */ - KroneckerProductSparse(const Lhs& A, const Rhs& B) - : Base(A, B) - {} - - /*! \brief Evaluate the Kronecker tensor product. */ - template<typename Dest> void evalTo(Dest& dst) const; -}; - -template<typename Lhs, typename Rhs> -template<typename Dest> -void KroneckerProduct<Lhs,Rhs>::evalTo(Dest& dst) const -{ - const int BlockRows = Rhs::RowsAtCompileTime, - BlockCols = Rhs::ColsAtCompileTime; - const Index Br = m_B.rows(), - Bc = m_B.cols(); - for (Index i=0; i < m_A.rows(); ++i) - for (Index j=0; j < m_A.cols(); ++j) - Block<Dest,BlockRows,BlockCols>(dst,i*Br,j*Bc,Br,Bc) = m_A.coeff(i,j) * m_B; -} - -template<typename Lhs, typename Rhs> -template<typename Dest> -void KroneckerProductSparse<Lhs,Rhs>::evalTo(Dest& dst) const -{ - Index Br = m_B.rows(), Bc = m_B.cols(); - dst.resize(this->rows(), this->cols()); - dst.resizeNonZeros(0); - - // 1 - evaluate the operands if needed: - typedef typename internal::nested_eval<Lhs,Dynamic>::type Lhs1; - typedef typename internal::remove_all<Lhs1>::type Lhs1Cleaned; - const Lhs1 lhs1(m_A); - typedef typename internal::nested_eval<Rhs,Dynamic>::type Rhs1; - typedef typename internal::remove_all<Rhs1>::type Rhs1Cleaned; - const Rhs1 rhs1(m_B); - - // 2 - construct respective iterators - typedef Eigen::InnerIterator<Lhs1Cleaned> LhsInnerIterator; - typedef Eigen::InnerIterator<Rhs1Cleaned> RhsInnerIterator; - - // compute number of non-zeros per innervectors of dst - { - // TODO VectorXi is not necessarily big enough! - VectorXi nnzA = VectorXi::Zero(Dest::IsRowMajor ? m_A.rows() : m_A.cols()); - for (Index kA=0; kA < m_A.outerSize(); ++kA) - for (LhsInnerIterator itA(lhs1,kA); itA; ++itA) - nnzA(Dest::IsRowMajor ? itA.row() : itA.col())++; - - VectorXi nnzB = VectorXi::Zero(Dest::IsRowMajor ? m_B.rows() : m_B.cols()); - for (Index kB=0; kB < m_B.outerSize(); ++kB) - for (RhsInnerIterator itB(rhs1,kB); itB; ++itB) - nnzB(Dest::IsRowMajor ? itB.row() : itB.col())++; - - Matrix<int,Dynamic,Dynamic,ColMajor> nnzAB = nnzB * nnzA.transpose(); - dst.reserve(VectorXi::Map(nnzAB.data(), nnzAB.size())); - } - - for (Index kA=0; kA < m_A.outerSize(); ++kA) - { - for (Index kB=0; kB < m_B.outerSize(); ++kB) - { - for (LhsInnerIterator itA(lhs1,kA); itA; ++itA) - { - for (RhsInnerIterator itB(rhs1,kB); itB; ++itB) - { - Index i = itA.row() * Br + itB.row(), - j = itA.col() * Bc + itB.col(); - dst.insert(i,j) = itA.value() * itB.value(); - } - } - } - } -} - -namespace internal { - -template<typename _Lhs, typename _Rhs> -struct traits<KroneckerProduct<_Lhs,_Rhs> > -{ - typedef typename remove_all<_Lhs>::type Lhs; - typedef typename remove_all<_Rhs>::type Rhs; - typedef typename ScalarBinaryOpTraits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar; - typedef typename promote_index_type<typename Lhs::StorageIndex, typename Rhs::StorageIndex>::type StorageIndex; - - enum { - Rows = size_at_compile_time<traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime>::ret, - Cols = size_at_compile_time<traits<Lhs>::ColsAtCompileTime, traits<Rhs>::ColsAtCompileTime>::ret, - MaxRows = size_at_compile_time<traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime>::ret, - MaxCols = size_at_compile_time<traits<Lhs>::MaxColsAtCompileTime, traits<Rhs>::MaxColsAtCompileTime>::ret - }; - - typedef Matrix<Scalar,Rows,Cols> ReturnType; -}; - -template<typename _Lhs, typename _Rhs> -struct traits<KroneckerProductSparse<_Lhs,_Rhs> > -{ - typedef MatrixXpr XprKind; - typedef typename remove_all<_Lhs>::type Lhs; - typedef typename remove_all<_Rhs>::type Rhs; - typedef typename ScalarBinaryOpTraits<typename Lhs::Scalar, typename Rhs::Scalar>::ReturnType Scalar; - typedef typename cwise_promote_storage_type<typename traits<Lhs>::StorageKind, typename traits<Rhs>::StorageKind, scalar_product_op<typename Lhs::Scalar, typename Rhs::Scalar> >::ret StorageKind; - typedef typename promote_index_type<typename Lhs::StorageIndex, typename Rhs::StorageIndex>::type StorageIndex; - - enum { - LhsFlags = Lhs::Flags, - RhsFlags = Rhs::Flags, - - RowsAtCompileTime = size_at_compile_time<traits<Lhs>::RowsAtCompileTime, traits<Rhs>::RowsAtCompileTime>::ret, - ColsAtCompileTime = size_at_compile_time<traits<Lhs>::ColsAtCompileTime, traits<Rhs>::ColsAtCompileTime>::ret, - MaxRowsAtCompileTime = size_at_compile_time<traits<Lhs>::MaxRowsAtCompileTime, traits<Rhs>::MaxRowsAtCompileTime>::ret, - MaxColsAtCompileTime = size_at_compile_time<traits<Lhs>::MaxColsAtCompileTime, traits<Rhs>::MaxColsAtCompileTime>::ret, - - EvalToRowMajor = (LhsFlags & RhsFlags & RowMajorBit), - RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit), - - Flags = ((LhsFlags | RhsFlags) & HereditaryBits & RemovedBits) - | EvalBeforeNestingBit, - CoeffReadCost = HugeCost - }; - - typedef SparseMatrix<Scalar, 0, StorageIndex> ReturnType; -}; - -} // end namespace internal - -/*! - * \ingroup KroneckerProduct_Module - * - * Computes Kronecker tensor product of two dense matrices - * - * \warning If you want to replace a matrix by its Kronecker product - * with some matrix, do \b NOT do this: - * \code - * A = kroneckerProduct(A,B); // bug!!! caused by aliasing effect - * \endcode - * instead, use eval() to work around this: - * \code - * A = kroneckerProduct(A,B).eval(); - * \endcode - * - * \param a Dense matrix a - * \param b Dense matrix b - * \return Kronecker tensor product of a and b - */ -template<typename A, typename B> -KroneckerProduct<A,B> kroneckerProduct(const MatrixBase<A>& a, const MatrixBase<B>& b) -{ - return KroneckerProduct<A, B>(a.derived(), b.derived()); -} - -/*! - * \ingroup KroneckerProduct_Module - * - * Computes Kronecker tensor product of two matrices, at least one of - * which is sparse - * - * \warning If you want to replace a matrix by its Kronecker product - * with some matrix, do \b NOT do this: - * \code - * A = kroneckerProduct(A,B); // bug!!! caused by aliasing effect - * \endcode - * instead, use eval() to work around this: - * \code - * A = kroneckerProduct(A,B).eval(); - * \endcode - * - * \param a Dense/sparse matrix a - * \param b Dense/sparse matrix b - * \return Kronecker tensor product of a and b, stored in a sparse - * matrix - */ -template<typename A, typename B> -KroneckerProductSparse<A,B> kroneckerProduct(const EigenBase<A>& a, const EigenBase<B>& b) -{ - return KroneckerProductSparse<A,B>(a.derived(), b.derived()); -} - -} // end namespace Eigen - -#endif // KRONECKER_TENSOR_PRODUCT_H diff --git a/eigen/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt b/eigen/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt deleted file mode 100644 index ae7984d..0000000 --- a/eigen/unsupported/Eigen/src/LevenbergMarquardt/CopyrightMINPACK.txt +++ /dev/null @@ -1,52 +0,0 @@ -Minpack Copyright Notice (1999) University of Chicago. All rights reserved - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the -following conditions are met: - -1. Redistributions of source code must retain the above -copyright notice, this list of conditions and the following -disclaimer. - -2. Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following -disclaimer in the documentation and/or other materials -provided with the distribution. - -3. The end-user documentation included with the -redistribution, if any, must include the following -acknowledgment: - - "This product includes software developed by the - University of Chicago, as Operator of Argonne National - Laboratory. - -Alternately, this acknowledgment may appear in the software -itself, if and wherever such third-party acknowledgments -normally appear. - -4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" -WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE -UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND -THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE -OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY -OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF -THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) -DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION -UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL -BE CORRECTED. - -5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT -HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF -ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, -INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF -ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF -PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER -SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT -(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, -EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE -POSSIBILITY OF SUCH LOSS OR DAMAGES. - diff --git a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h b/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h deleted file mode 100644 index b75bea2..0000000 --- a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMcovar.h +++ /dev/null @@ -1,84 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// This code initially comes from MINPACK whose original authors are: -// Copyright Jorge More - Argonne National Laboratory -// Copyright Burt Garbow - Argonne National Laboratory -// Copyright Ken Hillstrom - Argonne National Laboratory -// -// This Source Code Form is subject to the terms of the Minpack license -// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file. - -#ifndef EIGEN_LMCOVAR_H -#define EIGEN_LMCOVAR_H - -namespace Eigen { - -namespace internal { - -template <typename Scalar> -void covar( - Matrix< Scalar, Dynamic, Dynamic > &r, - const VectorXi& ipvt, - Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) ) -{ - using std::abs; - /* Local variables */ - Index i, j, k, l, ii, jj; - bool sing; - Scalar temp; - - /* Function Body */ - const Index n = r.cols(); - const Scalar tolr = tol * abs(r(0,0)); - Matrix< Scalar, Dynamic, 1 > wa(n); - eigen_assert(ipvt.size()==n); - - /* form the inverse of r in the full upper triangle of r. */ - l = -1; - for (k = 0; k < n; ++k) - if (abs(r(k,k)) > tolr) { - r(k,k) = 1. / r(k,k); - for (j = 0; j <= k-1; ++j) { - temp = r(k,k) * r(j,k); - r(j,k) = 0.; - r.col(k).head(j+1) -= r.col(j).head(j+1) * temp; - } - l = k; - } - - /* form the full upper triangle of the inverse of (r transpose)*r */ - /* in the full upper triangle of r. */ - for (k = 0; k <= l; ++k) { - for (j = 0; j <= k-1; ++j) - r.col(j).head(j+1) += r.col(k).head(j+1) * r(j,k); - r.col(k).head(k+1) *= r(k,k); - } - - /* form the full lower triangle of the covariance matrix */ - /* in the strict lower triangle of r and in wa. */ - for (j = 0; j < n; ++j) { - jj = ipvt[j]; - sing = j > l; - for (i = 0; i <= j; ++i) { - if (sing) - r(i,j) = 0.; - ii = ipvt[i]; - if (ii > jj) - r(ii,jj) = r(i,j); - if (ii < jj) - r(jj,ii) = r(i,j); - } - wa[jj] = r(j,j); - } - - /* symmetrize the covariance matrix in r. */ - r.topLeftCorner(n,n).template triangularView<StrictlyUpper>() = r.topLeftCorner(n,n).transpose(); - r.diagonal() = wa; -} - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_LMCOVAR_H diff --git a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h b/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h deleted file mode 100644 index 25b32ec..0000000 --- a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMonestep.h +++ /dev/null @@ -1,202 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> -// -// This code initially comes from MINPACK whose original authors are: -// Copyright Jorge More - Argonne National Laboratory -// Copyright Burt Garbow - Argonne National Laboratory -// Copyright Ken Hillstrom - Argonne National Laboratory -// -// This Source Code Form is subject to the terms of the Minpack license -// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file. - -#ifndef EIGEN_LMONESTEP_H -#define EIGEN_LMONESTEP_H - -namespace Eigen { - -template<typename FunctorType> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType>::minimizeOneStep(FVectorType &x) -{ - using std::abs; - using std::sqrt; - RealScalar temp, temp1,temp2; - RealScalar ratio; - RealScalar pnorm, xnorm, fnorm1, actred, dirder, prered; - eigen_assert(x.size()==n); // check the caller is not cheating us - - temp = 0.0; xnorm = 0.0; - /* calculate the jacobian matrix. */ - Index df_ret = m_functor.df(x, m_fjac); - if (df_ret<0) - return LevenbergMarquardtSpace::UserAsked; - if (df_ret>0) - // numerical diff, we evaluated the function df_ret times - m_nfev += df_ret; - else m_njev++; - - /* compute the qr factorization of the jacobian. */ - for (int j = 0; j < x.size(); ++j) - m_wa2(j) = m_fjac.col(j).blueNorm(); - QRSolver qrfac(m_fjac); - if(qrfac.info() != Success) { - m_info = NumericalIssue; - return LevenbergMarquardtSpace::ImproperInputParameters; - } - // Make a copy of the first factor with the associated permutation - m_rfactor = qrfac.matrixR(); - m_permutation = (qrfac.colsPermutation()); - - /* on the first iteration and if external scaling is not used, scale according */ - /* to the norms of the columns of the initial jacobian. */ - if (m_iter == 1) { - if (!m_useExternalScaling) - for (Index j = 0; j < n; ++j) - m_diag[j] = (m_wa2[j]==0.)? 1. : m_wa2[j]; - - /* on the first iteration, calculate the norm of the scaled x */ - /* and initialize the step bound m_delta. */ - xnorm = m_diag.cwiseProduct(x).stableNorm(); - m_delta = m_factor * xnorm; - if (m_delta == 0.) - m_delta = m_factor; - } - - /* form (q transpose)*m_fvec and store the first n components in */ - /* m_qtf. */ - m_wa4 = m_fvec; - m_wa4 = qrfac.matrixQ().adjoint() * m_fvec; - m_qtf = m_wa4.head(n); - - /* compute the norm of the scaled gradient. */ - m_gnorm = 0.; - if (m_fnorm != 0.) - for (Index j = 0; j < n; ++j) - if (m_wa2[m_permutation.indices()[j]] != 0.) - m_gnorm = (std::max)(m_gnorm, abs( m_rfactor.col(j).head(j+1).dot(m_qtf.head(j+1)/m_fnorm) / m_wa2[m_permutation.indices()[j]])); - - /* test for convergence of the gradient norm. */ - if (m_gnorm <= m_gtol) { - m_info = Success; - return LevenbergMarquardtSpace::CosinusTooSmall; - } - - /* rescale if necessary. */ - if (!m_useExternalScaling) - m_diag = m_diag.cwiseMax(m_wa2); - - do { - /* determine the levenberg-marquardt parameter. */ - internal::lmpar2(qrfac, m_diag, m_qtf, m_delta, m_par, m_wa1); - - /* store the direction p and x + p. calculate the norm of p. */ - m_wa1 = -m_wa1; - m_wa2 = x + m_wa1; - pnorm = m_diag.cwiseProduct(m_wa1).stableNorm(); - - /* on the first iteration, adjust the initial step bound. */ - if (m_iter == 1) - m_delta = (std::min)(m_delta,pnorm); - - /* evaluate the function at x + p and calculate its norm. */ - if ( m_functor(m_wa2, m_wa4) < 0) - return LevenbergMarquardtSpace::UserAsked; - ++m_nfev; - fnorm1 = m_wa4.stableNorm(); - - /* compute the scaled actual reduction. */ - actred = -1.; - if (Scalar(.1) * fnorm1 < m_fnorm) - actred = 1. - numext::abs2(fnorm1 / m_fnorm); - - /* compute the scaled predicted reduction and */ - /* the scaled directional derivative. */ - m_wa3 = m_rfactor.template triangularView<Upper>() * (m_permutation.inverse() *m_wa1); - temp1 = numext::abs2(m_wa3.stableNorm() / m_fnorm); - temp2 = numext::abs2(sqrt(m_par) * pnorm / m_fnorm); - prered = temp1 + temp2 / Scalar(.5); - dirder = -(temp1 + temp2); - - /* compute the ratio of the actual to the predicted */ - /* reduction. */ - ratio = 0.; - if (prered != 0.) - ratio = actred / prered; - - /* update the step bound. */ - if (ratio <= Scalar(.25)) { - if (actred >= 0.) - temp = RealScalar(.5); - if (actred < 0.) - temp = RealScalar(.5) * dirder / (dirder + RealScalar(.5) * actred); - if (RealScalar(.1) * fnorm1 >= m_fnorm || temp < RealScalar(.1)) - temp = Scalar(.1); - /* Computing MIN */ - m_delta = temp * (std::min)(m_delta, pnorm / RealScalar(.1)); - m_par /= temp; - } else if (!(m_par != 0. && ratio < RealScalar(.75))) { - m_delta = pnorm / RealScalar(.5); - m_par = RealScalar(.5) * m_par; - } - - /* test for successful iteration. */ - if (ratio >= RealScalar(1e-4)) { - /* successful iteration. update x, m_fvec, and their norms. */ - x = m_wa2; - m_wa2 = m_diag.cwiseProduct(x); - m_fvec = m_wa4; - xnorm = m_wa2.stableNorm(); - m_fnorm = fnorm1; - ++m_iter; - } - - /* tests for convergence. */ - if (abs(actred) <= m_ftol && prered <= m_ftol && Scalar(.5) * ratio <= 1. && m_delta <= m_xtol * xnorm) - { - m_info = Success; - return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall; - } - if (abs(actred) <= m_ftol && prered <= m_ftol && Scalar(.5) * ratio <= 1.) - { - m_info = Success; - return LevenbergMarquardtSpace::RelativeReductionTooSmall; - } - if (m_delta <= m_xtol * xnorm) - { - m_info = Success; - return LevenbergMarquardtSpace::RelativeErrorTooSmall; - } - - /* tests for termination and stringent tolerances. */ - if (m_nfev >= m_maxfev) - { - m_info = NoConvergence; - return LevenbergMarquardtSpace::TooManyFunctionEvaluation; - } - if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.) - { - m_info = Success; - return LevenbergMarquardtSpace::FtolTooSmall; - } - if (m_delta <= NumTraits<Scalar>::epsilon() * xnorm) - { - m_info = Success; - return LevenbergMarquardtSpace::XtolTooSmall; - } - if (m_gnorm <= NumTraits<Scalar>::epsilon()) - { - m_info = Success; - return LevenbergMarquardtSpace::GtolTooSmall; - } - - } while (ratio < Scalar(1e-4)); - - return LevenbergMarquardtSpace::Running; -} - - -} // end namespace Eigen - -#endif // EIGEN_LMONESTEP_H diff --git a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h b/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h deleted file mode 100644 index 9a48365..0000000 --- a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMpar.h +++ /dev/null @@ -1,160 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// This code initially comes from MINPACK whose original authors are: -// Copyright Jorge More - Argonne National Laboratory -// Copyright Burt Garbow - Argonne National Laboratory -// Copyright Ken Hillstrom - Argonne National Laboratory -// -// This Source Code Form is subject to the terms of the Minpack license -// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file. - -#ifndef EIGEN_LMPAR_H -#define EIGEN_LMPAR_H - -namespace Eigen { - -namespace internal { - - template <typename QRSolver, typename VectorType> - void lmpar2( - const QRSolver &qr, - const VectorType &diag, - const VectorType &qtb, - typename VectorType::Scalar m_delta, - typename VectorType::Scalar &par, - VectorType &x) - - { - using std::sqrt; - using std::abs; - typedef typename QRSolver::MatrixType MatrixType; - typedef typename QRSolver::Scalar Scalar; -// typedef typename QRSolver::StorageIndex StorageIndex; - - /* Local variables */ - Index j; - Scalar fp; - Scalar parc, parl; - Index iter; - Scalar temp, paru; - Scalar gnorm; - Scalar dxnorm; - - // Make a copy of the triangular factor. - // This copy is modified during call the qrsolv - MatrixType s; - s = qr.matrixR(); - - /* Function Body */ - const Scalar dwarf = (std::numeric_limits<Scalar>::min)(); - const Index n = qr.matrixR().cols(); - eigen_assert(n==diag.size()); - eigen_assert(n==qtb.size()); - - VectorType wa1, wa2; - - /* compute and store in x the gauss-newton direction. if the */ - /* jacobian is rank-deficient, obtain a least squares solution. */ - - // const Index rank = qr.nonzeroPivots(); // exactly double(0.) - const Index rank = qr.rank(); // use a threshold - wa1 = qtb; - wa1.tail(n-rank).setZero(); - //FIXME There is no solve in place for sparse triangularView - wa1.head(rank) = s.topLeftCorner(rank,rank).template triangularView<Upper>().solve(qtb.head(rank)); - - x = qr.colsPermutation()*wa1; - - /* initialize the iteration counter. */ - /* evaluate the function at the origin, and test */ - /* for acceptance of the gauss-newton direction. */ - iter = 0; - wa2 = diag.cwiseProduct(x); - dxnorm = wa2.blueNorm(); - fp = dxnorm - m_delta; - if (fp <= Scalar(0.1) * m_delta) { - par = 0; - return; - } - - /* if the jacobian is not rank deficient, the newton */ - /* step provides a lower bound, parl, for the zero of */ - /* the function. otherwise set this bound to zero. */ - parl = 0.; - if (rank==n) { - wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2)/dxnorm; - s.topLeftCorner(n,n).transpose().template triangularView<Lower>().solveInPlace(wa1); - temp = wa1.blueNorm(); - parl = fp / m_delta / temp / temp; - } - - /* calculate an upper bound, paru, for the zero of the function. */ - for (j = 0; j < n; ++j) - wa1[j] = s.col(j).head(j+1).dot(qtb.head(j+1)) / diag[qr.colsPermutation().indices()(j)]; - - gnorm = wa1.stableNorm(); - paru = gnorm / m_delta; - if (paru == 0.) - paru = dwarf / (std::min)(m_delta,Scalar(0.1)); - - /* if the input par lies outside of the interval (parl,paru), */ - /* set par to the closer endpoint. */ - par = (std::max)(par,parl); - par = (std::min)(par,paru); - if (par == 0.) - par = gnorm / dxnorm; - - /* beginning of an iteration. */ - while (true) { - ++iter; - - /* evaluate the function at the current value of par. */ - if (par == 0.) - par = (std::max)(dwarf,Scalar(.001) * paru); /* Computing MAX */ - wa1 = sqrt(par)* diag; - - VectorType sdiag(n); - lmqrsolv(s, qr.colsPermutation(), wa1, qtb, x, sdiag); - - wa2 = diag.cwiseProduct(x); - dxnorm = wa2.blueNorm(); - temp = fp; - fp = dxnorm - m_delta; - - /* if the function is small enough, accept the current value */ - /* of par. also test for the exceptional cases where parl */ - /* is zero or the number of iterations has reached 10. */ - if (abs(fp) <= Scalar(0.1) * m_delta || (parl == 0. && fp <= temp && temp < 0.) || iter == 10) - break; - - /* compute the newton correction. */ - wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2/dxnorm); - // we could almost use this here, but the diagonal is outside qr, in sdiag[] - for (j = 0; j < n; ++j) { - wa1[j] /= sdiag[j]; - temp = wa1[j]; - for (Index i = j+1; i < n; ++i) - wa1[i] -= s.coeff(i,j) * temp; - } - temp = wa1.blueNorm(); - parc = fp / m_delta / temp / temp; - - /* depending on the sign of the function, update parl or paru. */ - if (fp > 0.) - parl = (std::max)(parl,par); - if (fp < 0.) - paru = (std::min)(paru,par); - - /* compute an improved estimate for par. */ - par = (std::max)(parl,par+parc); - } - if (iter == 0) - par = 0.; - return; - } -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_LMPAR_H diff --git a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h b/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h deleted file mode 100644 index ae9d793..0000000 --- a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LMqrsolv.h +++ /dev/null @@ -1,188 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> -// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr> -// -// This code initially comes from MINPACK whose original authors are: -// Copyright Jorge More - Argonne National Laboratory -// Copyright Burt Garbow - Argonne National Laboratory -// Copyright Ken Hillstrom - Argonne National Laboratory -// -// This Source Code Form is subject to the terms of the Minpack license -// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file. - -#ifndef EIGEN_LMQRSOLV_H -#define EIGEN_LMQRSOLV_H - -namespace Eigen { - -namespace internal { - -template <typename Scalar,int Rows, int Cols, typename PermIndex> -void lmqrsolv( - Matrix<Scalar,Rows,Cols> &s, - const PermutationMatrix<Dynamic,Dynamic,PermIndex> &iPerm, - const Matrix<Scalar,Dynamic,1> &diag, - const Matrix<Scalar,Dynamic,1> &qtb, - Matrix<Scalar,Dynamic,1> &x, - Matrix<Scalar,Dynamic,1> &sdiag) -{ - /* Local variables */ - Index i, j, k; - Scalar temp; - Index n = s.cols(); - Matrix<Scalar,Dynamic,1> wa(n); - JacobiRotation<Scalar> givens; - - /* Function Body */ - // the following will only change the lower triangular part of s, including - // the diagonal, though the diagonal is restored afterward - - /* copy r and (q transpose)*b to preserve input and initialize s. */ - /* in particular, save the diagonal elements of r in x. */ - x = s.diagonal(); - wa = qtb; - - - s.topLeftCorner(n,n).template triangularView<StrictlyLower>() = s.topLeftCorner(n,n).transpose(); - /* eliminate the diagonal matrix d using a givens rotation. */ - for (j = 0; j < n; ++j) { - - /* prepare the row of d to be eliminated, locating the */ - /* diagonal element using p from the qr factorization. */ - const PermIndex l = iPerm.indices()(j); - if (diag[l] == 0.) - break; - sdiag.tail(n-j).setZero(); - sdiag[j] = diag[l]; - - /* the transformations to eliminate the row of d */ - /* modify only a single element of (q transpose)*b */ - /* beyond the first n, which is initially zero. */ - Scalar qtbpj = 0.; - for (k = j; k < n; ++k) { - /* determine a givens rotation which eliminates the */ - /* appropriate element in the current row of d. */ - givens.makeGivens(-s(k,k), sdiag[k]); - - /* compute the modified diagonal element of r and */ - /* the modified element of ((q transpose)*b,0). */ - s(k,k) = givens.c() * s(k,k) + givens.s() * sdiag[k]; - temp = givens.c() * wa[k] + givens.s() * qtbpj; - qtbpj = -givens.s() * wa[k] + givens.c() * qtbpj; - wa[k] = temp; - - /* accumulate the tranformation in the row of s. */ - for (i = k+1; i<n; ++i) { - temp = givens.c() * s(i,k) + givens.s() * sdiag[i]; - sdiag[i] = -givens.s() * s(i,k) + givens.c() * sdiag[i]; - s(i,k) = temp; - } - } - } - - /* solve the triangular system for z. if the system is */ - /* singular, then obtain a least squares solution. */ - Index nsing; - for(nsing=0; nsing<n && sdiag[nsing]!=0; nsing++) {} - - wa.tail(n-nsing).setZero(); - s.topLeftCorner(nsing, nsing).transpose().template triangularView<Upper>().solveInPlace(wa.head(nsing)); - - // restore - sdiag = s.diagonal(); - s.diagonal() = x; - - /* permute the components of z back to components of x. */ - x = iPerm * wa; -} - -template <typename Scalar, int _Options, typename Index> -void lmqrsolv( - SparseMatrix<Scalar,_Options,Index> &s, - const PermutationMatrix<Dynamic,Dynamic> &iPerm, - const Matrix<Scalar,Dynamic,1> &diag, - const Matrix<Scalar,Dynamic,1> &qtb, - Matrix<Scalar,Dynamic,1> &x, - Matrix<Scalar,Dynamic,1> &sdiag) -{ - /* Local variables */ - typedef SparseMatrix<Scalar,RowMajor,Index> FactorType; - Index i, j, k, l; - Scalar temp; - Index n = s.cols(); - Matrix<Scalar,Dynamic,1> wa(n); - JacobiRotation<Scalar> givens; - - /* Function Body */ - // the following will only change the lower triangular part of s, including - // the diagonal, though the diagonal is restored afterward - - /* copy r and (q transpose)*b to preserve input and initialize R. */ - wa = qtb; - FactorType R(s); - // Eliminate the diagonal matrix d using a givens rotation - for (j = 0; j < n; ++j) - { - // Prepare the row of d to be eliminated, locating the - // diagonal element using p from the qr factorization - l = iPerm.indices()(j); - if (diag(l) == Scalar(0)) - break; - sdiag.tail(n-j).setZero(); - sdiag[j] = diag[l]; - // the transformations to eliminate the row of d - // modify only a single element of (q transpose)*b - // beyond the first n, which is initially zero. - - Scalar qtbpj = 0; - // Browse the nonzero elements of row j of the upper triangular s - for (k = j; k < n; ++k) - { - typename FactorType::InnerIterator itk(R,k); - for (; itk; ++itk){ - if (itk.index() < k) continue; - else break; - } - //At this point, we have the diagonal element R(k,k) - // Determine a givens rotation which eliminates - // the appropriate element in the current row of d - givens.makeGivens(-itk.value(), sdiag(k)); - - // Compute the modified diagonal element of r and - // the modified element of ((q transpose)*b,0). - itk.valueRef() = givens.c() * itk.value() + givens.s() * sdiag(k); - temp = givens.c() * wa(k) + givens.s() * qtbpj; - qtbpj = -givens.s() * wa(k) + givens.c() * qtbpj; - wa(k) = temp; - - // Accumulate the transformation in the remaining k row/column of R - for (++itk; itk; ++itk) - { - i = itk.index(); - temp = givens.c() * itk.value() + givens.s() * sdiag(i); - sdiag(i) = -givens.s() * itk.value() + givens.c() * sdiag(i); - itk.valueRef() = temp; - } - } - } - - // Solve the triangular system for z. If the system is - // singular, then obtain a least squares solution - Index nsing; - for(nsing = 0; nsing<n && sdiag(nsing) !=0; nsing++) {} - - wa.tail(n-nsing).setZero(); -// x = wa; - wa.head(nsing) = R.topLeftCorner(nsing,nsing).template triangularView<Upper>().solve/*InPlace*/(wa.head(nsing)); - - sdiag = R.diagonal(); - // Permute the components of z back to components of x - x = iPerm * wa; -} -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_LMQRSOLV_H diff --git a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h b/eigen/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h deleted file mode 100644 index 9954279..0000000 --- a/eigen/unsupported/Eigen/src/LevenbergMarquardt/LevenbergMarquardt.h +++ /dev/null @@ -1,396 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> -// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr> -// -// The algorithm of this class initially comes from MINPACK whose original authors are: -// Copyright Jorge More - Argonne National Laboratory -// Copyright Burt Garbow - Argonne National Laboratory -// Copyright Ken Hillstrom - Argonne National Laboratory -// -// This Source Code Form is subject to the terms of the Minpack license -// (a BSD-like license) described in the campaigned CopyrightMINPACK.txt file. -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_LEVENBERGMARQUARDT_H -#define EIGEN_LEVENBERGMARQUARDT_H - - -namespace Eigen { -namespace LevenbergMarquardtSpace { - enum Status { - NotStarted = -2, - Running = -1, - ImproperInputParameters = 0, - RelativeReductionTooSmall = 1, - RelativeErrorTooSmall = 2, - RelativeErrorAndReductionTooSmall = 3, - CosinusTooSmall = 4, - TooManyFunctionEvaluation = 5, - FtolTooSmall = 6, - XtolTooSmall = 7, - GtolTooSmall = 8, - UserAsked = 9 - }; -} - -template <typename _Scalar, int NX=Dynamic, int NY=Dynamic> -struct DenseFunctor -{ - typedef _Scalar Scalar; - enum { - InputsAtCompileTime = NX, - ValuesAtCompileTime = NY - }; - typedef Matrix<Scalar,InputsAtCompileTime,1> InputType; - typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType; - typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType; - typedef ColPivHouseholderQR<JacobianType> QRSolver; - const int m_inputs, m_values; - - DenseFunctor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {} - DenseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {} - - int inputs() const { return m_inputs; } - int values() const { return m_values; } - - //int operator()(const InputType &x, ValueType& fvec) { } - // should be defined in derived classes - - //int df(const InputType &x, JacobianType& fjac) { } - // should be defined in derived classes -}; - -template <typename _Scalar, typename _Index> -struct SparseFunctor -{ - typedef _Scalar Scalar; - typedef _Index Index; - typedef Matrix<Scalar,Dynamic,1> InputType; - typedef Matrix<Scalar,Dynamic,1> ValueType; - typedef SparseMatrix<Scalar, ColMajor, Index> JacobianType; - typedef SparseQR<JacobianType, COLAMDOrdering<int> > QRSolver; - enum { - InputsAtCompileTime = Dynamic, - ValuesAtCompileTime = Dynamic - }; - - SparseFunctor(int inputs, int values) : m_inputs(inputs), m_values(values) {} - - int inputs() const { return m_inputs; } - int values() const { return m_values; } - - const int m_inputs, m_values; - //int operator()(const InputType &x, ValueType& fvec) { } - // to be defined in the functor - - //int df(const InputType &x, JacobianType& fjac) { } - // to be defined in the functor if no automatic differentiation - -}; -namespace internal { -template <typename QRSolver, typename VectorType> -void lmpar2(const QRSolver &qr, const VectorType &diag, const VectorType &qtb, - typename VectorType::Scalar m_delta, typename VectorType::Scalar &par, - VectorType &x); - } -/** - * \ingroup NonLinearOptimization_Module - * \brief Performs non linear optimization over a non-linear function, - * using a variant of the Levenberg Marquardt algorithm. - * - * Check wikipedia for more information. - * http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm - */ -template<typename _FunctorType> -class LevenbergMarquardt : internal::no_assignment_operator -{ - public: - typedef _FunctorType FunctorType; - typedef typename FunctorType::QRSolver QRSolver; - typedef typename FunctorType::JacobianType JacobianType; - typedef typename JacobianType::Scalar Scalar; - typedef typename JacobianType::RealScalar RealScalar; - typedef typename QRSolver::StorageIndex PermIndex; - typedef Matrix<Scalar,Dynamic,1> FVectorType; - typedef PermutationMatrix<Dynamic,Dynamic> PermutationType; - public: - LevenbergMarquardt(FunctorType& functor) - : m_functor(functor),m_nfev(0),m_njev(0),m_fnorm(0.0),m_gnorm(0), - m_isInitialized(false),m_info(InvalidInput) - { - resetParameters(); - m_useExternalScaling=false; - } - - LevenbergMarquardtSpace::Status minimize(FVectorType &x); - LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x); - LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x); - LevenbergMarquardtSpace::Status lmder1( - FVectorType &x, - const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) - ); - static LevenbergMarquardtSpace::Status lmdif1( - FunctorType &functor, - FVectorType &x, - Index *nfev, - const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) - ); - - /** Sets the default parameters */ - void resetParameters() - { - using std::sqrt; - - m_factor = 100.; - m_maxfev = 400; - m_ftol = sqrt(NumTraits<RealScalar>::epsilon()); - m_xtol = sqrt(NumTraits<RealScalar>::epsilon()); - m_gtol = 0. ; - m_epsfcn = 0. ; - } - - /** Sets the tolerance for the norm of the solution vector*/ - void setXtol(RealScalar xtol) { m_xtol = xtol; } - - /** Sets the tolerance for the norm of the vector function*/ - void setFtol(RealScalar ftol) { m_ftol = ftol; } - - /** Sets the tolerance for the norm of the gradient of the error vector*/ - void setGtol(RealScalar gtol) { m_gtol = gtol; } - - /** Sets the step bound for the diagonal shift */ - void setFactor(RealScalar factor) { m_factor = factor; } - - /** Sets the error precision */ - void setEpsilon (RealScalar epsfcn) { m_epsfcn = epsfcn; } - - /** Sets the maximum number of function evaluation */ - void setMaxfev(Index maxfev) {m_maxfev = maxfev; } - - /** Use an external Scaling. If set to true, pass a nonzero diagonal to diag() */ - void setExternalScaling(bool value) {m_useExternalScaling = value; } - - /** \returns the tolerance for the norm of the solution vector */ - RealScalar xtol() const {return m_xtol; } - - /** \returns the tolerance for the norm of the vector function */ - RealScalar ftol() const {return m_ftol; } - - /** \returns the tolerance for the norm of the gradient of the error vector */ - RealScalar gtol() const {return m_gtol; } - - /** \returns the step bound for the diagonal shift */ - RealScalar factor() const {return m_factor; } - - /** \returns the error precision */ - RealScalar epsilon() const {return m_epsfcn; } - - /** \returns the maximum number of function evaluation */ - Index maxfev() const {return m_maxfev; } - - /** \returns a reference to the diagonal of the jacobian */ - FVectorType& diag() {return m_diag; } - - /** \returns the number of iterations performed */ - Index iterations() { return m_iter; } - - /** \returns the number of functions evaluation */ - Index nfev() { return m_nfev; } - - /** \returns the number of jacobian evaluation */ - Index njev() { return m_njev; } - - /** \returns the norm of current vector function */ - RealScalar fnorm() {return m_fnorm; } - - /** \returns the norm of the gradient of the error */ - RealScalar gnorm() {return m_gnorm; } - - /** \returns the LevenbergMarquardt parameter */ - RealScalar lm_param(void) { return m_par; } - - /** \returns a reference to the current vector function - */ - FVectorType& fvec() {return m_fvec; } - - /** \returns a reference to the matrix where the current Jacobian matrix is stored - */ - JacobianType& jacobian() {return m_fjac; } - - /** \returns a reference to the triangular matrix R from the QR of the jacobian matrix. - * \sa jacobian() - */ - JacobianType& matrixR() {return m_rfactor; } - - /** the permutation used in the QR factorization - */ - PermutationType permutation() {return m_permutation; } - - /** - * \brief Reports whether the minimization was successful - * \returns \c Success if the minimization was succesful, - * \c NumericalIssue if a numerical problem arises during the - * minimization process, for exemple during the QR factorization - * \c NoConvergence if the minimization did not converge after - * the maximum number of function evaluation allowed - * \c InvalidInput if the input matrix is invalid - */ - ComputationInfo info() const - { - - return m_info; - } - private: - JacobianType m_fjac; - JacobianType m_rfactor; // The triangular matrix R from the QR of the jacobian matrix m_fjac - FunctorType &m_functor; - FVectorType m_fvec, m_qtf, m_diag; - Index n; - Index m; - Index m_nfev; - Index m_njev; - RealScalar m_fnorm; // Norm of the current vector function - RealScalar m_gnorm; //Norm of the gradient of the error - RealScalar m_factor; // - Index m_maxfev; // Maximum number of function evaluation - RealScalar m_ftol; //Tolerance in the norm of the vector function - RealScalar m_xtol; // - RealScalar m_gtol; //tolerance of the norm of the error gradient - RealScalar m_epsfcn; // - Index m_iter; // Number of iterations performed - RealScalar m_delta; - bool m_useExternalScaling; - PermutationType m_permutation; - FVectorType m_wa1, m_wa2, m_wa3, m_wa4; //Temporary vectors - RealScalar m_par; - bool m_isInitialized; // Check whether the minimization step has been called - ComputationInfo m_info; -}; - -template<typename FunctorType> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType>::minimize(FVectorType &x) -{ - LevenbergMarquardtSpace::Status status = minimizeInit(x); - if (status==LevenbergMarquardtSpace::ImproperInputParameters) { - m_isInitialized = true; - return status; - } - do { -// std::cout << " uv " << x.transpose() << "\n"; - status = minimizeOneStep(x); - } while (status==LevenbergMarquardtSpace::Running); - m_isInitialized = true; - return status; -} - -template<typename FunctorType> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType>::minimizeInit(FVectorType &x) -{ - n = x.size(); - m = m_functor.values(); - - m_wa1.resize(n); m_wa2.resize(n); m_wa3.resize(n); - m_wa4.resize(m); - m_fvec.resize(m); - //FIXME Sparse Case : Allocate space for the jacobian - m_fjac.resize(m, n); -// m_fjac.reserve(VectorXi::Constant(n,5)); // FIXME Find a better alternative - if (!m_useExternalScaling) - m_diag.resize(n); - eigen_assert( (!m_useExternalScaling || m_diag.size()==n) && "When m_useExternalScaling is set, the caller must provide a valid 'm_diag'"); - m_qtf.resize(n); - - /* Function Body */ - m_nfev = 0; - m_njev = 0; - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || m_ftol < 0. || m_xtol < 0. || m_gtol < 0. || m_maxfev <= 0 || m_factor <= 0.){ - m_info = InvalidInput; - return LevenbergMarquardtSpace::ImproperInputParameters; - } - - if (m_useExternalScaling) - for (Index j = 0; j < n; ++j) - if (m_diag[j] <= 0.) - { - m_info = InvalidInput; - return LevenbergMarquardtSpace::ImproperInputParameters; - } - - /* evaluate the function at the starting point */ - /* and calculate its norm. */ - m_nfev = 1; - if ( m_functor(x, m_fvec) < 0) - return LevenbergMarquardtSpace::UserAsked; - m_fnorm = m_fvec.stableNorm(); - - /* initialize levenberg-marquardt parameter and iteration counter. */ - m_par = 0.; - m_iter = 1; - - return LevenbergMarquardtSpace::NotStarted; -} - -template<typename FunctorType> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType>::lmder1( - FVectorType &x, - const Scalar tol - ) -{ - n = x.size(); - m = m_functor.values(); - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || tol < 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - resetParameters(); - m_ftol = tol; - m_xtol = tol; - m_maxfev = 100*(n+1); - - return minimize(x); -} - - -template<typename FunctorType> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType>::lmdif1( - FunctorType &functor, - FVectorType &x, - Index *nfev, - const Scalar tol - ) -{ - Index n = x.size(); - Index m = functor.values(); - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || tol < 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - NumericalDiff<FunctorType> numDiff(functor); - // embedded LevenbergMarquardt - LevenbergMarquardt<NumericalDiff<FunctorType> > lm(numDiff); - lm.setFtol(tol); - lm.setXtol(tol); - lm.setMaxfev(200*(n+1)); - - LevenbergMarquardtSpace::Status info = LevenbergMarquardtSpace::Status(lm.minimize(x)); - if (nfev) - * nfev = lm.nfev(); - return info; -} - -} // end namespace Eigen - -#endif // EIGEN_LEVENBERGMARQUARDT_H diff --git a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h b/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h deleted file mode 100644 index e5ebbcf..0000000 --- a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixExponential.h +++ /dev/null @@ -1,442 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009, 2010, 2013 Jitse Niesen <jitse@maths.leeds.ac.uk> -// Copyright (C) 2011, 2013 Chen-Pang He <jdh8@ms63.hinet.net> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_MATRIX_EXPONENTIAL -#define EIGEN_MATRIX_EXPONENTIAL - -#include "StemFunction.h" - -namespace Eigen { -namespace internal { - -/** \brief Scaling operator. - * - * This struct is used by CwiseUnaryOp to scale a matrix by \f$ 2^{-s} \f$. - */ -template <typename RealScalar> -struct MatrixExponentialScalingOp -{ - /** \brief Constructor. - * - * \param[in] squarings The integer \f$ s \f$ in this document. - */ - MatrixExponentialScalingOp(int squarings) : m_squarings(squarings) { } - - - /** \brief Scale a matrix coefficient. - * - * \param[in,out] x The scalar to be scaled, becoming \f$ 2^{-s} x \f$. - */ - inline const RealScalar operator() (const RealScalar& x) const - { - using std::ldexp; - return ldexp(x, -m_squarings); - } - - typedef std::complex<RealScalar> ComplexScalar; - - /** \brief Scale a matrix coefficient. - * - * \param[in,out] x The scalar to be scaled, becoming \f$ 2^{-s} x \f$. - */ - inline const ComplexScalar operator() (const ComplexScalar& x) const - { - using std::ldexp; - return ComplexScalar(ldexp(x.real(), -m_squarings), ldexp(x.imag(), -m_squarings)); - } - - private: - int m_squarings; -}; - -/** \brief Compute the (3,3)-Padé approximant to the exponential. - * - * After exit, \f$ (V+U)(V-U)^{-1} \f$ is the Padé - * approximant of \f$ \exp(A) \f$ around \f$ A = 0 \f$. - */ -template <typename MatA, typename MatU, typename MatV> -void matrix_exp_pade3(const MatA& A, MatU& U, MatV& V) -{ - typedef typename MatA::PlainObject MatrixType; - typedef typename NumTraits<typename traits<MatA>::Scalar>::Real RealScalar; - const RealScalar b[] = {120.L, 60.L, 12.L, 1.L}; - const MatrixType A2 = A * A; - const MatrixType tmp = b[3] * A2 + b[1] * MatrixType::Identity(A.rows(), A.cols()); - U.noalias() = A * tmp; - V = b[2] * A2 + b[0] * MatrixType::Identity(A.rows(), A.cols()); -} - -/** \brief Compute the (5,5)-Padé approximant to the exponential. - * - * After exit, \f$ (V+U)(V-U)^{-1} \f$ is the Padé - * approximant of \f$ \exp(A) \f$ around \f$ A = 0 \f$. - */ -template <typename MatA, typename MatU, typename MatV> -void matrix_exp_pade5(const MatA& A, MatU& U, MatV& V) -{ - typedef typename MatA::PlainObject MatrixType; - typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar; - const RealScalar b[] = {30240.L, 15120.L, 3360.L, 420.L, 30.L, 1.L}; - const MatrixType A2 = A * A; - const MatrixType A4 = A2 * A2; - const MatrixType tmp = b[5] * A4 + b[3] * A2 + b[1] * MatrixType::Identity(A.rows(), A.cols()); - U.noalias() = A * tmp; - V = b[4] * A4 + b[2] * A2 + b[0] * MatrixType::Identity(A.rows(), A.cols()); -} - -/** \brief Compute the (7,7)-Padé approximant to the exponential. - * - * After exit, \f$ (V+U)(V-U)^{-1} \f$ is the Padé - * approximant of \f$ \exp(A) \f$ around \f$ A = 0 \f$. - */ -template <typename MatA, typename MatU, typename MatV> -void matrix_exp_pade7(const MatA& A, MatU& U, MatV& V) -{ - typedef typename MatA::PlainObject MatrixType; - typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar; - const RealScalar b[] = {17297280.L, 8648640.L, 1995840.L, 277200.L, 25200.L, 1512.L, 56.L, 1.L}; - const MatrixType A2 = A * A; - const MatrixType A4 = A2 * A2; - const MatrixType A6 = A4 * A2; - const MatrixType tmp = b[7] * A6 + b[5] * A4 + b[3] * A2 - + b[1] * MatrixType::Identity(A.rows(), A.cols()); - U.noalias() = A * tmp; - V = b[6] * A6 + b[4] * A4 + b[2] * A2 + b[0] * MatrixType::Identity(A.rows(), A.cols()); - -} - -/** \brief Compute the (9,9)-Padé approximant to the exponential. - * - * After exit, \f$ (V+U)(V-U)^{-1} \f$ is the Padé - * approximant of \f$ \exp(A) \f$ around \f$ A = 0 \f$. - */ -template <typename MatA, typename MatU, typename MatV> -void matrix_exp_pade9(const MatA& A, MatU& U, MatV& V) -{ - typedef typename MatA::PlainObject MatrixType; - typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar; - const RealScalar b[] = {17643225600.L, 8821612800.L, 2075673600.L, 302702400.L, 30270240.L, - 2162160.L, 110880.L, 3960.L, 90.L, 1.L}; - const MatrixType A2 = A * A; - const MatrixType A4 = A2 * A2; - const MatrixType A6 = A4 * A2; - const MatrixType A8 = A6 * A2; - const MatrixType tmp = b[9] * A8 + b[7] * A6 + b[5] * A4 + b[3] * A2 - + b[1] * MatrixType::Identity(A.rows(), A.cols()); - U.noalias() = A * tmp; - V = b[8] * A8 + b[6] * A6 + b[4] * A4 + b[2] * A2 + b[0] * MatrixType::Identity(A.rows(), A.cols()); -} - -/** \brief Compute the (13,13)-Padé approximant to the exponential. - * - * After exit, \f$ (V+U)(V-U)^{-1} \f$ is the Padé - * approximant of \f$ \exp(A) \f$ around \f$ A = 0 \f$. - */ -template <typename MatA, typename MatU, typename MatV> -void matrix_exp_pade13(const MatA& A, MatU& U, MatV& V) -{ - typedef typename MatA::PlainObject MatrixType; - typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar; - const RealScalar b[] = {64764752532480000.L, 32382376266240000.L, 7771770303897600.L, - 1187353796428800.L, 129060195264000.L, 10559470521600.L, 670442572800.L, - 33522128640.L, 1323241920.L, 40840800.L, 960960.L, 16380.L, 182.L, 1.L}; - const MatrixType A2 = A * A; - const MatrixType A4 = A2 * A2; - const MatrixType A6 = A4 * A2; - V = b[13] * A6 + b[11] * A4 + b[9] * A2; // used for temporary storage - MatrixType tmp = A6 * V; - tmp += b[7] * A6 + b[5] * A4 + b[3] * A2 + b[1] * MatrixType::Identity(A.rows(), A.cols()); - U.noalias() = A * tmp; - tmp = b[12] * A6 + b[10] * A4 + b[8] * A2; - V.noalias() = A6 * tmp; - V += b[6] * A6 + b[4] * A4 + b[2] * A2 + b[0] * MatrixType::Identity(A.rows(), A.cols()); -} - -/** \brief Compute the (17,17)-Padé approximant to the exponential. - * - * After exit, \f$ (V+U)(V-U)^{-1} \f$ is the Padé - * approximant of \f$ \exp(A) \f$ around \f$ A = 0 \f$. - * - * This function activates only if your long double is double-double or quadruple. - */ -#if LDBL_MANT_DIG > 64 -template <typename MatA, typename MatU, typename MatV> -void matrix_exp_pade17(const MatA& A, MatU& U, MatV& V) -{ - typedef typename MatA::PlainObject MatrixType; - typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar; - const RealScalar b[] = {830034394580628357120000.L, 415017197290314178560000.L, - 100610229646136770560000.L, 15720348382208870400000.L, - 1774878043152614400000.L, 153822763739893248000.L, 10608466464820224000.L, - 595373117923584000.L, 27563570274240000.L, 1060137318240000.L, - 33924394183680.L, 899510451840.L, 19554575040.L, 341863200.L, 4651200.L, - 46512.L, 306.L, 1.L}; - const MatrixType A2 = A * A; - const MatrixType A4 = A2 * A2; - const MatrixType A6 = A4 * A2; - const MatrixType A8 = A4 * A4; - V = b[17] * A8 + b[15] * A6 + b[13] * A4 + b[11] * A2; // used for temporary storage - MatrixType tmp = A8 * V; - tmp += b[9] * A8 + b[7] * A6 + b[5] * A4 + b[3] * A2 - + b[1] * MatrixType::Identity(A.rows(), A.cols()); - U.noalias() = A * tmp; - tmp = b[16] * A8 + b[14] * A6 + b[12] * A4 + b[10] * A2; - V.noalias() = tmp * A8; - V += b[8] * A8 + b[6] * A6 + b[4] * A4 + b[2] * A2 - + b[0] * MatrixType::Identity(A.rows(), A.cols()); -} -#endif - -template <typename MatrixType, typename RealScalar = typename NumTraits<typename traits<MatrixType>::Scalar>::Real> -struct matrix_exp_computeUV -{ - /** \brief Compute Padé approximant to the exponential. - * - * Computes \c U, \c V and \c squarings such that \f$ (V+U)(V-U)^{-1} \f$ is a Padé - * approximant of \f$ \exp(2^{-\mbox{squarings}}M) \f$ around \f$ M = 0 \f$, where \f$ M \f$ - * denotes the matrix \c arg. The degree of the Padé approximant and the value of squarings - * are chosen such that the approximation error is no more than the round-off error. - */ - static void run(const MatrixType& arg, MatrixType& U, MatrixType& V, int& squarings); -}; - -template <typename MatrixType> -struct matrix_exp_computeUV<MatrixType, float> -{ - template <typename ArgType> - static void run(const ArgType& arg, MatrixType& U, MatrixType& V, int& squarings) - { - using std::frexp; - using std::pow; - const float l1norm = arg.cwiseAbs().colwise().sum().maxCoeff(); - squarings = 0; - if (l1norm < 4.258730016922831e-001f) { - matrix_exp_pade3(arg, U, V); - } else if (l1norm < 1.880152677804762e+000f) { - matrix_exp_pade5(arg, U, V); - } else { - const float maxnorm = 3.925724783138660f; - frexp(l1norm / maxnorm, &squarings); - if (squarings < 0) squarings = 0; - MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<float>(squarings)); - matrix_exp_pade7(A, U, V); - } - } -}; - -template <typename MatrixType> -struct matrix_exp_computeUV<MatrixType, double> -{ - typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar; - template <typename ArgType> - static void run(const ArgType& arg, MatrixType& U, MatrixType& V, int& squarings) - { - using std::frexp; - using std::pow; - const RealScalar l1norm = arg.cwiseAbs().colwise().sum().maxCoeff(); - squarings = 0; - if (l1norm < 1.495585217958292e-002) { - matrix_exp_pade3(arg, U, V); - } else if (l1norm < 2.539398330063230e-001) { - matrix_exp_pade5(arg, U, V); - } else if (l1norm < 9.504178996162932e-001) { - matrix_exp_pade7(arg, U, V); - } else if (l1norm < 2.097847961257068e+000) { - matrix_exp_pade9(arg, U, V); - } else { - const RealScalar maxnorm = 5.371920351148152; - frexp(l1norm / maxnorm, &squarings); - if (squarings < 0) squarings = 0; - MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<RealScalar>(squarings)); - matrix_exp_pade13(A, U, V); - } - } -}; - -template <typename MatrixType> -struct matrix_exp_computeUV<MatrixType, long double> -{ - template <typename ArgType> - static void run(const ArgType& arg, MatrixType& U, MatrixType& V, int& squarings) - { -#if LDBL_MANT_DIG == 53 // double precision - matrix_exp_computeUV<MatrixType, double>::run(arg, U, V, squarings); - -#else - - using std::frexp; - using std::pow; - const long double l1norm = arg.cwiseAbs().colwise().sum().maxCoeff(); - squarings = 0; - -#if LDBL_MANT_DIG <= 64 // extended precision - - if (l1norm < 4.1968497232266989671e-003L) { - matrix_exp_pade3(arg, U, V); - } else if (l1norm < 1.1848116734693823091e-001L) { - matrix_exp_pade5(arg, U, V); - } else if (l1norm < 5.5170388480686700274e-001L) { - matrix_exp_pade7(arg, U, V); - } else if (l1norm < 1.3759868875587845383e+000L) { - matrix_exp_pade9(arg, U, V); - } else { - const long double maxnorm = 4.0246098906697353063L; - frexp(l1norm / maxnorm, &squarings); - if (squarings < 0) squarings = 0; - MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings)); - matrix_exp_pade13(A, U, V); - } - -#elif LDBL_MANT_DIG <= 106 // double-double - - if (l1norm < 3.2787892205607026992947488108213e-005L) { - matrix_exp_pade3(arg, U, V); - } else if (l1norm < 6.4467025060072760084130906076332e-003L) { - matrix_exp_pade5(arg, U, V); - } else if (l1norm < 6.8988028496595374751374122881143e-002L) { - matrix_exp_pade7(arg, U, V); - } else if (l1norm < 2.7339737518502231741495857201670e-001L) { - matrix_exp_pade9(arg, U, V); - } else if (l1norm < 1.3203382096514474905666448850278e+000L) { - matrix_exp_pade13(arg, U, V); - } else { - const long double maxnorm = 3.2579440895405400856599663723517L; - frexp(l1norm / maxnorm, &squarings); - if (squarings < 0) squarings = 0; - MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings)); - matrix_exp_pade17(A, U, V); - } - -#elif LDBL_MANT_DIG <= 112 // quadruple precison - - if (l1norm < 1.639394610288918690547467954466970e-005L) { - matrix_exp_pade3(arg, U, V); - } else if (l1norm < 4.253237712165275566025884344433009e-003L) { - matrix_exp_pade5(arg, U, V); - } else if (l1norm < 5.125804063165764409885122032933142e-002L) { - matrix_exp_pade7(arg, U, V); - } else if (l1norm < 2.170000765161155195453205651889853e-001L) { - matrix_exp_pade9(arg, U, V); - } else if (l1norm < 1.125358383453143065081397882891878e+000L) { - matrix_exp_pade13(arg, U, V); - } else { - const long double maxnorm = 2.884233277829519311757165057717815L; - frexp(l1norm / maxnorm, &squarings); - if (squarings < 0) squarings = 0; - MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<long double>(squarings)); - matrix_exp_pade17(A, U, V); - } - -#else - - // this case should be handled in compute() - eigen_assert(false && "Bug in MatrixExponential"); - -#endif -#endif // LDBL_MANT_DIG - } -}; - -template<typename T> struct is_exp_known_type : false_type {}; -template<> struct is_exp_known_type<float> : true_type {}; -template<> struct is_exp_known_type<double> : true_type {}; -#if LDBL_MANT_DIG <= 112 -template<> struct is_exp_known_type<long double> : true_type {}; -#endif - -template <typename ArgType, typename ResultType> -void matrix_exp_compute(const ArgType& arg, ResultType &result, true_type) // natively supported scalar type -{ - typedef typename ArgType::PlainObject MatrixType; - MatrixType U, V; - int squarings; - matrix_exp_computeUV<MatrixType>::run(arg, U, V, squarings); // Pade approximant is (U+V) / (-U+V) - MatrixType numer = U + V; - MatrixType denom = -U + V; - result = denom.partialPivLu().solve(numer); - for (int i=0; i<squarings; i++) - result *= result; // undo scaling by repeated squaring -} - - -/* Computes the matrix exponential - * - * \param arg argument of matrix exponential (should be plain object) - * \param result variable in which result will be stored - */ -template <typename ArgType, typename ResultType> -void matrix_exp_compute(const ArgType& arg, ResultType &result, false_type) // default -{ - typedef typename ArgType::PlainObject MatrixType; - typedef typename traits<MatrixType>::Scalar Scalar; - typedef typename NumTraits<Scalar>::Real RealScalar; - typedef typename std::complex<RealScalar> ComplexScalar; - result = arg.matrixFunction(internal::stem_function_exp<ComplexScalar>); -} - -} // end namespace Eigen::internal - -/** \ingroup MatrixFunctions_Module - * - * \brief Proxy for the matrix exponential of some matrix (expression). - * - * \tparam Derived Type of the argument to the matrix exponential. - * - * This class holds the argument to the matrix exponential until it is assigned or evaluated for - * some other reason (so the argument should not be changed in the meantime). It is the return type - * of MatrixBase::exp() and most of the time this is the only way it is used. - */ -template<typename Derived> struct MatrixExponentialReturnValue -: public ReturnByValue<MatrixExponentialReturnValue<Derived> > -{ - typedef typename Derived::Index Index; - public: - /** \brief Constructor. - * - * \param src %Matrix (expression) forming the argument of the matrix exponential. - */ - MatrixExponentialReturnValue(const Derived& src) : m_src(src) { } - - /** \brief Compute the matrix exponential. - * - * \param result the matrix exponential of \p src in the constructor. - */ - template <typename ResultType> - inline void evalTo(ResultType& result) const - { - const typename internal::nested_eval<Derived, 10>::type tmp(m_src); - internal::matrix_exp_compute(tmp, result, internal::is_exp_known_type<typename Derived::Scalar>()); - } - - Index rows() const { return m_src.rows(); } - Index cols() const { return m_src.cols(); } - - protected: - const typename internal::ref_selector<Derived>::type m_src; -}; - -namespace internal { -template<typename Derived> -struct traits<MatrixExponentialReturnValue<Derived> > -{ - typedef typename Derived::PlainObject ReturnType; -}; -} - -template <typename Derived> -const MatrixExponentialReturnValue<Derived> MatrixBase<Derived>::exp() const -{ - eigen_assert(rows() == cols()); - return MatrixExponentialReturnValue<Derived>(derived()); -} - -} // end namespace Eigen - -#endif // EIGEN_MATRIX_EXPONENTIAL diff --git a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h b/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h deleted file mode 100644 index 3df8239..0000000 --- a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h +++ /dev/null @@ -1,580 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009-2011, 2013 Jitse Niesen <jitse@maths.leeds.ac.uk> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_MATRIX_FUNCTION_H -#define EIGEN_MATRIX_FUNCTION_H - -#include "StemFunction.h" - - -namespace Eigen { - -namespace internal { - -/** \brief Maximum distance allowed between eigenvalues to be considered "close". */ -static const float matrix_function_separation = 0.1f; - -/** \ingroup MatrixFunctions_Module - * \class MatrixFunctionAtomic - * \brief Helper class for computing matrix functions of atomic matrices. - * - * Here, an atomic matrix is a triangular matrix whose diagonal entries are close to each other. - */ -template <typename MatrixType> -class MatrixFunctionAtomic -{ - public: - - typedef typename MatrixType::Scalar Scalar; - typedef typename stem_function<Scalar>::type StemFunction; - - /** \brief Constructor - * \param[in] f matrix function to compute. - */ - MatrixFunctionAtomic(StemFunction f) : m_f(f) { } - - /** \brief Compute matrix function of atomic matrix - * \param[in] A argument of matrix function, should be upper triangular and atomic - * \returns f(A), the matrix function evaluated at the given matrix - */ - MatrixType compute(const MatrixType& A); - - private: - StemFunction* m_f; -}; - -template <typename MatrixType> -typename NumTraits<typename MatrixType::Scalar>::Real matrix_function_compute_mu(const MatrixType& A) -{ - typedef typename plain_col_type<MatrixType>::type VectorType; - typename MatrixType::Index rows = A.rows(); - const MatrixType N = MatrixType::Identity(rows, rows) - A; - VectorType e = VectorType::Ones(rows); - N.template triangularView<Upper>().solveInPlace(e); - return e.cwiseAbs().maxCoeff(); -} - -template <typename MatrixType> -MatrixType MatrixFunctionAtomic<MatrixType>::compute(const MatrixType& A) -{ - // TODO: Use that A is upper triangular - typedef typename NumTraits<Scalar>::Real RealScalar; - typedef typename MatrixType::Index Index; - Index rows = A.rows(); - Scalar avgEival = A.trace() / Scalar(RealScalar(rows)); - MatrixType Ashifted = A - avgEival * MatrixType::Identity(rows, rows); - RealScalar mu = matrix_function_compute_mu(Ashifted); - MatrixType F = m_f(avgEival, 0) * MatrixType::Identity(rows, rows); - MatrixType P = Ashifted; - MatrixType Fincr; - for (Index s = 1; s < 1.1 * rows + 10; s++) { // upper limit is fairly arbitrary - Fincr = m_f(avgEival, static_cast<int>(s)) * P; - F += Fincr; - P = Scalar(RealScalar(1.0/(s + 1))) * P * Ashifted; - - // test whether Taylor series converged - const RealScalar F_norm = F.cwiseAbs().rowwise().sum().maxCoeff(); - const RealScalar Fincr_norm = Fincr.cwiseAbs().rowwise().sum().maxCoeff(); - if (Fincr_norm < NumTraits<Scalar>::epsilon() * F_norm) { - RealScalar delta = 0; - RealScalar rfactorial = 1; - for (Index r = 0; r < rows; r++) { - RealScalar mx = 0; - for (Index i = 0; i < rows; i++) - mx = (std::max)(mx, std::abs(m_f(Ashifted(i, i) + avgEival, static_cast<int>(s+r)))); - if (r != 0) - rfactorial *= RealScalar(r); - delta = (std::max)(delta, mx / rfactorial); - } - const RealScalar P_norm = P.cwiseAbs().rowwise().sum().maxCoeff(); - if (mu * delta * P_norm < NumTraits<Scalar>::epsilon() * F_norm) // series converged - break; - } - } - return F; -} - -/** \brief Find cluster in \p clusters containing some value - * \param[in] key Value to find - * \returns Iterator to cluster containing \p key, or \c clusters.end() if no cluster in \p m_clusters - * contains \p key. - */ -template <typename Index, typename ListOfClusters> -typename ListOfClusters::iterator matrix_function_find_cluster(Index key, ListOfClusters& clusters) -{ - typename std::list<Index>::iterator j; - for (typename ListOfClusters::iterator i = clusters.begin(); i != clusters.end(); ++i) { - j = std::find(i->begin(), i->end(), key); - if (j != i->end()) - return i; - } - return clusters.end(); -} - -/** \brief Partition eigenvalues in clusters of ei'vals close to each other - * - * \param[in] eivals Eigenvalues - * \param[out] clusters Resulting partition of eigenvalues - * - * The partition satisfies the following two properties: - * # Any eigenvalue in a certain cluster is at most matrix_function_separation() away from another eigenvalue - * in the same cluster. - * # The distance between two eigenvalues in different clusters is more than matrix_function_separation(). - * The implementation follows Algorithm 4.1 in the paper of Davies and Higham. - */ -template <typename EivalsType, typename Cluster> -void matrix_function_partition_eigenvalues(const EivalsType& eivals, std::list<Cluster>& clusters) -{ - typedef typename EivalsType::Index Index; - typedef typename EivalsType::RealScalar RealScalar; - for (Index i=0; i<eivals.rows(); ++i) { - // Find cluster containing i-th ei'val, adding a new cluster if necessary - typename std::list<Cluster>::iterator qi = matrix_function_find_cluster(i, clusters); - if (qi == clusters.end()) { - Cluster l; - l.push_back(i); - clusters.push_back(l); - qi = clusters.end(); - --qi; - } - - // Look for other element to add to the set - for (Index j=i+1; j<eivals.rows(); ++j) { - if (abs(eivals(j) - eivals(i)) <= RealScalar(matrix_function_separation) - && std::find(qi->begin(), qi->end(), j) == qi->end()) { - typename std::list<Cluster>::iterator qj = matrix_function_find_cluster(j, clusters); - if (qj == clusters.end()) { - qi->push_back(j); - } else { - qi->insert(qi->end(), qj->begin(), qj->end()); - clusters.erase(qj); - } - } - } - } -} - -/** \brief Compute size of each cluster given a partitioning */ -template <typename ListOfClusters, typename Index> -void matrix_function_compute_cluster_size(const ListOfClusters& clusters, Matrix<Index, Dynamic, 1>& clusterSize) -{ - const Index numClusters = static_cast<Index>(clusters.size()); - clusterSize.setZero(numClusters); - Index clusterIndex = 0; - for (typename ListOfClusters::const_iterator cluster = clusters.begin(); cluster != clusters.end(); ++cluster) { - clusterSize[clusterIndex] = cluster->size(); - ++clusterIndex; - } -} - -/** \brief Compute start of each block using clusterSize */ -template <typename VectorType> -void matrix_function_compute_block_start(const VectorType& clusterSize, VectorType& blockStart) -{ - blockStart.resize(clusterSize.rows()); - blockStart(0) = 0; - for (typename VectorType::Index i = 1; i < clusterSize.rows(); i++) { - blockStart(i) = blockStart(i-1) + clusterSize(i-1); - } -} - -/** \brief Compute mapping of eigenvalue indices to cluster indices */ -template <typename EivalsType, typename ListOfClusters, typename VectorType> -void matrix_function_compute_map(const EivalsType& eivals, const ListOfClusters& clusters, VectorType& eivalToCluster) -{ - typedef typename EivalsType::Index Index; - eivalToCluster.resize(eivals.rows()); - Index clusterIndex = 0; - for (typename ListOfClusters::const_iterator cluster = clusters.begin(); cluster != clusters.end(); ++cluster) { - for (Index i = 0; i < eivals.rows(); ++i) { - if (std::find(cluster->begin(), cluster->end(), i) != cluster->end()) { - eivalToCluster[i] = clusterIndex; - } - } - ++clusterIndex; - } -} - -/** \brief Compute permutation which groups ei'vals in same cluster together */ -template <typename DynVectorType, typename VectorType> -void matrix_function_compute_permutation(const DynVectorType& blockStart, const DynVectorType& eivalToCluster, VectorType& permutation) -{ - typedef typename VectorType::Index Index; - DynVectorType indexNextEntry = blockStart; - permutation.resize(eivalToCluster.rows()); - for (Index i = 0; i < eivalToCluster.rows(); i++) { - Index cluster = eivalToCluster[i]; - permutation[i] = indexNextEntry[cluster]; - ++indexNextEntry[cluster]; - } -} - -/** \brief Permute Schur decomposition in U and T according to permutation */ -template <typename VectorType, typename MatrixType> -void matrix_function_permute_schur(VectorType& permutation, MatrixType& U, MatrixType& T) -{ - typedef typename VectorType::Index Index; - for (Index i = 0; i < permutation.rows() - 1; i++) { - Index j; - for (j = i; j < permutation.rows(); j++) { - if (permutation(j) == i) break; - } - eigen_assert(permutation(j) == i); - for (Index k = j-1; k >= i; k--) { - JacobiRotation<typename MatrixType::Scalar> rotation; - rotation.makeGivens(T(k, k+1), T(k+1, k+1) - T(k, k)); - T.applyOnTheLeft(k, k+1, rotation.adjoint()); - T.applyOnTheRight(k, k+1, rotation); - U.applyOnTheRight(k, k+1, rotation); - std::swap(permutation.coeffRef(k), permutation.coeffRef(k+1)); - } - } -} - -/** \brief Compute block diagonal part of matrix function. - * - * This routine computes the matrix function applied to the block diagonal part of \p T (which should be - * upper triangular), with the blocking given by \p blockStart and \p clusterSize. The matrix function of - * each diagonal block is computed by \p atomic. The off-diagonal parts of \p fT are set to zero. - */ -template <typename MatrixType, typename AtomicType, typename VectorType> -void matrix_function_compute_block_atomic(const MatrixType& T, AtomicType& atomic, const VectorType& blockStart, const VectorType& clusterSize, MatrixType& fT) -{ - fT.setZero(T.rows(), T.cols()); - for (typename VectorType::Index i = 0; i < clusterSize.rows(); ++i) { - fT.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i)) - = atomic.compute(T.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i))); - } -} - -/** \brief Solve a triangular Sylvester equation AX + XB = C - * - * \param[in] A the matrix A; should be square and upper triangular - * \param[in] B the matrix B; should be square and upper triangular - * \param[in] C the matrix C; should have correct size. - * - * \returns the solution X. - * - * If A is m-by-m and B is n-by-n, then both C and X are m-by-n. The (i,j)-th component of the Sylvester - * equation is - * \f[ - * \sum_{k=i}^m A_{ik} X_{kj} + \sum_{k=1}^j X_{ik} B_{kj} = C_{ij}. - * \f] - * This can be re-arranged to yield: - * \f[ - * X_{ij} = \frac{1}{A_{ii} + B_{jj}} \Bigl( C_{ij} - * - \sum_{k=i+1}^m A_{ik} X_{kj} - \sum_{k=1}^{j-1} X_{ik} B_{kj} \Bigr). - * \f] - * It is assumed that A and B are such that the numerator is never zero (otherwise the Sylvester equation - * does not have a unique solution). In that case, these equations can be evaluated in the order - * \f$ i=m,\ldots,1 \f$ and \f$ j=1,\ldots,n \f$. - */ -template <typename MatrixType> -MatrixType matrix_function_solve_triangular_sylvester(const MatrixType& A, const MatrixType& B, const MatrixType& C) -{ - eigen_assert(A.rows() == A.cols()); - eigen_assert(A.isUpperTriangular()); - eigen_assert(B.rows() == B.cols()); - eigen_assert(B.isUpperTriangular()); - eigen_assert(C.rows() == A.rows()); - eigen_assert(C.cols() == B.rows()); - - typedef typename MatrixType::Index Index; - typedef typename MatrixType::Scalar Scalar; - - Index m = A.rows(); - Index n = B.rows(); - MatrixType X(m, n); - - for (Index i = m - 1; i >= 0; --i) { - for (Index j = 0; j < n; ++j) { - - // Compute AX = \sum_{k=i+1}^m A_{ik} X_{kj} - Scalar AX; - if (i == m - 1) { - AX = 0; - } else { - Matrix<Scalar,1,1> AXmatrix = A.row(i).tail(m-1-i) * X.col(j).tail(m-1-i); - AX = AXmatrix(0,0); - } - - // Compute XB = \sum_{k=1}^{j-1} X_{ik} B_{kj} - Scalar XB; - if (j == 0) { - XB = 0; - } else { - Matrix<Scalar,1,1> XBmatrix = X.row(i).head(j) * B.col(j).head(j); - XB = XBmatrix(0,0); - } - - X(i,j) = (C(i,j) - AX - XB) / (A(i,i) + B(j,j)); - } - } - return X; -} - -/** \brief Compute part of matrix function above block diagonal. - * - * This routine completes the computation of \p fT, denoting a matrix function applied to the triangular - * matrix \p T. It assumes that the block diagonal part of \p fT has already been computed. The part below - * the diagonal is zero, because \p T is upper triangular. - */ -template <typename MatrixType, typename VectorType> -void matrix_function_compute_above_diagonal(const MatrixType& T, const VectorType& blockStart, const VectorType& clusterSize, MatrixType& fT) -{ - typedef internal::traits<MatrixType> Traits; - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::Index Index; - static const int RowsAtCompileTime = Traits::RowsAtCompileTime; - static const int ColsAtCompileTime = Traits::ColsAtCompileTime; - static const int Options = MatrixType::Options; - typedef Matrix<Scalar, Dynamic, Dynamic, Options, RowsAtCompileTime, ColsAtCompileTime> DynMatrixType; - - for (Index k = 1; k < clusterSize.rows(); k++) { - for (Index i = 0; i < clusterSize.rows() - k; i++) { - // compute (i, i+k) block - DynMatrixType A = T.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i)); - DynMatrixType B = -T.block(blockStart(i+k), blockStart(i+k), clusterSize(i+k), clusterSize(i+k)); - DynMatrixType C = fT.block(blockStart(i), blockStart(i), clusterSize(i), clusterSize(i)) - * T.block(blockStart(i), blockStart(i+k), clusterSize(i), clusterSize(i+k)); - C -= T.block(blockStart(i), blockStart(i+k), clusterSize(i), clusterSize(i+k)) - * fT.block(blockStart(i+k), blockStart(i+k), clusterSize(i+k), clusterSize(i+k)); - for (Index m = i + 1; m < i + k; m++) { - C += fT.block(blockStart(i), blockStart(m), clusterSize(i), clusterSize(m)) - * T.block(blockStart(m), blockStart(i+k), clusterSize(m), clusterSize(i+k)); - C -= T.block(blockStart(i), blockStart(m), clusterSize(i), clusterSize(m)) - * fT.block(blockStart(m), blockStart(i+k), clusterSize(m), clusterSize(i+k)); - } - fT.block(blockStart(i), blockStart(i+k), clusterSize(i), clusterSize(i+k)) - = matrix_function_solve_triangular_sylvester(A, B, C); - } - } -} - -/** \ingroup MatrixFunctions_Module - * \brief Class for computing matrix functions. - * \tparam MatrixType type of the argument of the matrix function, - * expected to be an instantiation of the Matrix class template. - * \tparam AtomicType type for computing matrix function of atomic blocks. - * \tparam IsComplex used internally to select correct specialization. - * - * This class implements the Schur-Parlett algorithm for computing matrix functions. The spectrum of the - * matrix is divided in clustered of eigenvalues that lies close together. This class delegates the - * computation of the matrix function on every block corresponding to these clusters to an object of type - * \p AtomicType and uses these results to compute the matrix function of the whole matrix. The class - * \p AtomicType should have a \p compute() member function for computing the matrix function of a block. - * - * \sa class MatrixFunctionAtomic, class MatrixLogarithmAtomic - */ -template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex> -struct matrix_function_compute -{ - /** \brief Compute the matrix function. - * - * \param[in] A argument of matrix function, should be a square matrix. - * \param[in] atomic class for computing matrix function of atomic blocks. - * \param[out] result the function \p f applied to \p A, as - * specified in the constructor. - * - * See MatrixBase::matrixFunction() for details on how this computation - * is implemented. - */ - template <typename AtomicType, typename ResultType> - static void run(const MatrixType& A, AtomicType& atomic, ResultType &result); -}; - -/** \internal \ingroup MatrixFunctions_Module - * \brief Partial specialization of MatrixFunction for real matrices - * - * This converts the real matrix to a complex matrix, compute the matrix function of that matrix, and then - * converts the result back to a real matrix. - */ -template <typename MatrixType> -struct matrix_function_compute<MatrixType, 0> -{ - template <typename MatA, typename AtomicType, typename ResultType> - static void run(const MatA& A, AtomicType& atomic, ResultType &result) - { - typedef internal::traits<MatrixType> Traits; - typedef typename Traits::Scalar Scalar; - static const int Rows = Traits::RowsAtCompileTime, Cols = Traits::ColsAtCompileTime; - static const int MaxRows = Traits::MaxRowsAtCompileTime, MaxCols = Traits::MaxColsAtCompileTime; - - typedef std::complex<Scalar> ComplexScalar; - typedef Matrix<ComplexScalar, Rows, Cols, 0, MaxRows, MaxCols> ComplexMatrix; - - ComplexMatrix CA = A.template cast<ComplexScalar>(); - ComplexMatrix Cresult; - matrix_function_compute<ComplexMatrix>::run(CA, atomic, Cresult); - result = Cresult.real(); - } -}; - -/** \internal \ingroup MatrixFunctions_Module - * \brief Partial specialization of MatrixFunction for complex matrices - */ -template <typename MatrixType> -struct matrix_function_compute<MatrixType, 1> -{ - template <typename MatA, typename AtomicType, typename ResultType> - static void run(const MatA& A, AtomicType& atomic, ResultType &result) - { - typedef internal::traits<MatrixType> Traits; - - // compute Schur decomposition of A - const ComplexSchur<MatrixType> schurOfA(A); - MatrixType T = schurOfA.matrixT(); - MatrixType U = schurOfA.matrixU(); - - // partition eigenvalues into clusters of ei'vals "close" to each other - std::list<std::list<Index> > clusters; - matrix_function_partition_eigenvalues(T.diagonal(), clusters); - - // compute size of each cluster - Matrix<Index, Dynamic, 1> clusterSize; - matrix_function_compute_cluster_size(clusters, clusterSize); - - // blockStart[i] is row index at which block corresponding to i-th cluster starts - Matrix<Index, Dynamic, 1> blockStart; - matrix_function_compute_block_start(clusterSize, blockStart); - - // compute map so that eivalToCluster[i] = j means that i-th ei'val is in j-th cluster - Matrix<Index, Dynamic, 1> eivalToCluster; - matrix_function_compute_map(T.diagonal(), clusters, eivalToCluster); - - // compute permutation which groups ei'vals in same cluster together - Matrix<Index, Traits::RowsAtCompileTime, 1> permutation; - matrix_function_compute_permutation(blockStart, eivalToCluster, permutation); - - // permute Schur decomposition - matrix_function_permute_schur(permutation, U, T); - - // compute result - MatrixType fT; // matrix function applied to T - matrix_function_compute_block_atomic(T, atomic, blockStart, clusterSize, fT); - matrix_function_compute_above_diagonal(T, blockStart, clusterSize, fT); - result = U * (fT.template triangularView<Upper>() * U.adjoint()); - } -}; - -} // end of namespace internal - -/** \ingroup MatrixFunctions_Module - * - * \brief Proxy for the matrix function of some matrix (expression). - * - * \tparam Derived Type of the argument to the matrix function. - * - * This class holds the argument to the matrix function until it is assigned or evaluated for some other - * reason (so the argument should not be changed in the meantime). It is the return type of - * matrixBase::matrixFunction() and related functions and most of the time this is the only way it is used. - */ -template<typename Derived> class MatrixFunctionReturnValue -: public ReturnByValue<MatrixFunctionReturnValue<Derived> > -{ - public: - typedef typename Derived::Scalar Scalar; - typedef typename Derived::Index Index; - typedef typename internal::stem_function<Scalar>::type StemFunction; - - protected: - typedef typename internal::ref_selector<Derived>::type DerivedNested; - - public: - - /** \brief Constructor. - * - * \param[in] A %Matrix (expression) forming the argument of the matrix function. - * \param[in] f Stem function for matrix function under consideration. - */ - MatrixFunctionReturnValue(const Derived& A, StemFunction f) : m_A(A), m_f(f) { } - - /** \brief Compute the matrix function. - * - * \param[out] result \p f applied to \p A, where \p f and \p A are as in the constructor. - */ - template <typename ResultType> - inline void evalTo(ResultType& result) const - { - typedef typename internal::nested_eval<Derived, 10>::type NestedEvalType; - typedef typename internal::remove_all<NestedEvalType>::type NestedEvalTypeClean; - typedef internal::traits<NestedEvalTypeClean> Traits; - static const int RowsAtCompileTime = Traits::RowsAtCompileTime; - static const int ColsAtCompileTime = Traits::ColsAtCompileTime; - typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar; - typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, RowsAtCompileTime, ColsAtCompileTime> DynMatrixType; - - typedef internal::MatrixFunctionAtomic<DynMatrixType> AtomicType; - AtomicType atomic(m_f); - - internal::matrix_function_compute<typename NestedEvalTypeClean::PlainObject>::run(m_A, atomic, result); - } - - Index rows() const { return m_A.rows(); } - Index cols() const { return m_A.cols(); } - - private: - const DerivedNested m_A; - StemFunction *m_f; -}; - -namespace internal { -template<typename Derived> -struct traits<MatrixFunctionReturnValue<Derived> > -{ - typedef typename Derived::PlainObject ReturnType; -}; -} - - -/********** MatrixBase methods **********/ - - -template <typename Derived> -const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::matrixFunction(typename internal::stem_function<typename internal::traits<Derived>::Scalar>::type f) const -{ - eigen_assert(rows() == cols()); - return MatrixFunctionReturnValue<Derived>(derived(), f); -} - -template <typename Derived> -const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sin() const -{ - eigen_assert(rows() == cols()); - typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_sin<ComplexScalar>); -} - -template <typename Derived> -const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cos() const -{ - eigen_assert(rows() == cols()); - typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_cos<ComplexScalar>); -} - -template <typename Derived> -const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sinh() const -{ - eigen_assert(rows() == cols()); - typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_sinh<ComplexScalar>); -} - -template <typename Derived> -const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cosh() const -{ - eigen_assert(rows() == cols()); - typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar; - return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_cosh<ComplexScalar>); -} - -} // end namespace Eigen - -#endif // EIGEN_MATRIX_FUNCTION_H diff --git a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h b/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h deleted file mode 100644 index cf5fffa..0000000 --- a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixLogarithm.h +++ /dev/null @@ -1,373 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2011, 2013 Jitse Niesen <jitse@maths.leeds.ac.uk> -// Copyright (C) 2011 Chen-Pang He <jdh8@ms63.hinet.net> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_MATRIX_LOGARITHM -#define EIGEN_MATRIX_LOGARITHM - -namespace Eigen { - -namespace internal { - -template <typename Scalar> -struct matrix_log_min_pade_degree -{ - static const int value = 3; -}; - -template <typename Scalar> -struct matrix_log_max_pade_degree -{ - typedef typename NumTraits<Scalar>::Real RealScalar; - static const int value = std::numeric_limits<RealScalar>::digits<= 24? 5: // single precision - std::numeric_limits<RealScalar>::digits<= 53? 7: // double precision - std::numeric_limits<RealScalar>::digits<= 64? 8: // extended precision - std::numeric_limits<RealScalar>::digits<=106? 10: // double-double - 11; // quadruple precision -}; - -/** \brief Compute logarithm of 2x2 triangular matrix. */ -template <typename MatrixType> -void matrix_log_compute_2x2(const MatrixType& A, MatrixType& result) -{ - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::RealScalar RealScalar; - using std::abs; - using std::ceil; - using std::imag; - using std::log; - - Scalar logA00 = log(A(0,0)); - Scalar logA11 = log(A(1,1)); - - result(0,0) = logA00; - result(1,0) = Scalar(0); - result(1,1) = logA11; - - Scalar y = A(1,1) - A(0,0); - if (y==Scalar(0)) - { - result(0,1) = A(0,1) / A(0,0); - } - else if ((abs(A(0,0)) < RealScalar(0.5)*abs(A(1,1))) || (abs(A(0,0)) > 2*abs(A(1,1)))) - { - result(0,1) = A(0,1) * (logA11 - logA00) / y; - } - else - { - // computation in previous branch is inaccurate if A(1,1) \approx A(0,0) - int unwindingNumber = static_cast<int>(ceil((imag(logA11 - logA00) - RealScalar(EIGEN_PI)) / RealScalar(2*EIGEN_PI))); - result(0,1) = A(0,1) * (numext::log1p(y/A(0,0)) + Scalar(0,2*EIGEN_PI*unwindingNumber)) / y; - } -} - -/* \brief Get suitable degree for Pade approximation. (specialized for RealScalar = float) */ -inline int matrix_log_get_pade_degree(float normTminusI) -{ - const float maxNormForPade[] = { 2.5111573934555054e-1 /* degree = 3 */ , 4.0535837411880493e-1, - 5.3149729967117310e-1 }; - const int minPadeDegree = matrix_log_min_pade_degree<float>::value; - const int maxPadeDegree = matrix_log_max_pade_degree<float>::value; - int degree = minPadeDegree; - for (; degree <= maxPadeDegree; ++degree) - if (normTminusI <= maxNormForPade[degree - minPadeDegree]) - break; - return degree; -} - -/* \brief Get suitable degree for Pade approximation. (specialized for RealScalar = double) */ -inline int matrix_log_get_pade_degree(double normTminusI) -{ - const double maxNormForPade[] = { 1.6206284795015624e-2 /* degree = 3 */ , 5.3873532631381171e-2, - 1.1352802267628681e-1, 1.8662860613541288e-1, 2.642960831111435e-1 }; - const int minPadeDegree = matrix_log_min_pade_degree<double>::value; - const int maxPadeDegree = matrix_log_max_pade_degree<double>::value; - int degree = minPadeDegree; - for (; degree <= maxPadeDegree; ++degree) - if (normTminusI <= maxNormForPade[degree - minPadeDegree]) - break; - return degree; -} - -/* \brief Get suitable degree for Pade approximation. (specialized for RealScalar = long double) */ -inline int matrix_log_get_pade_degree(long double normTminusI) -{ -#if LDBL_MANT_DIG == 53 // double precision - const long double maxNormForPade[] = { 1.6206284795015624e-2L /* degree = 3 */ , 5.3873532631381171e-2L, - 1.1352802267628681e-1L, 1.8662860613541288e-1L, 2.642960831111435e-1L }; -#elif LDBL_MANT_DIG <= 64 // extended precision - const long double maxNormForPade[] = { 5.48256690357782863103e-3L /* degree = 3 */, 2.34559162387971167321e-2L, - 5.84603923897347449857e-2L, 1.08486423756725170223e-1L, 1.68385767881294446649e-1L, - 2.32777776523703892094e-1L }; -#elif LDBL_MANT_DIG <= 106 // double-double - const long double maxNormForPade[] = { 8.58970550342939562202529664318890e-5L /* degree = 3 */, - 9.34074328446359654039446552677759e-4L, 4.26117194647672175773064114582860e-3L, - 1.21546224740281848743149666560464e-2L, 2.61100544998339436713088248557444e-2L, - 4.66170074627052749243018566390567e-2L, 7.32585144444135027565872014932387e-2L, - 1.05026503471351080481093652651105e-1L }; -#else // quadruple precision - const long double maxNormForPade[] = { 4.7419931187193005048501568167858103e-5L /* degree = 3 */, - 5.8853168473544560470387769480192666e-4L, 2.9216120366601315391789493628113520e-3L, - 8.8415758124319434347116734705174308e-3L, 1.9850836029449446668518049562565291e-2L, - 3.6688019729653446926585242192447447e-2L, 5.9290962294020186998954055264528393e-2L, - 8.6998436081634343903250580992127677e-2L, 1.1880960220216759245467951592883642e-1L }; -#endif - const int minPadeDegree = matrix_log_min_pade_degree<long double>::value; - const int maxPadeDegree = matrix_log_max_pade_degree<long double>::value; - int degree = minPadeDegree; - for (; degree <= maxPadeDegree; ++degree) - if (normTminusI <= maxNormForPade[degree - minPadeDegree]) - break; - return degree; -} - -/* \brief Compute Pade approximation to matrix logarithm */ -template <typename MatrixType> -void matrix_log_compute_pade(MatrixType& result, const MatrixType& T, int degree) -{ - typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; - const int minPadeDegree = 3; - const int maxPadeDegree = 11; - assert(degree >= minPadeDegree && degree <= maxPadeDegree); - - const RealScalar nodes[][maxPadeDegree] = { - { 0.1127016653792583114820734600217600L, 0.5000000000000000000000000000000000L, // degree 3 - 0.8872983346207416885179265399782400L }, - { 0.0694318442029737123880267555535953L, 0.3300094782075718675986671204483777L, // degree 4 - 0.6699905217924281324013328795516223L, 0.9305681557970262876119732444464048L }, - { 0.0469100770306680036011865608503035L, 0.2307653449471584544818427896498956L, // degree 5 - 0.5000000000000000000000000000000000L, 0.7692346550528415455181572103501044L, - 0.9530899229693319963988134391496965L }, - { 0.0337652428984239860938492227530027L, 0.1693953067668677431693002024900473L, // degree 6 - 0.3806904069584015456847491391596440L, 0.6193095930415984543152508608403560L, - 0.8306046932331322568306997975099527L, 0.9662347571015760139061507772469973L }, - { 0.0254460438286207377369051579760744L, 0.1292344072003027800680676133596058L, // degree 7 - 0.2970774243113014165466967939615193L, 0.5000000000000000000000000000000000L, - 0.7029225756886985834533032060384807L, 0.8707655927996972199319323866403942L, - 0.9745539561713792622630948420239256L }, - { 0.0198550717512318841582195657152635L, 0.1016667612931866302042230317620848L, // degree 8 - 0.2372337950418355070911304754053768L, 0.4082826787521750975302619288199080L, - 0.5917173212478249024697380711800920L, 0.7627662049581644929088695245946232L, - 0.8983332387068133697957769682379152L, 0.9801449282487681158417804342847365L }, - { 0.0159198802461869550822118985481636L, 0.0819844463366821028502851059651326L, // degree 9 - 0.1933142836497048013456489803292629L, 0.3378732882980955354807309926783317L, - 0.5000000000000000000000000000000000L, 0.6621267117019044645192690073216683L, - 0.8066857163502951986543510196707371L, 0.9180155536633178971497148940348674L, - 0.9840801197538130449177881014518364L }, - { 0.0130467357414141399610179939577740L, 0.0674683166555077446339516557882535L, // degree 10 - 0.1602952158504877968828363174425632L, 0.2833023029353764046003670284171079L, - 0.4255628305091843945575869994351400L, 0.5744371694908156054424130005648600L, - 0.7166976970646235953996329715828921L, 0.8397047841495122031171636825574368L, - 0.9325316833444922553660483442117465L, 0.9869532642585858600389820060422260L }, - { 0.0108856709269715035980309994385713L, 0.0564687001159523504624211153480364L, // degree 11 - 0.1349239972129753379532918739844233L, 0.2404519353965940920371371652706952L, - 0.3652284220238275138342340072995692L, 0.5000000000000000000000000000000000L, - 0.6347715779761724861657659927004308L, 0.7595480646034059079628628347293048L, - 0.8650760027870246620467081260155767L, 0.9435312998840476495375788846519636L, - 0.9891143290730284964019690005614287L } }; - - const RealScalar weights[][maxPadeDegree] = { - { 0.2777777777777777777777777777777778L, 0.4444444444444444444444444444444444L, // degree 3 - 0.2777777777777777777777777777777778L }, - { 0.1739274225687269286865319746109997L, 0.3260725774312730713134680253890003L, // degree 4 - 0.3260725774312730713134680253890003L, 0.1739274225687269286865319746109997L }, - { 0.1184634425280945437571320203599587L, 0.2393143352496832340206457574178191L, // degree 5 - 0.2844444444444444444444444444444444L, 0.2393143352496832340206457574178191L, - 0.1184634425280945437571320203599587L }, - { 0.0856622461895851725201480710863665L, 0.1803807865240693037849167569188581L, // degree 6 - 0.2339569672863455236949351719947755L, 0.2339569672863455236949351719947755L, - 0.1803807865240693037849167569188581L, 0.0856622461895851725201480710863665L }, - { 0.0647424830844348466353057163395410L, 0.1398526957446383339507338857118898L, // degree 7 - 0.1909150252525594724751848877444876L, 0.2089795918367346938775510204081633L, - 0.1909150252525594724751848877444876L, 0.1398526957446383339507338857118898L, - 0.0647424830844348466353057163395410L }, - { 0.0506142681451881295762656771549811L, 0.1111905172266872352721779972131204L, // degree 8 - 0.1568533229389436436689811009933007L, 0.1813418916891809914825752246385978L, - 0.1813418916891809914825752246385978L, 0.1568533229389436436689811009933007L, - 0.1111905172266872352721779972131204L, 0.0506142681451881295762656771549811L }, - { 0.0406371941807872059859460790552618L, 0.0903240803474287020292360156214564L, // degree 9 - 0.1303053482014677311593714347093164L, 0.1561735385200014200343152032922218L, - 0.1651196775006298815822625346434870L, 0.1561735385200014200343152032922218L, - 0.1303053482014677311593714347093164L, 0.0903240803474287020292360156214564L, - 0.0406371941807872059859460790552618L }, - { 0.0333356721543440687967844049466659L, 0.0747256745752902965728881698288487L, // degree 10 - 0.1095431812579910219977674671140816L, 0.1346333596549981775456134607847347L, - 0.1477621123573764350869464973256692L, 0.1477621123573764350869464973256692L, - 0.1346333596549981775456134607847347L, 0.1095431812579910219977674671140816L, - 0.0747256745752902965728881698288487L, 0.0333356721543440687967844049466659L }, - { 0.0278342835580868332413768602212743L, 0.0627901847324523123173471496119701L, // degree 11 - 0.0931451054638671257130488207158280L, 0.1165968822959952399592618524215876L, - 0.1314022722551233310903444349452546L, 0.1364625433889503153572417641681711L, - 0.1314022722551233310903444349452546L, 0.1165968822959952399592618524215876L, - 0.0931451054638671257130488207158280L, 0.0627901847324523123173471496119701L, - 0.0278342835580868332413768602212743L } }; - - MatrixType TminusI = T - MatrixType::Identity(T.rows(), T.rows()); - result.setZero(T.rows(), T.rows()); - for (int k = 0; k < degree; ++k) { - RealScalar weight = weights[degree-minPadeDegree][k]; - RealScalar node = nodes[degree-minPadeDegree][k]; - result += weight * (MatrixType::Identity(T.rows(), T.rows()) + node * TminusI) - .template triangularView<Upper>().solve(TminusI); - } -} - -/** \brief Compute logarithm of triangular matrices with size > 2. - * \details This uses a inverse scale-and-square algorithm. */ -template <typename MatrixType> -void matrix_log_compute_big(const MatrixType& A, MatrixType& result) -{ - typedef typename MatrixType::Scalar Scalar; - typedef typename NumTraits<Scalar>::Real RealScalar; - using std::pow; - - int numberOfSquareRoots = 0; - int numberOfExtraSquareRoots = 0; - int degree; - MatrixType T = A, sqrtT; - - int maxPadeDegree = matrix_log_max_pade_degree<Scalar>::value; - const RealScalar maxNormForPade = maxPadeDegree<= 5? 5.3149729967117310e-1L: // single precision - maxPadeDegree<= 7? 2.6429608311114350e-1L: // double precision - maxPadeDegree<= 8? 2.32777776523703892094e-1L: // extended precision - maxPadeDegree<=10? 1.05026503471351080481093652651105e-1L: // double-double - 1.1880960220216759245467951592883642e-1L; // quadruple precision - - while (true) { - RealScalar normTminusI = (T - MatrixType::Identity(T.rows(), T.rows())).cwiseAbs().colwise().sum().maxCoeff(); - if (normTminusI < maxNormForPade) { - degree = matrix_log_get_pade_degree(normTminusI); - int degree2 = matrix_log_get_pade_degree(normTminusI / RealScalar(2)); - if ((degree - degree2 <= 1) || (numberOfExtraSquareRoots == 1)) - break; - ++numberOfExtraSquareRoots; - } - matrix_sqrt_triangular(T, sqrtT); - T = sqrtT.template triangularView<Upper>(); - ++numberOfSquareRoots; - } - - matrix_log_compute_pade(result, T, degree); - result *= pow(RealScalar(2), numberOfSquareRoots); -} - -/** \ingroup MatrixFunctions_Module - * \class MatrixLogarithmAtomic - * \brief Helper class for computing matrix logarithm of atomic matrices. - * - * Here, an atomic matrix is a triangular matrix whose diagonal entries are close to each other. - * - * \sa class MatrixFunctionAtomic, MatrixBase::log() - */ -template <typename MatrixType> -class MatrixLogarithmAtomic -{ -public: - /** \brief Compute matrix logarithm of atomic matrix - * \param[in] A argument of matrix logarithm, should be upper triangular and atomic - * \returns The logarithm of \p A. - */ - MatrixType compute(const MatrixType& A); -}; - -template <typename MatrixType> -MatrixType MatrixLogarithmAtomic<MatrixType>::compute(const MatrixType& A) -{ - using std::log; - MatrixType result(A.rows(), A.rows()); - if (A.rows() == 1) - result(0,0) = log(A(0,0)); - else if (A.rows() == 2) - matrix_log_compute_2x2(A, result); - else - matrix_log_compute_big(A, result); - return result; -} - -} // end of namespace internal - -/** \ingroup MatrixFunctions_Module - * - * \brief Proxy for the matrix logarithm of some matrix (expression). - * - * \tparam Derived Type of the argument to the matrix function. - * - * This class holds the argument to the matrix function until it is - * assigned or evaluated for some other reason (so the argument - * should not be changed in the meantime). It is the return type of - * MatrixBase::log() and most of the time this is the only way it - * is used. - */ -template<typename Derived> class MatrixLogarithmReturnValue -: public ReturnByValue<MatrixLogarithmReturnValue<Derived> > -{ -public: - typedef typename Derived::Scalar Scalar; - typedef typename Derived::Index Index; - -protected: - typedef typename internal::ref_selector<Derived>::type DerivedNested; - -public: - - /** \brief Constructor. - * - * \param[in] A %Matrix (expression) forming the argument of the matrix logarithm. - */ - explicit MatrixLogarithmReturnValue(const Derived& A) : m_A(A) { } - - /** \brief Compute the matrix logarithm. - * - * \param[out] result Logarithm of \c A, where \c A is as specified in the constructor. - */ - template <typename ResultType> - inline void evalTo(ResultType& result) const - { - typedef typename internal::nested_eval<Derived, 10>::type DerivedEvalType; - typedef typename internal::remove_all<DerivedEvalType>::type DerivedEvalTypeClean; - typedef internal::traits<DerivedEvalTypeClean> Traits; - static const int RowsAtCompileTime = Traits::RowsAtCompileTime; - static const int ColsAtCompileTime = Traits::ColsAtCompileTime; - typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar; - typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, RowsAtCompileTime, ColsAtCompileTime> DynMatrixType; - typedef internal::MatrixLogarithmAtomic<DynMatrixType> AtomicType; - AtomicType atomic; - - internal::matrix_function_compute<typename DerivedEvalTypeClean::PlainObject>::run(m_A, atomic, result); - } - - Index rows() const { return m_A.rows(); } - Index cols() const { return m_A.cols(); } - -private: - const DerivedNested m_A; -}; - -namespace internal { - template<typename Derived> - struct traits<MatrixLogarithmReturnValue<Derived> > - { - typedef typename Derived::PlainObject ReturnType; - }; -} - - -/********** MatrixBase method **********/ - - -template <typename Derived> -const MatrixLogarithmReturnValue<Derived> MatrixBase<Derived>::log() const -{ - eigen_assert(rows() == cols()); - return MatrixLogarithmReturnValue<Derived>(derived()); -} - -} // end namespace Eigen - -#endif // EIGEN_MATRIX_LOGARITHM diff --git a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h b/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h deleted file mode 100644 index a3273da..0000000 --- a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixPower.h +++ /dev/null @@ -1,709 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2012, 2013 Chen-Pang He <jdh8@ms63.hinet.net> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_MATRIX_POWER -#define EIGEN_MATRIX_POWER - -namespace Eigen { - -template<typename MatrixType> class MatrixPower; - -/** - * \ingroup MatrixFunctions_Module - * - * \brief Proxy for the matrix power of some matrix. - * - * \tparam MatrixType type of the base, a matrix. - * - * This class holds the arguments to the matrix power until it is - * assigned or evaluated for some other reason (so the argument - * should not be changed in the meantime). It is the return type of - * MatrixPower::operator() and related functions and most of the - * time this is the only way it is used. - */ -/* TODO This class is only used by MatrixPower, so it should be nested - * into MatrixPower, like MatrixPower::ReturnValue. However, my - * compiler complained about unused template parameter in the - * following declaration in namespace internal. - * - * template<typename MatrixType> - * struct traits<MatrixPower<MatrixType>::ReturnValue>; - */ -template<typename MatrixType> -class MatrixPowerParenthesesReturnValue : public ReturnByValue< MatrixPowerParenthesesReturnValue<MatrixType> > -{ - public: - typedef typename MatrixType::RealScalar RealScalar; - typedef typename MatrixType::Index Index; - - /** - * \brief Constructor. - * - * \param[in] pow %MatrixPower storing the base. - * \param[in] p scalar, the exponent of the matrix power. - */ - MatrixPowerParenthesesReturnValue(MatrixPower<MatrixType>& pow, RealScalar p) : m_pow(pow), m_p(p) - { } - - /** - * \brief Compute the matrix power. - * - * \param[out] result - */ - template<typename ResultType> - inline void evalTo(ResultType& result) const - { m_pow.compute(result, m_p); } - - Index rows() const { return m_pow.rows(); } - Index cols() const { return m_pow.cols(); } - - private: - MatrixPower<MatrixType>& m_pow; - const RealScalar m_p; -}; - -/** - * \ingroup MatrixFunctions_Module - * - * \brief Class for computing matrix powers. - * - * \tparam MatrixType type of the base, expected to be an instantiation - * of the Matrix class template. - * - * This class is capable of computing triangular real/complex matrices - * raised to a power in the interval \f$ (-1, 1) \f$. - * - * \note Currently this class is only used by MatrixPower. One may - * insist that this be nested into MatrixPower. This class is here to - * faciliate future development of triangular matrix functions. - */ -template<typename MatrixType> -class MatrixPowerAtomic : internal::noncopyable -{ - private: - enum { - RowsAtCompileTime = MatrixType::RowsAtCompileTime, - MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime - }; - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::RealScalar RealScalar; - typedef std::complex<RealScalar> ComplexScalar; - typedef typename MatrixType::Index Index; - typedef Block<MatrixType,Dynamic,Dynamic> ResultType; - - const MatrixType& m_A; - RealScalar m_p; - - void computePade(int degree, const MatrixType& IminusT, ResultType& res) const; - void compute2x2(ResultType& res, RealScalar p) const; - void computeBig(ResultType& res) const; - static int getPadeDegree(float normIminusT); - static int getPadeDegree(double normIminusT); - static int getPadeDegree(long double normIminusT); - static ComplexScalar computeSuperDiag(const ComplexScalar&, const ComplexScalar&, RealScalar p); - static RealScalar computeSuperDiag(RealScalar, RealScalar, RealScalar p); - - public: - /** - * \brief Constructor. - * - * \param[in] T the base of the matrix power. - * \param[in] p the exponent of the matrix power, should be in - * \f$ (-1, 1) \f$. - * - * The class stores a reference to T, so it should not be changed - * (or destroyed) before evaluation. Only the upper triangular - * part of T is read. - */ - MatrixPowerAtomic(const MatrixType& T, RealScalar p); - - /** - * \brief Compute the matrix power. - * - * \param[out] res \f$ A^p \f$ where A and p are specified in the - * constructor. - */ - void compute(ResultType& res) const; -}; - -template<typename MatrixType> -MatrixPowerAtomic<MatrixType>::MatrixPowerAtomic(const MatrixType& T, RealScalar p) : - m_A(T), m_p(p) -{ - eigen_assert(T.rows() == T.cols()); - eigen_assert(p > -1 && p < 1); -} - -template<typename MatrixType> -void MatrixPowerAtomic<MatrixType>::compute(ResultType& res) const -{ - using std::pow; - switch (m_A.rows()) { - case 0: - break; - case 1: - res(0,0) = pow(m_A(0,0), m_p); - break; - case 2: - compute2x2(res, m_p); - break; - default: - computeBig(res); - } -} - -template<typename MatrixType> -void MatrixPowerAtomic<MatrixType>::computePade(int degree, const MatrixType& IminusT, ResultType& res) const -{ - int i = 2*degree; - res = (m_p-degree) / (2*i-2) * IminusT; - - for (--i; i; --i) { - res = (MatrixType::Identity(IminusT.rows(), IminusT.cols()) + res).template triangularView<Upper>() - .solve((i==1 ? -m_p : i&1 ? (-m_p-i/2)/(2*i) : (m_p-i/2)/(2*i-2)) * IminusT).eval(); - } - res += MatrixType::Identity(IminusT.rows(), IminusT.cols()); -} - -// This function assumes that res has the correct size (see bug 614) -template<typename MatrixType> -void MatrixPowerAtomic<MatrixType>::compute2x2(ResultType& res, RealScalar p) const -{ - using std::abs; - using std::pow; - res.coeffRef(0,0) = pow(m_A.coeff(0,0), p); - - for (Index i=1; i < m_A.cols(); ++i) { - res.coeffRef(i,i) = pow(m_A.coeff(i,i), p); - if (m_A.coeff(i-1,i-1) == m_A.coeff(i,i)) - res.coeffRef(i-1,i) = p * pow(m_A.coeff(i,i), p-1); - else if (2*abs(m_A.coeff(i-1,i-1)) < abs(m_A.coeff(i,i)) || 2*abs(m_A.coeff(i,i)) < abs(m_A.coeff(i-1,i-1))) - res.coeffRef(i-1,i) = (res.coeff(i,i)-res.coeff(i-1,i-1)) / (m_A.coeff(i,i)-m_A.coeff(i-1,i-1)); - else - res.coeffRef(i-1,i) = computeSuperDiag(m_A.coeff(i,i), m_A.coeff(i-1,i-1), p); - res.coeffRef(i-1,i) *= m_A.coeff(i-1,i); - } -} - -template<typename MatrixType> -void MatrixPowerAtomic<MatrixType>::computeBig(ResultType& res) const -{ - using std::ldexp; - const int digits = std::numeric_limits<RealScalar>::digits; - const RealScalar maxNormForPade = digits <= 24? 4.3386528e-1L // single precision - : digits <= 53? 2.789358995219730e-1L // double precision - : digits <= 64? 2.4471944416607995472e-1L // extended precision - : digits <= 106? 1.1016843812851143391275867258512e-1L // double-double - : 9.134603732914548552537150753385375e-2L; // quadruple precision - MatrixType IminusT, sqrtT, T = m_A.template triangularView<Upper>(); - RealScalar normIminusT; - int degree, degree2, numberOfSquareRoots = 0; - bool hasExtraSquareRoot = false; - - for (Index i=0; i < m_A.cols(); ++i) - eigen_assert(m_A(i,i) != RealScalar(0)); - - while (true) { - IminusT = MatrixType::Identity(m_A.rows(), m_A.cols()) - T; - normIminusT = IminusT.cwiseAbs().colwise().sum().maxCoeff(); - if (normIminusT < maxNormForPade) { - degree = getPadeDegree(normIminusT); - degree2 = getPadeDegree(normIminusT/2); - if (degree - degree2 <= 1 || hasExtraSquareRoot) - break; - hasExtraSquareRoot = true; - } - matrix_sqrt_triangular(T, sqrtT); - T = sqrtT.template triangularView<Upper>(); - ++numberOfSquareRoots; - } - computePade(degree, IminusT, res); - - for (; numberOfSquareRoots; --numberOfSquareRoots) { - compute2x2(res, ldexp(m_p, -numberOfSquareRoots)); - res = res.template triangularView<Upper>() * res; - } - compute2x2(res, m_p); -} - -template<typename MatrixType> -inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(float normIminusT) -{ - const float maxNormForPade[] = { 2.8064004e-1f /* degree = 3 */ , 4.3386528e-1f }; - int degree = 3; - for (; degree <= 4; ++degree) - if (normIminusT <= maxNormForPade[degree - 3]) - break; - return degree; -} - -template<typename MatrixType> -inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(double normIminusT) -{ - const double maxNormForPade[] = { 1.884160592658218e-2 /* degree = 3 */ , 6.038881904059573e-2, 1.239917516308172e-1, - 1.999045567181744e-1, 2.789358995219730e-1 }; - int degree = 3; - for (; degree <= 7; ++degree) - if (normIminusT <= maxNormForPade[degree - 3]) - break; - return degree; -} - -template<typename MatrixType> -inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(long double normIminusT) -{ -#if LDBL_MANT_DIG == 53 - const int maxPadeDegree = 7; - const double maxNormForPade[] = { 1.884160592658218e-2L /* degree = 3 */ , 6.038881904059573e-2L, 1.239917516308172e-1L, - 1.999045567181744e-1L, 2.789358995219730e-1L }; -#elif LDBL_MANT_DIG <= 64 - const int maxPadeDegree = 8; - const long double maxNormForPade[] = { 6.3854693117491799460e-3L /* degree = 3 */ , 2.6394893435456973676e-2L, - 6.4216043030404063729e-2L, 1.1701165502926694307e-1L, 1.7904284231268670284e-1L, 2.4471944416607995472e-1L }; -#elif LDBL_MANT_DIG <= 106 - const int maxPadeDegree = 10; - const double maxNormForPade[] = { 1.0007161601787493236741409687186e-4L /* degree = 3 */ , - 1.0007161601787493236741409687186e-3L, 4.7069769360887572939882574746264e-3L, 1.3220386624169159689406653101695e-2L, - 2.8063482381631737920612944054906e-2L, 4.9625993951953473052385361085058e-2L, 7.7367040706027886224557538328171e-2L, - 1.1016843812851143391275867258512e-1L }; -#else - const int maxPadeDegree = 10; - const double maxNormForPade[] = { 5.524506147036624377378713555116378e-5L /* degree = 3 */ , - 6.640600568157479679823602193345995e-4L, 3.227716520106894279249709728084626e-3L, - 9.619593944683432960546978734646284e-3L, 2.134595382433742403911124458161147e-2L, - 3.908166513900489428442993794761185e-2L, 6.266780814639442865832535460550138e-2L, - 9.134603732914548552537150753385375e-2L }; -#endif - int degree = 3; - for (; degree <= maxPadeDegree; ++degree) - if (normIminusT <= maxNormForPade[degree - 3]) - break; - return degree; -} - -template<typename MatrixType> -inline typename MatrixPowerAtomic<MatrixType>::ComplexScalar -MatrixPowerAtomic<MatrixType>::computeSuperDiag(const ComplexScalar& curr, const ComplexScalar& prev, RealScalar p) -{ - using std::ceil; - using std::exp; - using std::log; - using std::sinh; - - ComplexScalar logCurr = log(curr); - ComplexScalar logPrev = log(prev); - int unwindingNumber = ceil((numext::imag(logCurr - logPrev) - RealScalar(EIGEN_PI)) / RealScalar(2*EIGEN_PI)); - ComplexScalar w = numext::log1p((curr-prev)/prev)/RealScalar(2) + ComplexScalar(0, EIGEN_PI*unwindingNumber); - return RealScalar(2) * exp(RealScalar(0.5) * p * (logCurr + logPrev)) * sinh(p * w) / (curr - prev); -} - -template<typename MatrixType> -inline typename MatrixPowerAtomic<MatrixType>::RealScalar -MatrixPowerAtomic<MatrixType>::computeSuperDiag(RealScalar curr, RealScalar prev, RealScalar p) -{ - using std::exp; - using std::log; - using std::sinh; - - RealScalar w = numext::log1p((curr-prev)/prev)/RealScalar(2); - return 2 * exp(p * (log(curr) + log(prev)) / 2) * sinh(p * w) / (curr - prev); -} - -/** - * \ingroup MatrixFunctions_Module - * - * \brief Class for computing matrix powers. - * - * \tparam MatrixType type of the base, expected to be an instantiation - * of the Matrix class template. - * - * This class is capable of computing real/complex matrices raised to - * an arbitrary real power. Meanwhile, it saves the result of Schur - * decomposition if an non-integral power has even been calculated. - * Therefore, if you want to compute multiple (>= 2) matrix powers - * for the same matrix, using the class directly is more efficient than - * calling MatrixBase::pow(). - * - * Example: - * \include MatrixPower_optimal.cpp - * Output: \verbinclude MatrixPower_optimal.out - */ -template<typename MatrixType> -class MatrixPower : internal::noncopyable -{ - private: - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::RealScalar RealScalar; - typedef typename MatrixType::Index Index; - - public: - /** - * \brief Constructor. - * - * \param[in] A the base of the matrix power. - * - * The class stores a reference to A, so it should not be changed - * (or destroyed) before evaluation. - */ - explicit MatrixPower(const MatrixType& A) : - m_A(A), - m_conditionNumber(0), - m_rank(A.cols()), - m_nulls(0) - { eigen_assert(A.rows() == A.cols()); } - - /** - * \brief Returns the matrix power. - * - * \param[in] p exponent, a real scalar. - * \return The expression \f$ A^p \f$, where A is specified in the - * constructor. - */ - const MatrixPowerParenthesesReturnValue<MatrixType> operator()(RealScalar p) - { return MatrixPowerParenthesesReturnValue<MatrixType>(*this, p); } - - /** - * \brief Compute the matrix power. - * - * \param[in] p exponent, a real scalar. - * \param[out] res \f$ A^p \f$ where A is specified in the - * constructor. - */ - template<typename ResultType> - void compute(ResultType& res, RealScalar p); - - Index rows() const { return m_A.rows(); } - Index cols() const { return m_A.cols(); } - - private: - typedef std::complex<RealScalar> ComplexScalar; - typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, - MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> ComplexMatrix; - - /** \brief Reference to the base of matrix power. */ - typename MatrixType::Nested m_A; - - /** \brief Temporary storage. */ - MatrixType m_tmp; - - /** \brief Store the result of Schur decomposition. */ - ComplexMatrix m_T, m_U; - - /** \brief Store fractional power of m_T. */ - ComplexMatrix m_fT; - - /** - * \brief Condition number of m_A. - * - * It is initialized as 0 to avoid performing unnecessary Schur - * decomposition, which is the bottleneck. - */ - RealScalar m_conditionNumber; - - /** \brief Rank of m_A. */ - Index m_rank; - - /** \brief Rank deficiency of m_A. */ - Index m_nulls; - - /** - * \brief Split p into integral part and fractional part. - * - * \param[in] p The exponent. - * \param[out] p The fractional part ranging in \f$ (-1, 1) \f$. - * \param[out] intpart The integral part. - * - * Only if the fractional part is nonzero, it calls initialize(). - */ - void split(RealScalar& p, RealScalar& intpart); - - /** \brief Perform Schur decomposition for fractional power. */ - void initialize(); - - template<typename ResultType> - void computeIntPower(ResultType& res, RealScalar p); - - template<typename ResultType> - void computeFracPower(ResultType& res, RealScalar p); - - template<int Rows, int Cols, int Options, int MaxRows, int MaxCols> - static void revertSchur( - Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res, - const ComplexMatrix& T, - const ComplexMatrix& U); - - template<int Rows, int Cols, int Options, int MaxRows, int MaxCols> - static void revertSchur( - Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res, - const ComplexMatrix& T, - const ComplexMatrix& U); -}; - -template<typename MatrixType> -template<typename ResultType> -void MatrixPower<MatrixType>::compute(ResultType& res, RealScalar p) -{ - using std::pow; - switch (cols()) { - case 0: - break; - case 1: - res(0,0) = pow(m_A.coeff(0,0), p); - break; - default: - RealScalar intpart; - split(p, intpart); - - res = MatrixType::Identity(rows(), cols()); - computeIntPower(res, intpart); - if (p) computeFracPower(res, p); - } -} - -template<typename MatrixType> -void MatrixPower<MatrixType>::split(RealScalar& p, RealScalar& intpart) -{ - using std::floor; - using std::pow; - - intpart = floor(p); - p -= intpart; - - // Perform Schur decomposition if it is not yet performed and the power is - // not an integer. - if (!m_conditionNumber && p) - initialize(); - - // Choose the more stable of intpart = floor(p) and intpart = ceil(p). - if (p > RealScalar(0.5) && p > (1-p) * pow(m_conditionNumber, p)) { - --p; - ++intpart; - } -} - -template<typename MatrixType> -void MatrixPower<MatrixType>::initialize() -{ - const ComplexSchur<MatrixType> schurOfA(m_A); - JacobiRotation<ComplexScalar> rot; - ComplexScalar eigenvalue; - - m_fT.resizeLike(m_A); - m_T = schurOfA.matrixT(); - m_U = schurOfA.matrixU(); - m_conditionNumber = m_T.diagonal().array().abs().maxCoeff() / m_T.diagonal().array().abs().minCoeff(); - - // Move zero eigenvalues to the bottom right corner. - for (Index i = cols()-1; i>=0; --i) { - if (m_rank <= 2) - return; - if (m_T.coeff(i,i) == RealScalar(0)) { - for (Index j=i+1; j < m_rank; ++j) { - eigenvalue = m_T.coeff(j,j); - rot.makeGivens(m_T.coeff(j-1,j), eigenvalue); - m_T.applyOnTheRight(j-1, j, rot); - m_T.applyOnTheLeft(j-1, j, rot.adjoint()); - m_T.coeffRef(j-1,j-1) = eigenvalue; - m_T.coeffRef(j,j) = RealScalar(0); - m_U.applyOnTheRight(j-1, j, rot); - } - --m_rank; - } - } - - m_nulls = rows() - m_rank; - if (m_nulls) { - eigen_assert(m_T.bottomRightCorner(m_nulls, m_nulls).isZero() - && "Base of matrix power should be invertible or with a semisimple zero eigenvalue."); - m_fT.bottomRows(m_nulls).fill(RealScalar(0)); - } -} - -template<typename MatrixType> -template<typename ResultType> -void MatrixPower<MatrixType>::computeIntPower(ResultType& res, RealScalar p) -{ - using std::abs; - using std::fmod; - RealScalar pp = abs(p); - - if (p<0) - m_tmp = m_A.inverse(); - else - m_tmp = m_A; - - while (true) { - if (fmod(pp, 2) >= 1) - res = m_tmp * res; - pp /= 2; - if (pp < 1) - break; - m_tmp *= m_tmp; - } -} - -template<typename MatrixType> -template<typename ResultType> -void MatrixPower<MatrixType>::computeFracPower(ResultType& res, RealScalar p) -{ - Block<ComplexMatrix,Dynamic,Dynamic> blockTp(m_fT, 0, 0, m_rank, m_rank); - eigen_assert(m_conditionNumber); - eigen_assert(m_rank + m_nulls == rows()); - - MatrixPowerAtomic<ComplexMatrix>(m_T.topLeftCorner(m_rank, m_rank), p).compute(blockTp); - if (m_nulls) { - m_fT.topRightCorner(m_rank, m_nulls) = m_T.topLeftCorner(m_rank, m_rank).template triangularView<Upper>() - .solve(blockTp * m_T.topRightCorner(m_rank, m_nulls)); - } - revertSchur(m_tmp, m_fT, m_U); - res = m_tmp * res; -} - -template<typename MatrixType> -template<int Rows, int Cols, int Options, int MaxRows, int MaxCols> -inline void MatrixPower<MatrixType>::revertSchur( - Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res, - const ComplexMatrix& T, - const ComplexMatrix& U) -{ res.noalias() = U * (T.template triangularView<Upper>() * U.adjoint()); } - -template<typename MatrixType> -template<int Rows, int Cols, int Options, int MaxRows, int MaxCols> -inline void MatrixPower<MatrixType>::revertSchur( - Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res, - const ComplexMatrix& T, - const ComplexMatrix& U) -{ res.noalias() = (U * (T.template triangularView<Upper>() * U.adjoint())).real(); } - -/** - * \ingroup MatrixFunctions_Module - * - * \brief Proxy for the matrix power of some matrix (expression). - * - * \tparam Derived type of the base, a matrix (expression). - * - * This class holds the arguments to the matrix power until it is - * assigned or evaluated for some other reason (so the argument - * should not be changed in the meantime). It is the return type of - * MatrixBase::pow() and related functions and most of the - * time this is the only way it is used. - */ -template<typename Derived> -class MatrixPowerReturnValue : public ReturnByValue< MatrixPowerReturnValue<Derived> > -{ - public: - typedef typename Derived::PlainObject PlainObject; - typedef typename Derived::RealScalar RealScalar; - typedef typename Derived::Index Index; - - /** - * \brief Constructor. - * - * \param[in] A %Matrix (expression), the base of the matrix power. - * \param[in] p real scalar, the exponent of the matrix power. - */ - MatrixPowerReturnValue(const Derived& A, RealScalar p) : m_A(A), m_p(p) - { } - - /** - * \brief Compute the matrix power. - * - * \param[out] result \f$ A^p \f$ where \p A and \p p are as in the - * constructor. - */ - template<typename ResultType> - inline void evalTo(ResultType& result) const - { MatrixPower<PlainObject>(m_A.eval()).compute(result, m_p); } - - Index rows() const { return m_A.rows(); } - Index cols() const { return m_A.cols(); } - - private: - const Derived& m_A; - const RealScalar m_p; -}; - -/** - * \ingroup MatrixFunctions_Module - * - * \brief Proxy for the matrix power of some matrix (expression). - * - * \tparam Derived type of the base, a matrix (expression). - * - * This class holds the arguments to the matrix power until it is - * assigned or evaluated for some other reason (so the argument - * should not be changed in the meantime). It is the return type of - * MatrixBase::pow() and related functions and most of the - * time this is the only way it is used. - */ -template<typename Derived> -class MatrixComplexPowerReturnValue : public ReturnByValue< MatrixComplexPowerReturnValue<Derived> > -{ - public: - typedef typename Derived::PlainObject PlainObject; - typedef typename std::complex<typename Derived::RealScalar> ComplexScalar; - typedef typename Derived::Index Index; - - /** - * \brief Constructor. - * - * \param[in] A %Matrix (expression), the base of the matrix power. - * \param[in] p complex scalar, the exponent of the matrix power. - */ - MatrixComplexPowerReturnValue(const Derived& A, const ComplexScalar& p) : m_A(A), m_p(p) - { } - - /** - * \brief Compute the matrix power. - * - * Because \p p is complex, \f$ A^p \f$ is simply evaluated as \f$ - * \exp(p \log(A)) \f$. - * - * \param[out] result \f$ A^p \f$ where \p A and \p p are as in the - * constructor. - */ - template<typename ResultType> - inline void evalTo(ResultType& result) const - { result = (m_p * m_A.log()).exp(); } - - Index rows() const { return m_A.rows(); } - Index cols() const { return m_A.cols(); } - - private: - const Derived& m_A; - const ComplexScalar m_p; -}; - -namespace internal { - -template<typename MatrixPowerType> -struct traits< MatrixPowerParenthesesReturnValue<MatrixPowerType> > -{ typedef typename MatrixPowerType::PlainObject ReturnType; }; - -template<typename Derived> -struct traits< MatrixPowerReturnValue<Derived> > -{ typedef typename Derived::PlainObject ReturnType; }; - -template<typename Derived> -struct traits< MatrixComplexPowerReturnValue<Derived> > -{ typedef typename Derived::PlainObject ReturnType; }; - -} - -template<typename Derived> -const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(const RealScalar& p) const -{ return MatrixPowerReturnValue<Derived>(derived(), p); } - -template<typename Derived> -const MatrixComplexPowerReturnValue<Derived> MatrixBase<Derived>::pow(const std::complex<RealScalar>& p) const -{ return MatrixComplexPowerReturnValue<Derived>(derived(), p); } - -} // namespace Eigen - -#endif // EIGEN_MATRIX_POWER diff --git a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h b/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h deleted file mode 100644 index 2e5abda..0000000 --- a/eigen/unsupported/Eigen/src/MatrixFunctions/MatrixSquareRoot.h +++ /dev/null @@ -1,366 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2011, 2013 Jitse Niesen <jitse@maths.leeds.ac.uk> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_MATRIX_SQUARE_ROOT -#define EIGEN_MATRIX_SQUARE_ROOT - -namespace Eigen { - -namespace internal { - -// pre: T.block(i,i,2,2) has complex conjugate eigenvalues -// post: sqrtT.block(i,i,2,2) is square root of T.block(i,i,2,2) -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular_2x2_diagonal_block(const MatrixType& T, typename MatrixType::Index i, ResultType& sqrtT) -{ - // TODO: This case (2-by-2 blocks with complex conjugate eigenvalues) is probably hidden somewhere - // in EigenSolver. If we expose it, we could call it directly from here. - typedef typename traits<MatrixType>::Scalar Scalar; - Matrix<Scalar,2,2> block = T.template block<2,2>(i,i); - EigenSolver<Matrix<Scalar,2,2> > es(block); - sqrtT.template block<2,2>(i,i) - = (es.eigenvectors() * es.eigenvalues().cwiseSqrt().asDiagonal() * es.eigenvectors().inverse()).real(); -} - -// pre: block structure of T is such that (i,j) is a 1x1 block, -// all blocks of sqrtT to left of and below (i,j) are correct -// post: sqrtT(i,j) has the correct value -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular_1x1_off_diagonal_block(const MatrixType& T, typename MatrixType::Index i, typename MatrixType::Index j, ResultType& sqrtT) -{ - typedef typename traits<MatrixType>::Scalar Scalar; - Scalar tmp = (sqrtT.row(i).segment(i+1,j-i-1) * sqrtT.col(j).segment(i+1,j-i-1)).value(); - sqrtT.coeffRef(i,j) = (T.coeff(i,j) - tmp) / (sqrtT.coeff(i,i) + sqrtT.coeff(j,j)); -} - -// similar to compute1x1offDiagonalBlock() -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular_1x2_off_diagonal_block(const MatrixType& T, typename MatrixType::Index i, typename MatrixType::Index j, ResultType& sqrtT) -{ - typedef typename traits<MatrixType>::Scalar Scalar; - Matrix<Scalar,1,2> rhs = T.template block<1,2>(i,j); - if (j-i > 1) - rhs -= sqrtT.block(i, i+1, 1, j-i-1) * sqrtT.block(i+1, j, j-i-1, 2); - Matrix<Scalar,2,2> A = sqrtT.coeff(i,i) * Matrix<Scalar,2,2>::Identity(); - A += sqrtT.template block<2,2>(j,j).transpose(); - sqrtT.template block<1,2>(i,j).transpose() = A.fullPivLu().solve(rhs.transpose()); -} - -// similar to compute1x1offDiagonalBlock() -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular_2x1_off_diagonal_block(const MatrixType& T, typename MatrixType::Index i, typename MatrixType::Index j, ResultType& sqrtT) -{ - typedef typename traits<MatrixType>::Scalar Scalar; - Matrix<Scalar,2,1> rhs = T.template block<2,1>(i,j); - if (j-i > 2) - rhs -= sqrtT.block(i, i+2, 2, j-i-2) * sqrtT.block(i+2, j, j-i-2, 1); - Matrix<Scalar,2,2> A = sqrtT.coeff(j,j) * Matrix<Scalar,2,2>::Identity(); - A += sqrtT.template block<2,2>(i,i); - sqrtT.template block<2,1>(i,j) = A.fullPivLu().solve(rhs); -} - -// solves the equation A X + X B = C where all matrices are 2-by-2 -template <typename MatrixType> -void matrix_sqrt_quasi_triangular_solve_auxiliary_equation(MatrixType& X, const MatrixType& A, const MatrixType& B, const MatrixType& C) -{ - typedef typename traits<MatrixType>::Scalar Scalar; - Matrix<Scalar,4,4> coeffMatrix = Matrix<Scalar,4,4>::Zero(); - coeffMatrix.coeffRef(0,0) = A.coeff(0,0) + B.coeff(0,0); - coeffMatrix.coeffRef(1,1) = A.coeff(0,0) + B.coeff(1,1); - coeffMatrix.coeffRef(2,2) = A.coeff(1,1) + B.coeff(0,0); - coeffMatrix.coeffRef(3,3) = A.coeff(1,1) + B.coeff(1,1); - coeffMatrix.coeffRef(0,1) = B.coeff(1,0); - coeffMatrix.coeffRef(0,2) = A.coeff(0,1); - coeffMatrix.coeffRef(1,0) = B.coeff(0,1); - coeffMatrix.coeffRef(1,3) = A.coeff(0,1); - coeffMatrix.coeffRef(2,0) = A.coeff(1,0); - coeffMatrix.coeffRef(2,3) = B.coeff(1,0); - coeffMatrix.coeffRef(3,1) = A.coeff(1,0); - coeffMatrix.coeffRef(3,2) = B.coeff(0,1); - - Matrix<Scalar,4,1> rhs; - rhs.coeffRef(0) = C.coeff(0,0); - rhs.coeffRef(1) = C.coeff(0,1); - rhs.coeffRef(2) = C.coeff(1,0); - rhs.coeffRef(3) = C.coeff(1,1); - - Matrix<Scalar,4,1> result; - result = coeffMatrix.fullPivLu().solve(rhs); - - X.coeffRef(0,0) = result.coeff(0); - X.coeffRef(0,1) = result.coeff(1); - X.coeffRef(1,0) = result.coeff(2); - X.coeffRef(1,1) = result.coeff(3); -} - -// similar to compute1x1offDiagonalBlock() -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular_2x2_off_diagonal_block(const MatrixType& T, typename MatrixType::Index i, typename MatrixType::Index j, ResultType& sqrtT) -{ - typedef typename traits<MatrixType>::Scalar Scalar; - Matrix<Scalar,2,2> A = sqrtT.template block<2,2>(i,i); - Matrix<Scalar,2,2> B = sqrtT.template block<2,2>(j,j); - Matrix<Scalar,2,2> C = T.template block<2,2>(i,j); - if (j-i > 2) - C -= sqrtT.block(i, i+2, 2, j-i-2) * sqrtT.block(i+2, j, j-i-2, 2); - Matrix<Scalar,2,2> X; - matrix_sqrt_quasi_triangular_solve_auxiliary_equation(X, A, B, C); - sqrtT.template block<2,2>(i,j) = X; -} - -// pre: T is quasi-upper-triangular and sqrtT is a zero matrix of the same size -// post: the diagonal blocks of sqrtT are the square roots of the diagonal blocks of T -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular_diagonal(const MatrixType& T, ResultType& sqrtT) -{ - using std::sqrt; - const Index size = T.rows(); - for (Index i = 0; i < size; i++) { - if (i == size - 1 || T.coeff(i+1, i) == 0) { - eigen_assert(T(i,i) >= 0); - sqrtT.coeffRef(i,i) = sqrt(T.coeff(i,i)); - } - else { - matrix_sqrt_quasi_triangular_2x2_diagonal_block(T, i, sqrtT); - ++i; - } - } -} - -// pre: T is quasi-upper-triangular and diagonal blocks of sqrtT are square root of diagonal blocks of T. -// post: sqrtT is the square root of T. -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular_off_diagonal(const MatrixType& T, ResultType& sqrtT) -{ - const Index size = T.rows(); - for (Index j = 1; j < size; j++) { - if (T.coeff(j, j-1) != 0) // if T(j-1:j, j-1:j) is a 2-by-2 block - continue; - for (Index i = j-1; i >= 0; i--) { - if (i > 0 && T.coeff(i, i-1) != 0) // if T(i-1:i, i-1:i) is a 2-by-2 block - continue; - bool iBlockIs2x2 = (i < size - 1) && (T.coeff(i+1, i) != 0); - bool jBlockIs2x2 = (j < size - 1) && (T.coeff(j+1, j) != 0); - if (iBlockIs2x2 && jBlockIs2x2) - matrix_sqrt_quasi_triangular_2x2_off_diagonal_block(T, i, j, sqrtT); - else if (iBlockIs2x2 && !jBlockIs2x2) - matrix_sqrt_quasi_triangular_2x1_off_diagonal_block(T, i, j, sqrtT); - else if (!iBlockIs2x2 && jBlockIs2x2) - matrix_sqrt_quasi_triangular_1x2_off_diagonal_block(T, i, j, sqrtT); - else if (!iBlockIs2x2 && !jBlockIs2x2) - matrix_sqrt_quasi_triangular_1x1_off_diagonal_block(T, i, j, sqrtT); - } - } -} - -} // end of namespace internal - -/** \ingroup MatrixFunctions_Module - * \brief Compute matrix square root of quasi-triangular matrix. - * - * \tparam MatrixType type of \p arg, the argument of matrix square root, - * expected to be an instantiation of the Matrix class template. - * \tparam ResultType type of \p result, where result is to be stored. - * \param[in] arg argument of matrix square root. - * \param[out] result matrix square root of upper Hessenberg part of \p arg. - * - * This function computes the square root of the upper quasi-triangular matrix stored in the upper - * Hessenberg part of \p arg. Only the upper Hessenberg part of \p result is updated, the rest is - * not touched. See MatrixBase::sqrt() for details on how this computation is implemented. - * - * \sa MatrixSquareRoot, MatrixSquareRootQuasiTriangular - */ -template <typename MatrixType, typename ResultType> -void matrix_sqrt_quasi_triangular(const MatrixType &arg, ResultType &result) -{ - eigen_assert(arg.rows() == arg.cols()); - result.resize(arg.rows(), arg.cols()); - internal::matrix_sqrt_quasi_triangular_diagonal(arg, result); - internal::matrix_sqrt_quasi_triangular_off_diagonal(arg, result); -} - - -/** \ingroup MatrixFunctions_Module - * \brief Compute matrix square root of triangular matrix. - * - * \tparam MatrixType type of \p arg, the argument of matrix square root, - * expected to be an instantiation of the Matrix class template. - * \tparam ResultType type of \p result, where result is to be stored. - * \param[in] arg argument of matrix square root. - * \param[out] result matrix square root of upper triangular part of \p arg. - * - * Only the upper triangular part (including the diagonal) of \p result is updated, the rest is not - * touched. See MatrixBase::sqrt() for details on how this computation is implemented. - * - * \sa MatrixSquareRoot, MatrixSquareRootQuasiTriangular - */ -template <typename MatrixType, typename ResultType> -void matrix_sqrt_triangular(const MatrixType &arg, ResultType &result) -{ - using std::sqrt; - typedef typename MatrixType::Scalar Scalar; - - eigen_assert(arg.rows() == arg.cols()); - - // Compute square root of arg and store it in upper triangular part of result - // This uses that the square root of triangular matrices can be computed directly. - result.resize(arg.rows(), arg.cols()); - for (Index i = 0; i < arg.rows(); i++) { - result.coeffRef(i,i) = sqrt(arg.coeff(i,i)); - } - for (Index j = 1; j < arg.cols(); j++) { - for (Index i = j-1; i >= 0; i--) { - // if i = j-1, then segment has length 0 so tmp = 0 - Scalar tmp = (result.row(i).segment(i+1,j-i-1) * result.col(j).segment(i+1,j-i-1)).value(); - // denominator may be zero if original matrix is singular - result.coeffRef(i,j) = (arg.coeff(i,j) - tmp) / (result.coeff(i,i) + result.coeff(j,j)); - } - } -} - - -namespace internal { - -/** \ingroup MatrixFunctions_Module - * \brief Helper struct for computing matrix square roots of general matrices. - * \tparam MatrixType type of the argument of the matrix square root, - * expected to be an instantiation of the Matrix class template. - * - * \sa MatrixSquareRootTriangular, MatrixSquareRootQuasiTriangular, MatrixBase::sqrt() - */ -template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex> -struct matrix_sqrt_compute -{ - /** \brief Compute the matrix square root - * - * \param[in] arg matrix whose square root is to be computed. - * \param[out] result square root of \p arg. - * - * See MatrixBase::sqrt() for details on how this computation is implemented. - */ - template <typename ResultType> static void run(const MatrixType &arg, ResultType &result); -}; - - -// ********** Partial specialization for real matrices ********** - -template <typename MatrixType> -struct matrix_sqrt_compute<MatrixType, 0> -{ - template <typename ResultType> - static void run(const MatrixType &arg, ResultType &result) - { - eigen_assert(arg.rows() == arg.cols()); - - // Compute Schur decomposition of arg - const RealSchur<MatrixType> schurOfA(arg); - const MatrixType& T = schurOfA.matrixT(); - const MatrixType& U = schurOfA.matrixU(); - - // Compute square root of T - MatrixType sqrtT = MatrixType::Zero(arg.rows(), arg.cols()); - matrix_sqrt_quasi_triangular(T, sqrtT); - - // Compute square root of arg - result = U * sqrtT * U.adjoint(); - } -}; - - -// ********** Partial specialization for complex matrices ********** - -template <typename MatrixType> -struct matrix_sqrt_compute<MatrixType, 1> -{ - template <typename ResultType> - static void run(const MatrixType &arg, ResultType &result) - { - eigen_assert(arg.rows() == arg.cols()); - - // Compute Schur decomposition of arg - const ComplexSchur<MatrixType> schurOfA(arg); - const MatrixType& T = schurOfA.matrixT(); - const MatrixType& U = schurOfA.matrixU(); - - // Compute square root of T - MatrixType sqrtT; - matrix_sqrt_triangular(T, sqrtT); - - // Compute square root of arg - result = U * (sqrtT.template triangularView<Upper>() * U.adjoint()); - } -}; - -} // end namespace internal - -/** \ingroup MatrixFunctions_Module - * - * \brief Proxy for the matrix square root of some matrix (expression). - * - * \tparam Derived Type of the argument to the matrix square root. - * - * This class holds the argument to the matrix square root until it - * is assigned or evaluated for some other reason (so the argument - * should not be changed in the meantime). It is the return type of - * MatrixBase::sqrt() and most of the time this is the only way it is - * used. - */ -template<typename Derived> class MatrixSquareRootReturnValue -: public ReturnByValue<MatrixSquareRootReturnValue<Derived> > -{ - protected: - typedef typename internal::ref_selector<Derived>::type DerivedNested; - - public: - /** \brief Constructor. - * - * \param[in] src %Matrix (expression) forming the argument of the - * matrix square root. - */ - explicit MatrixSquareRootReturnValue(const Derived& src) : m_src(src) { } - - /** \brief Compute the matrix square root. - * - * \param[out] result the matrix square root of \p src in the - * constructor. - */ - template <typename ResultType> - inline void evalTo(ResultType& result) const - { - typedef typename internal::nested_eval<Derived, 10>::type DerivedEvalType; - typedef typename internal::remove_all<DerivedEvalType>::type DerivedEvalTypeClean; - DerivedEvalType tmp(m_src); - internal::matrix_sqrt_compute<DerivedEvalTypeClean>::run(tmp, result); - } - - Index rows() const { return m_src.rows(); } - Index cols() const { return m_src.cols(); } - - protected: - const DerivedNested m_src; -}; - -namespace internal { -template<typename Derived> -struct traits<MatrixSquareRootReturnValue<Derived> > -{ - typedef typename Derived::PlainObject ReturnType; -}; -} - -template <typename Derived> -const MatrixSquareRootReturnValue<Derived> MatrixBase<Derived>::sqrt() const -{ - eigen_assert(rows() == cols()); - return MatrixSquareRootReturnValue<Derived>(derived()); -} - -} // end namespace Eigen - -#endif // EIGEN_MATRIX_FUNCTION diff --git a/eigen/unsupported/Eigen/src/MatrixFunctions/StemFunction.h b/eigen/unsupported/Eigen/src/MatrixFunctions/StemFunction.h deleted file mode 100644 index 7604df9..0000000 --- a/eigen/unsupported/Eigen/src/MatrixFunctions/StemFunction.h +++ /dev/null @@ -1,117 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2010, 2013 Jitse Niesen <jitse@maths.leeds.ac.uk> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_STEM_FUNCTION -#define EIGEN_STEM_FUNCTION - -namespace Eigen { - -namespace internal { - -/** \brief The exponential function (and its derivatives). */ -template <typename Scalar> -Scalar stem_function_exp(Scalar x, int) -{ - using std::exp; - return exp(x); -} - -/** \brief Cosine (and its derivatives). */ -template <typename Scalar> -Scalar stem_function_cos(Scalar x, int n) -{ - using std::cos; - using std::sin; - Scalar res; - - switch (n % 4) { - case 0: - res = std::cos(x); - break; - case 1: - res = -std::sin(x); - break; - case 2: - res = -std::cos(x); - break; - case 3: - res = std::sin(x); - break; - } - return res; -} - -/** \brief Sine (and its derivatives). */ -template <typename Scalar> -Scalar stem_function_sin(Scalar x, int n) -{ - using std::cos; - using std::sin; - Scalar res; - - switch (n % 4) { - case 0: - res = std::sin(x); - break; - case 1: - res = std::cos(x); - break; - case 2: - res = -std::sin(x); - break; - case 3: - res = -std::cos(x); - break; - } - return res; -} - -/** \brief Hyperbolic cosine (and its derivatives). */ -template <typename Scalar> -Scalar stem_function_cosh(Scalar x, int n) -{ - using std::cosh; - using std::sinh; - Scalar res; - - switch (n % 2) { - case 0: - res = std::cosh(x); - break; - case 1: - res = std::sinh(x); - break; - } - return res; -} - -/** \brief Hyperbolic sine (and its derivatives). */ -template <typename Scalar> -Scalar stem_function_sinh(Scalar x, int n) -{ - using std::cosh; - using std::sinh; - Scalar res; - - switch (n % 2) { - case 0: - res = std::sinh(x); - break; - case 1: - res = std::cosh(x); - break; - } - return res; -} - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_STEM_FUNCTION diff --git a/eigen/unsupported/Eigen/src/MoreVectorization/MathFunctions.h b/eigen/unsupported/Eigen/src/MoreVectorization/MathFunctions.h deleted file mode 100644 index 63cb28d..0000000 --- a/eigen/unsupported/Eigen/src/MoreVectorization/MathFunctions.h +++ /dev/null @@ -1,95 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Rohit Garg <rpg.314@gmail.com> -// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_MOREVECTORIZATION_MATHFUNCTIONS_H -#define EIGEN_MOREVECTORIZATION_MATHFUNCTIONS_H - -namespace Eigen { - -namespace internal { - -/** \internal \returns the arcsin of \a a (coeff-wise) */ -template<typename Packet> inline static Packet pasin(Packet a) { return std::asin(a); } - -#ifdef EIGEN_VECTORIZE_SSE - -template<> EIGEN_DONT_INLINE Packet4f pasin(Packet4f x) -{ - _EIGEN_DECLARE_CONST_Packet4f(half, 0.5); - _EIGEN_DECLARE_CONST_Packet4f(minus_half, -0.5); - _EIGEN_DECLARE_CONST_Packet4f(3half, 1.5); - - _EIGEN_DECLARE_CONST_Packet4f_FROM_INT(sign_mask, 0x80000000); - - _EIGEN_DECLARE_CONST_Packet4f(pi, 3.141592654); - _EIGEN_DECLARE_CONST_Packet4f(pi_over_2, 3.141592654*0.5); - - _EIGEN_DECLARE_CONST_Packet4f(asin1, 4.2163199048E-2); - _EIGEN_DECLARE_CONST_Packet4f(asin2, 2.4181311049E-2); - _EIGEN_DECLARE_CONST_Packet4f(asin3, 4.5470025998E-2); - _EIGEN_DECLARE_CONST_Packet4f(asin4, 7.4953002686E-2); - _EIGEN_DECLARE_CONST_Packet4f(asin5, 1.6666752422E-1); - - Packet4f a = pabs(x);//got the absolute value - - Packet4f sign_bit= _mm_and_ps(x, p4f_sign_mask);//extracted the sign bit - - Packet4f z1,z2;//will need them during computation - - -//will compute the two branches for asin -//so first compare with half - - Packet4f branch_mask= _mm_cmpgt_ps(a, p4f_half);//this is to select which branch to take -//both will be taken, and finally results will be merged -//the branch for values >0.5 - - { -//the core series expansion - z1=pmadd(p4f_minus_half,a,p4f_half); - Packet4f x1=psqrt(z1); - Packet4f s1=pmadd(p4f_asin1, z1, p4f_asin2); - Packet4f s2=pmadd(s1, z1, p4f_asin3); - Packet4f s3=pmadd(s2,z1, p4f_asin4); - Packet4f s4=pmadd(s3,z1, p4f_asin5); - Packet4f temp=pmul(s4,z1);//not really a madd but a mul by z so that the next term can be a madd - z1=pmadd(temp,x1,x1); - z1=padd(z1,z1); - z1=psub(p4f_pi_over_2,z1); - } - - { -//the core series expansion - Packet4f x2=a; - z2=pmul(x2,x2); - Packet4f s1=pmadd(p4f_asin1, z2, p4f_asin2); - Packet4f s2=pmadd(s1, z2, p4f_asin3); - Packet4f s3=pmadd(s2,z2, p4f_asin4); - Packet4f s4=pmadd(s3,z2, p4f_asin5); - Packet4f temp=pmul(s4,z2);//not really a madd but a mul by z so that the next term can be a madd - z2=pmadd(temp,x2,x2); - } - -/* select the correct result from the two branch evaluations */ - z1 = _mm_and_ps(branch_mask, z1); - z2 = _mm_andnot_ps(branch_mask, z2); - Packet4f z = _mm_or_ps(z1,z2); - -/* update the sign */ - return _mm_xor_ps(z, sign_bit); -} - -#endif // EIGEN_VECTORIZE_SSE - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_MOREVECTORIZATION_MATHFUNCTIONS_H diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h deleted file mode 100644 index 8fe3ed8..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h +++ /dev/null @@ -1,601 +0,0 @@ -// -*- coding: utf-8 -// vim: set fileencoding=utf-8 - -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_HYBRIDNONLINEARSOLVER_H -#define EIGEN_HYBRIDNONLINEARSOLVER_H - -namespace Eigen { - -namespace HybridNonLinearSolverSpace { - enum Status { - Running = -1, - ImproperInputParameters = 0, - RelativeErrorTooSmall = 1, - TooManyFunctionEvaluation = 2, - TolTooSmall = 3, - NotMakingProgressJacobian = 4, - NotMakingProgressIterations = 5, - UserAsked = 6 - }; -} - -/** - * \ingroup NonLinearOptimization_Module - * \brief Finds a zero of a system of n - * nonlinear functions in n variables by a modification of the Powell - * hybrid method ("dogleg"). - * - * The user must provide a subroutine which calculates the - * functions. The Jacobian is either provided by the user, or approximated - * using a forward-difference method. - * - */ -template<typename FunctorType, typename Scalar=double> -class HybridNonLinearSolver -{ -public: - typedef DenseIndex Index; - - HybridNonLinearSolver(FunctorType &_functor) - : functor(_functor) { nfev=njev=iter = 0; fnorm= 0.; useExternalScaling=false;} - - struct Parameters { - Parameters() - : factor(Scalar(100.)) - , maxfev(1000) - , xtol(std::sqrt(NumTraits<Scalar>::epsilon())) - , nb_of_subdiagonals(-1) - , nb_of_superdiagonals(-1) - , epsfcn(Scalar(0.)) {} - Scalar factor; - Index maxfev; // maximum number of function evaluation - Scalar xtol; - Index nb_of_subdiagonals; - Index nb_of_superdiagonals; - Scalar epsfcn; - }; - typedef Matrix< Scalar, Dynamic, 1 > FVectorType; - typedef Matrix< Scalar, Dynamic, Dynamic > JacobianType; - /* TODO: if eigen provides a triangular storage, use it here */ - typedef Matrix< Scalar, Dynamic, Dynamic > UpperTriangularType; - - HybridNonLinearSolverSpace::Status hybrj1( - FVectorType &x, - const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) - ); - - HybridNonLinearSolverSpace::Status solveInit(FVectorType &x); - HybridNonLinearSolverSpace::Status solveOneStep(FVectorType &x); - HybridNonLinearSolverSpace::Status solve(FVectorType &x); - - HybridNonLinearSolverSpace::Status hybrd1( - FVectorType &x, - const Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) - ); - - HybridNonLinearSolverSpace::Status solveNumericalDiffInit(FVectorType &x); - HybridNonLinearSolverSpace::Status solveNumericalDiffOneStep(FVectorType &x); - HybridNonLinearSolverSpace::Status solveNumericalDiff(FVectorType &x); - - void resetParameters(void) { parameters = Parameters(); } - Parameters parameters; - FVectorType fvec, qtf, diag; - JacobianType fjac; - UpperTriangularType R; - Index nfev; - Index njev; - Index iter; - Scalar fnorm; - bool useExternalScaling; -private: - FunctorType &functor; - Index n; - Scalar sum; - bool sing; - Scalar temp; - Scalar delta; - bool jeval; - Index ncsuc; - Scalar ratio; - Scalar pnorm, xnorm, fnorm1; - Index nslow1, nslow2; - Index ncfail; - Scalar actred, prered; - FVectorType wa1, wa2, wa3, wa4; - - HybridNonLinearSolver& operator=(const HybridNonLinearSolver&); -}; - - - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::hybrj1( - FVectorType &x, - const Scalar tol - ) -{ - n = x.size(); - - /* check the input parameters for errors. */ - if (n <= 0 || tol < 0.) - return HybridNonLinearSolverSpace::ImproperInputParameters; - - resetParameters(); - parameters.maxfev = 100*(n+1); - parameters.xtol = tol; - diag.setConstant(n, 1.); - useExternalScaling = true; - return solve(x); -} - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::solveInit(FVectorType &x) -{ - n = x.size(); - - wa1.resize(n); wa2.resize(n); wa3.resize(n); wa4.resize(n); - fvec.resize(n); - qtf.resize(n); - fjac.resize(n, n); - if (!useExternalScaling) - diag.resize(n); - eigen_assert( (!useExternalScaling || diag.size()==n) && "When useExternalScaling is set, the caller must provide a valid 'diag'"); - - /* Function Body */ - nfev = 0; - njev = 0; - - /* check the input parameters for errors. */ - if (n <= 0 || parameters.xtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0. ) - return HybridNonLinearSolverSpace::ImproperInputParameters; - if (useExternalScaling) - for (Index j = 0; j < n; ++j) - if (diag[j] <= 0.) - return HybridNonLinearSolverSpace::ImproperInputParameters; - - /* evaluate the function at the starting point */ - /* and calculate its norm. */ - nfev = 1; - if ( functor(x, fvec) < 0) - return HybridNonLinearSolverSpace::UserAsked; - fnorm = fvec.stableNorm(); - - /* initialize iteration counter and monitors. */ - iter = 1; - ncsuc = 0; - ncfail = 0; - nslow1 = 0; - nslow2 = 0; - - return HybridNonLinearSolverSpace::Running; -} - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::solveOneStep(FVectorType &x) -{ - using std::abs; - - eigen_assert(x.size()==n); // check the caller is not cheating us - - Index j; - std::vector<JacobiRotation<Scalar> > v_givens(n), w_givens(n); - - jeval = true; - - /* calculate the jacobian matrix. */ - if ( functor.df(x, fjac) < 0) - return HybridNonLinearSolverSpace::UserAsked; - ++njev; - - wa2 = fjac.colwise().blueNorm(); - - /* on the first iteration and if external scaling is not used, scale according */ - /* to the norms of the columns of the initial jacobian. */ - if (iter == 1) { - if (!useExternalScaling) - for (j = 0; j < n; ++j) - diag[j] = (wa2[j]==0.) ? 1. : wa2[j]; - - /* on the first iteration, calculate the norm of the scaled x */ - /* and initialize the step bound delta. */ - xnorm = diag.cwiseProduct(x).stableNorm(); - delta = parameters.factor * xnorm; - if (delta == 0.) - delta = parameters.factor; - } - - /* compute the qr factorization of the jacobian. */ - HouseholderQR<JacobianType> qrfac(fjac); // no pivoting: - - /* copy the triangular factor of the qr factorization into r. */ - R = qrfac.matrixQR(); - - /* accumulate the orthogonal factor in fjac. */ - fjac = qrfac.householderQ(); - - /* form (q transpose)*fvec and store in qtf. */ - qtf = fjac.transpose() * fvec; - - /* rescale if necessary. */ - if (!useExternalScaling) - diag = diag.cwiseMax(wa2); - - while (true) { - /* determine the direction p. */ - internal::dogleg<Scalar>(R, diag, qtf, delta, wa1); - - /* store the direction p and x + p. calculate the norm of p. */ - wa1 = -wa1; - wa2 = x + wa1; - pnorm = diag.cwiseProduct(wa1).stableNorm(); - - /* on the first iteration, adjust the initial step bound. */ - if (iter == 1) - delta = (std::min)(delta,pnorm); - - /* evaluate the function at x + p and calculate its norm. */ - if ( functor(wa2, wa4) < 0) - return HybridNonLinearSolverSpace::UserAsked; - ++nfev; - fnorm1 = wa4.stableNorm(); - - /* compute the scaled actual reduction. */ - actred = -1.; - if (fnorm1 < fnorm) /* Computing 2nd power */ - actred = 1. - numext::abs2(fnorm1 / fnorm); - - /* compute the scaled predicted reduction. */ - wa3 = R.template triangularView<Upper>()*wa1 + qtf; - temp = wa3.stableNorm(); - prered = 0.; - if (temp < fnorm) /* Computing 2nd power */ - prered = 1. - numext::abs2(temp / fnorm); - - /* compute the ratio of the actual to the predicted reduction. */ - ratio = 0.; - if (prered > 0.) - ratio = actred / prered; - - /* update the step bound. */ - if (ratio < Scalar(.1)) { - ncsuc = 0; - ++ncfail; - delta = Scalar(.5) * delta; - } else { - ncfail = 0; - ++ncsuc; - if (ratio >= Scalar(.5) || ncsuc > 1) - delta = (std::max)(delta, pnorm / Scalar(.5)); - if (abs(ratio - 1.) <= Scalar(.1)) { - delta = pnorm / Scalar(.5); - } - } - - /* test for successful iteration. */ - if (ratio >= Scalar(1e-4)) { - /* successful iteration. update x, fvec, and their norms. */ - x = wa2; - wa2 = diag.cwiseProduct(x); - fvec = wa4; - xnorm = wa2.stableNorm(); - fnorm = fnorm1; - ++iter; - } - - /* determine the progress of the iteration. */ - ++nslow1; - if (actred >= Scalar(.001)) - nslow1 = 0; - if (jeval) - ++nslow2; - if (actred >= Scalar(.1)) - nslow2 = 0; - - /* test for convergence. */ - if (delta <= parameters.xtol * xnorm || fnorm == 0.) - return HybridNonLinearSolverSpace::RelativeErrorTooSmall; - - /* tests for termination and stringent tolerances. */ - if (nfev >= parameters.maxfev) - return HybridNonLinearSolverSpace::TooManyFunctionEvaluation; - if (Scalar(.1) * (std::max)(Scalar(.1) * delta, pnorm) <= NumTraits<Scalar>::epsilon() * xnorm) - return HybridNonLinearSolverSpace::TolTooSmall; - if (nslow2 == 5) - return HybridNonLinearSolverSpace::NotMakingProgressJacobian; - if (nslow1 == 10) - return HybridNonLinearSolverSpace::NotMakingProgressIterations; - - /* criterion for recalculating jacobian. */ - if (ncfail == 2) - break; // leave inner loop and go for the next outer loop iteration - - /* calculate the rank one modification to the jacobian */ - /* and update qtf if necessary. */ - wa1 = diag.cwiseProduct( diag.cwiseProduct(wa1)/pnorm ); - wa2 = fjac.transpose() * wa4; - if (ratio >= Scalar(1e-4)) - qtf = wa2; - wa2 = (wa2-wa3)/pnorm; - - /* compute the qr factorization of the updated jacobian. */ - internal::r1updt<Scalar>(R, wa1, v_givens, w_givens, wa2, wa3, &sing); - internal::r1mpyq<Scalar>(n, n, fjac.data(), v_givens, w_givens); - internal::r1mpyq<Scalar>(1, n, qtf.data(), v_givens, w_givens); - - jeval = false; - } - return HybridNonLinearSolverSpace::Running; -} - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::solve(FVectorType &x) -{ - HybridNonLinearSolverSpace::Status status = solveInit(x); - if (status==HybridNonLinearSolverSpace::ImproperInputParameters) - return status; - while (status==HybridNonLinearSolverSpace::Running) - status = solveOneStep(x); - return status; -} - - - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::hybrd1( - FVectorType &x, - const Scalar tol - ) -{ - n = x.size(); - - /* check the input parameters for errors. */ - if (n <= 0 || tol < 0.) - return HybridNonLinearSolverSpace::ImproperInputParameters; - - resetParameters(); - parameters.maxfev = 200*(n+1); - parameters.xtol = tol; - - diag.setConstant(n, 1.); - useExternalScaling = true; - return solveNumericalDiff(x); -} - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffInit(FVectorType &x) -{ - n = x.size(); - - if (parameters.nb_of_subdiagonals<0) parameters.nb_of_subdiagonals= n-1; - if (parameters.nb_of_superdiagonals<0) parameters.nb_of_superdiagonals= n-1; - - wa1.resize(n); wa2.resize(n); wa3.resize(n); wa4.resize(n); - qtf.resize(n); - fjac.resize(n, n); - fvec.resize(n); - if (!useExternalScaling) - diag.resize(n); - eigen_assert( (!useExternalScaling || diag.size()==n) && "When useExternalScaling is set, the caller must provide a valid 'diag'"); - - /* Function Body */ - nfev = 0; - njev = 0; - - /* check the input parameters for errors. */ - if (n <= 0 || parameters.xtol < 0. || parameters.maxfev <= 0 || parameters.nb_of_subdiagonals< 0 || parameters.nb_of_superdiagonals< 0 || parameters.factor <= 0. ) - return HybridNonLinearSolverSpace::ImproperInputParameters; - if (useExternalScaling) - for (Index j = 0; j < n; ++j) - if (diag[j] <= 0.) - return HybridNonLinearSolverSpace::ImproperInputParameters; - - /* evaluate the function at the starting point */ - /* and calculate its norm. */ - nfev = 1; - if ( functor(x, fvec) < 0) - return HybridNonLinearSolverSpace::UserAsked; - fnorm = fvec.stableNorm(); - - /* initialize iteration counter and monitors. */ - iter = 1; - ncsuc = 0; - ncfail = 0; - nslow1 = 0; - nslow2 = 0; - - return HybridNonLinearSolverSpace::Running; -} - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffOneStep(FVectorType &x) -{ - using std::sqrt; - using std::abs; - - assert(x.size()==n); // check the caller is not cheating us - - Index j; - std::vector<JacobiRotation<Scalar> > v_givens(n), w_givens(n); - - jeval = true; - if (parameters.nb_of_subdiagonals<0) parameters.nb_of_subdiagonals= n-1; - if (parameters.nb_of_superdiagonals<0) parameters.nb_of_superdiagonals= n-1; - - /* calculate the jacobian matrix. */ - if (internal::fdjac1(functor, x, fvec, fjac, parameters.nb_of_subdiagonals, parameters.nb_of_superdiagonals, parameters.epsfcn) <0) - return HybridNonLinearSolverSpace::UserAsked; - nfev += (std::min)(parameters.nb_of_subdiagonals+parameters.nb_of_superdiagonals+ 1, n); - - wa2 = fjac.colwise().blueNorm(); - - /* on the first iteration and if external scaling is not used, scale according */ - /* to the norms of the columns of the initial jacobian. */ - if (iter == 1) { - if (!useExternalScaling) - for (j = 0; j < n; ++j) - diag[j] = (wa2[j]==0.) ? 1. : wa2[j]; - - /* on the first iteration, calculate the norm of the scaled x */ - /* and initialize the step bound delta. */ - xnorm = diag.cwiseProduct(x).stableNorm(); - delta = parameters.factor * xnorm; - if (delta == 0.) - delta = parameters.factor; - } - - /* compute the qr factorization of the jacobian. */ - HouseholderQR<JacobianType> qrfac(fjac); // no pivoting: - - /* copy the triangular factor of the qr factorization into r. */ - R = qrfac.matrixQR(); - - /* accumulate the orthogonal factor in fjac. */ - fjac = qrfac.householderQ(); - - /* form (q transpose)*fvec and store in qtf. */ - qtf = fjac.transpose() * fvec; - - /* rescale if necessary. */ - if (!useExternalScaling) - diag = diag.cwiseMax(wa2); - - while (true) { - /* determine the direction p. */ - internal::dogleg<Scalar>(R, diag, qtf, delta, wa1); - - /* store the direction p and x + p. calculate the norm of p. */ - wa1 = -wa1; - wa2 = x + wa1; - pnorm = diag.cwiseProduct(wa1).stableNorm(); - - /* on the first iteration, adjust the initial step bound. */ - if (iter == 1) - delta = (std::min)(delta,pnorm); - - /* evaluate the function at x + p and calculate its norm. */ - if ( functor(wa2, wa4) < 0) - return HybridNonLinearSolverSpace::UserAsked; - ++nfev; - fnorm1 = wa4.stableNorm(); - - /* compute the scaled actual reduction. */ - actred = -1.; - if (fnorm1 < fnorm) /* Computing 2nd power */ - actred = 1. - numext::abs2(fnorm1 / fnorm); - - /* compute the scaled predicted reduction. */ - wa3 = R.template triangularView<Upper>()*wa1 + qtf; - temp = wa3.stableNorm(); - prered = 0.; - if (temp < fnorm) /* Computing 2nd power */ - prered = 1. - numext::abs2(temp / fnorm); - - /* compute the ratio of the actual to the predicted reduction. */ - ratio = 0.; - if (prered > 0.) - ratio = actred / prered; - - /* update the step bound. */ - if (ratio < Scalar(.1)) { - ncsuc = 0; - ++ncfail; - delta = Scalar(.5) * delta; - } else { - ncfail = 0; - ++ncsuc; - if (ratio >= Scalar(.5) || ncsuc > 1) - delta = (std::max)(delta, pnorm / Scalar(.5)); - if (abs(ratio - 1.) <= Scalar(.1)) { - delta = pnorm / Scalar(.5); - } - } - - /* test for successful iteration. */ - if (ratio >= Scalar(1e-4)) { - /* successful iteration. update x, fvec, and their norms. */ - x = wa2; - wa2 = diag.cwiseProduct(x); - fvec = wa4; - xnorm = wa2.stableNorm(); - fnorm = fnorm1; - ++iter; - } - - /* determine the progress of the iteration. */ - ++nslow1; - if (actred >= Scalar(.001)) - nslow1 = 0; - if (jeval) - ++nslow2; - if (actred >= Scalar(.1)) - nslow2 = 0; - - /* test for convergence. */ - if (delta <= parameters.xtol * xnorm || fnorm == 0.) - return HybridNonLinearSolverSpace::RelativeErrorTooSmall; - - /* tests for termination and stringent tolerances. */ - if (nfev >= parameters.maxfev) - return HybridNonLinearSolverSpace::TooManyFunctionEvaluation; - if (Scalar(.1) * (std::max)(Scalar(.1) * delta, pnorm) <= NumTraits<Scalar>::epsilon() * xnorm) - return HybridNonLinearSolverSpace::TolTooSmall; - if (nslow2 == 5) - return HybridNonLinearSolverSpace::NotMakingProgressJacobian; - if (nslow1 == 10) - return HybridNonLinearSolverSpace::NotMakingProgressIterations; - - /* criterion for recalculating jacobian. */ - if (ncfail == 2) - break; // leave inner loop and go for the next outer loop iteration - - /* calculate the rank one modification to the jacobian */ - /* and update qtf if necessary. */ - wa1 = diag.cwiseProduct( diag.cwiseProduct(wa1)/pnorm ); - wa2 = fjac.transpose() * wa4; - if (ratio >= Scalar(1e-4)) - qtf = wa2; - wa2 = (wa2-wa3)/pnorm; - - /* compute the qr factorization of the updated jacobian. */ - internal::r1updt<Scalar>(R, wa1, v_givens, w_givens, wa2, wa3, &sing); - internal::r1mpyq<Scalar>(n, n, fjac.data(), v_givens, w_givens); - internal::r1mpyq<Scalar>(1, n, qtf.data(), v_givens, w_givens); - - jeval = false; - } - return HybridNonLinearSolverSpace::Running; -} - -template<typename FunctorType, typename Scalar> -HybridNonLinearSolverSpace::Status -HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiff(FVectorType &x) -{ - HybridNonLinearSolverSpace::Status status = solveNumericalDiffInit(x); - if (status==HybridNonLinearSolverSpace::ImproperInputParameters) - return status; - while (status==HybridNonLinearSolverSpace::Running) - status = solveNumericalDiffOneStep(x); - return status; -} - -} // end namespace Eigen - -#endif // EIGEN_HYBRIDNONLINEARSOLVER_H - -//vim: ai ts=4 sts=4 et sw=4 diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h deleted file mode 100644 index fe3b79c..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h +++ /dev/null @@ -1,657 +0,0 @@ -// -*- coding: utf-8 -// vim: set fileencoding=utf-8 - -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_LEVENBERGMARQUARDT__H -#define EIGEN_LEVENBERGMARQUARDT__H - -namespace Eigen { - -namespace LevenbergMarquardtSpace { - enum Status { - NotStarted = -2, - Running = -1, - ImproperInputParameters = 0, - RelativeReductionTooSmall = 1, - RelativeErrorTooSmall = 2, - RelativeErrorAndReductionTooSmall = 3, - CosinusTooSmall = 4, - TooManyFunctionEvaluation = 5, - FtolTooSmall = 6, - XtolTooSmall = 7, - GtolTooSmall = 8, - UserAsked = 9 - }; -} - - - -/** - * \ingroup NonLinearOptimization_Module - * \brief Performs non linear optimization over a non-linear function, - * using a variant of the Levenberg Marquardt algorithm. - * - * Check wikipedia for more information. - * http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm - */ -template<typename FunctorType, typename Scalar=double> -class LevenbergMarquardt -{ - static Scalar sqrt_epsilon() - { - using std::sqrt; - return sqrt(NumTraits<Scalar>::epsilon()); - } - -public: - LevenbergMarquardt(FunctorType &_functor) - : functor(_functor) { nfev = njev = iter = 0; fnorm = gnorm = 0.; useExternalScaling=false; } - - typedef DenseIndex Index; - - struct Parameters { - Parameters() - : factor(Scalar(100.)) - , maxfev(400) - , ftol(sqrt_epsilon()) - , xtol(sqrt_epsilon()) - , gtol(Scalar(0.)) - , epsfcn(Scalar(0.)) {} - Scalar factor; - Index maxfev; // maximum number of function evaluation - Scalar ftol; - Scalar xtol; - Scalar gtol; - Scalar epsfcn; - }; - - typedef Matrix< Scalar, Dynamic, 1 > FVectorType; - typedef Matrix< Scalar, Dynamic, Dynamic > JacobianType; - - LevenbergMarquardtSpace::Status lmder1( - FVectorType &x, - const Scalar tol = sqrt_epsilon() - ); - - LevenbergMarquardtSpace::Status minimize(FVectorType &x); - LevenbergMarquardtSpace::Status minimizeInit(FVectorType &x); - LevenbergMarquardtSpace::Status minimizeOneStep(FVectorType &x); - - static LevenbergMarquardtSpace::Status lmdif1( - FunctorType &functor, - FVectorType &x, - Index *nfev, - const Scalar tol = sqrt_epsilon() - ); - - LevenbergMarquardtSpace::Status lmstr1( - FVectorType &x, - const Scalar tol = sqrt_epsilon() - ); - - LevenbergMarquardtSpace::Status minimizeOptimumStorage(FVectorType &x); - LevenbergMarquardtSpace::Status minimizeOptimumStorageInit(FVectorType &x); - LevenbergMarquardtSpace::Status minimizeOptimumStorageOneStep(FVectorType &x); - - void resetParameters(void) { parameters = Parameters(); } - - Parameters parameters; - FVectorType fvec, qtf, diag; - JacobianType fjac; - PermutationMatrix<Dynamic,Dynamic> permutation; - Index nfev; - Index njev; - Index iter; - Scalar fnorm, gnorm; - bool useExternalScaling; - - Scalar lm_param(void) { return par; } -private: - - FunctorType &functor; - Index n; - Index m; - FVectorType wa1, wa2, wa3, wa4; - - Scalar par, sum; - Scalar temp, temp1, temp2; - Scalar delta; - Scalar ratio; - Scalar pnorm, xnorm, fnorm1, actred, dirder, prered; - - LevenbergMarquardt& operator=(const LevenbergMarquardt&); -}; - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::lmder1( - FVectorType &x, - const Scalar tol - ) -{ - n = x.size(); - m = functor.values(); - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || tol < 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - resetParameters(); - parameters.ftol = tol; - parameters.xtol = tol; - parameters.maxfev = 100*(n+1); - - return minimize(x); -} - - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::minimize(FVectorType &x) -{ - LevenbergMarquardtSpace::Status status = minimizeInit(x); - if (status==LevenbergMarquardtSpace::ImproperInputParameters) - return status; - do { - status = minimizeOneStep(x); - } while (status==LevenbergMarquardtSpace::Running); - return status; -} - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::minimizeInit(FVectorType &x) -{ - n = x.size(); - m = functor.values(); - - wa1.resize(n); wa2.resize(n); wa3.resize(n); - wa4.resize(m); - fvec.resize(m); - fjac.resize(m, n); - if (!useExternalScaling) - diag.resize(n); - eigen_assert( (!useExternalScaling || diag.size()==n) && "When useExternalScaling is set, the caller must provide a valid 'diag'"); - qtf.resize(n); - - /* Function Body */ - nfev = 0; - njev = 0; - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - if (useExternalScaling) - for (Index j = 0; j < n; ++j) - if (diag[j] <= 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - /* evaluate the function at the starting point */ - /* and calculate its norm. */ - nfev = 1; - if ( functor(x, fvec) < 0) - return LevenbergMarquardtSpace::UserAsked; - fnorm = fvec.stableNorm(); - - /* initialize levenberg-marquardt parameter and iteration counter. */ - par = 0.; - iter = 1; - - return LevenbergMarquardtSpace::NotStarted; -} - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep(FVectorType &x) -{ - using std::abs; - using std::sqrt; - - eigen_assert(x.size()==n); // check the caller is not cheating us - - /* calculate the jacobian matrix. */ - Index df_ret = functor.df(x, fjac); - if (df_ret<0) - return LevenbergMarquardtSpace::UserAsked; - if (df_ret>0) - // numerical diff, we evaluated the function df_ret times - nfev += df_ret; - else njev++; - - /* compute the qr factorization of the jacobian. */ - wa2 = fjac.colwise().blueNorm(); - ColPivHouseholderQR<JacobianType> qrfac(fjac); - fjac = qrfac.matrixQR(); - permutation = qrfac.colsPermutation(); - - /* on the first iteration and if external scaling is not used, scale according */ - /* to the norms of the columns of the initial jacobian. */ - if (iter == 1) { - if (!useExternalScaling) - for (Index j = 0; j < n; ++j) - diag[j] = (wa2[j]==0.)? 1. : wa2[j]; - - /* on the first iteration, calculate the norm of the scaled x */ - /* and initialize the step bound delta. */ - xnorm = diag.cwiseProduct(x).stableNorm(); - delta = parameters.factor * xnorm; - if (delta == 0.) - delta = parameters.factor; - } - - /* form (q transpose)*fvec and store the first n components in */ - /* qtf. */ - wa4 = fvec; - wa4.applyOnTheLeft(qrfac.householderQ().adjoint()); - qtf = wa4.head(n); - - /* compute the norm of the scaled gradient. */ - gnorm = 0.; - if (fnorm != 0.) - for (Index j = 0; j < n; ++j) - if (wa2[permutation.indices()[j]] != 0.) - gnorm = (std::max)(gnorm, abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]])); - - /* test for convergence of the gradient norm. */ - if (gnorm <= parameters.gtol) - return LevenbergMarquardtSpace::CosinusTooSmall; - - /* rescale if necessary. */ - if (!useExternalScaling) - diag = diag.cwiseMax(wa2); - - do { - - /* determine the levenberg-marquardt parameter. */ - internal::lmpar2<Scalar>(qrfac, diag, qtf, delta, par, wa1); - - /* store the direction p and x + p. calculate the norm of p. */ - wa1 = -wa1; - wa2 = x + wa1; - pnorm = diag.cwiseProduct(wa1).stableNorm(); - - /* on the first iteration, adjust the initial step bound. */ - if (iter == 1) - delta = (std::min)(delta,pnorm); - - /* evaluate the function at x + p and calculate its norm. */ - if ( functor(wa2, wa4) < 0) - return LevenbergMarquardtSpace::UserAsked; - ++nfev; - fnorm1 = wa4.stableNorm(); - - /* compute the scaled actual reduction. */ - actred = -1.; - if (Scalar(.1) * fnorm1 < fnorm) - actred = 1. - numext::abs2(fnorm1 / fnorm); - - /* compute the scaled predicted reduction and */ - /* the scaled directional derivative. */ - wa3 = fjac.template triangularView<Upper>() * (qrfac.colsPermutation().inverse() *wa1); - temp1 = numext::abs2(wa3.stableNorm() / fnorm); - temp2 = numext::abs2(sqrt(par) * pnorm / fnorm); - prered = temp1 + temp2 / Scalar(.5); - dirder = -(temp1 + temp2); - - /* compute the ratio of the actual to the predicted */ - /* reduction. */ - ratio = 0.; - if (prered != 0.) - ratio = actred / prered; - - /* update the step bound. */ - if (ratio <= Scalar(.25)) { - if (actred >= 0.) - temp = Scalar(.5); - if (actred < 0.) - temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred); - if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1)) - temp = Scalar(.1); - /* Computing MIN */ - delta = temp * (std::min)(delta, pnorm / Scalar(.1)); - par /= temp; - } else if (!(par != 0. && ratio < Scalar(.75))) { - delta = pnorm / Scalar(.5); - par = Scalar(.5) * par; - } - - /* test for successful iteration. */ - if (ratio >= Scalar(1e-4)) { - /* successful iteration. update x, fvec, and their norms. */ - x = wa2; - wa2 = diag.cwiseProduct(x); - fvec = wa4; - xnorm = wa2.stableNorm(); - fnorm = fnorm1; - ++iter; - } - - /* tests for convergence. */ - if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm) - return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall; - if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.) - return LevenbergMarquardtSpace::RelativeReductionTooSmall; - if (delta <= parameters.xtol * xnorm) - return LevenbergMarquardtSpace::RelativeErrorTooSmall; - - /* tests for termination and stringent tolerances. */ - if (nfev >= parameters.maxfev) - return LevenbergMarquardtSpace::TooManyFunctionEvaluation; - if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.) - return LevenbergMarquardtSpace::FtolTooSmall; - if (delta <= NumTraits<Scalar>::epsilon() * xnorm) - return LevenbergMarquardtSpace::XtolTooSmall; - if (gnorm <= NumTraits<Scalar>::epsilon()) - return LevenbergMarquardtSpace::GtolTooSmall; - - } while (ratio < Scalar(1e-4)); - - return LevenbergMarquardtSpace::Running; -} - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::lmstr1( - FVectorType &x, - const Scalar tol - ) -{ - n = x.size(); - m = functor.values(); - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || tol < 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - resetParameters(); - parameters.ftol = tol; - parameters.xtol = tol; - parameters.maxfev = 100*(n+1); - - return minimizeOptimumStorage(x); -} - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageInit(FVectorType &x) -{ - n = x.size(); - m = functor.values(); - - wa1.resize(n); wa2.resize(n); wa3.resize(n); - wa4.resize(m); - fvec.resize(m); - // Only R is stored in fjac. Q is only used to compute 'qtf', which is - // Q.transpose()*rhs. qtf will be updated using givens rotation, - // instead of storing them in Q. - // The purpose it to only use a nxn matrix, instead of mxn here, so - // that we can handle cases where m>>n : - fjac.resize(n, n); - if (!useExternalScaling) - diag.resize(n); - eigen_assert( (!useExternalScaling || diag.size()==n) && "When useExternalScaling is set, the caller must provide a valid 'diag'"); - qtf.resize(n); - - /* Function Body */ - nfev = 0; - njev = 0; - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || parameters.ftol < 0. || parameters.xtol < 0. || parameters.gtol < 0. || parameters.maxfev <= 0 || parameters.factor <= 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - if (useExternalScaling) - for (Index j = 0; j < n; ++j) - if (diag[j] <= 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - /* evaluate the function at the starting point */ - /* and calculate its norm. */ - nfev = 1; - if ( functor(x, fvec) < 0) - return LevenbergMarquardtSpace::UserAsked; - fnorm = fvec.stableNorm(); - - /* initialize levenberg-marquardt parameter and iteration counter. */ - par = 0.; - iter = 1; - - return LevenbergMarquardtSpace::NotStarted; -} - - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep(FVectorType &x) -{ - using std::abs; - using std::sqrt; - - eigen_assert(x.size()==n); // check the caller is not cheating us - - Index i, j; - bool sing; - - /* compute the qr factorization of the jacobian matrix */ - /* calculated one row at a time, while simultaneously */ - /* forming (q transpose)*fvec and storing the first */ - /* n components in qtf. */ - qtf.fill(0.); - fjac.fill(0.); - Index rownb = 2; - for (i = 0; i < m; ++i) { - if (functor.df(x, wa3, rownb) < 0) return LevenbergMarquardtSpace::UserAsked; - internal::rwupdt<Scalar>(fjac, wa3, qtf, fvec[i]); - ++rownb; - } - ++njev; - - /* if the jacobian is rank deficient, call qrfac to */ - /* reorder its columns and update the components of qtf. */ - sing = false; - for (j = 0; j < n; ++j) { - if (fjac(j,j) == 0.) - sing = true; - wa2[j] = fjac.col(j).head(j).stableNorm(); - } - permutation.setIdentity(n); - if (sing) { - wa2 = fjac.colwise().blueNorm(); - // TODO We have no unit test covering this code path, do not modify - // until it is carefully tested - ColPivHouseholderQR<JacobianType> qrfac(fjac); - fjac = qrfac.matrixQR(); - wa1 = fjac.diagonal(); - fjac.diagonal() = qrfac.hCoeffs(); - permutation = qrfac.colsPermutation(); - // TODO : avoid this: - for(Index ii=0; ii< fjac.cols(); ii++) fjac.col(ii).segment(ii+1, fjac.rows()-ii-1) *= fjac(ii,ii); // rescale vectors - - for (j = 0; j < n; ++j) { - if (fjac(j,j) != 0.) { - sum = 0.; - for (i = j; i < n; ++i) - sum += fjac(i,j) * qtf[i]; - temp = -sum / fjac(j,j); - for (i = j; i < n; ++i) - qtf[i] += fjac(i,j) * temp; - } - fjac(j,j) = wa1[j]; - } - } - - /* on the first iteration and if external scaling is not used, scale according */ - /* to the norms of the columns of the initial jacobian. */ - if (iter == 1) { - if (!useExternalScaling) - for (j = 0; j < n; ++j) - diag[j] = (wa2[j]==0.)? 1. : wa2[j]; - - /* on the first iteration, calculate the norm of the scaled x */ - /* and initialize the step bound delta. */ - xnorm = diag.cwiseProduct(x).stableNorm(); - delta = parameters.factor * xnorm; - if (delta == 0.) - delta = parameters.factor; - } - - /* compute the norm of the scaled gradient. */ - gnorm = 0.; - if (fnorm != 0.) - for (j = 0; j < n; ++j) - if (wa2[permutation.indices()[j]] != 0.) - gnorm = (std::max)(gnorm, abs( fjac.col(j).head(j+1).dot(qtf.head(j+1)/fnorm) / wa2[permutation.indices()[j]])); - - /* test for convergence of the gradient norm. */ - if (gnorm <= parameters.gtol) - return LevenbergMarquardtSpace::CosinusTooSmall; - - /* rescale if necessary. */ - if (!useExternalScaling) - diag = diag.cwiseMax(wa2); - - do { - - /* determine the levenberg-marquardt parameter. */ - internal::lmpar<Scalar>(fjac, permutation.indices(), diag, qtf, delta, par, wa1); - - /* store the direction p and x + p. calculate the norm of p. */ - wa1 = -wa1; - wa2 = x + wa1; - pnorm = diag.cwiseProduct(wa1).stableNorm(); - - /* on the first iteration, adjust the initial step bound. */ - if (iter == 1) - delta = (std::min)(delta,pnorm); - - /* evaluate the function at x + p and calculate its norm. */ - if ( functor(wa2, wa4) < 0) - return LevenbergMarquardtSpace::UserAsked; - ++nfev; - fnorm1 = wa4.stableNorm(); - - /* compute the scaled actual reduction. */ - actred = -1.; - if (Scalar(.1) * fnorm1 < fnorm) - actred = 1. - numext::abs2(fnorm1 / fnorm); - - /* compute the scaled predicted reduction and */ - /* the scaled directional derivative. */ - wa3 = fjac.topLeftCorner(n,n).template triangularView<Upper>() * (permutation.inverse() * wa1); - temp1 = numext::abs2(wa3.stableNorm() / fnorm); - temp2 = numext::abs2(sqrt(par) * pnorm / fnorm); - prered = temp1 + temp2 / Scalar(.5); - dirder = -(temp1 + temp2); - - /* compute the ratio of the actual to the predicted */ - /* reduction. */ - ratio = 0.; - if (prered != 0.) - ratio = actred / prered; - - /* update the step bound. */ - if (ratio <= Scalar(.25)) { - if (actred >= 0.) - temp = Scalar(.5); - if (actred < 0.) - temp = Scalar(.5) * dirder / (dirder + Scalar(.5) * actred); - if (Scalar(.1) * fnorm1 >= fnorm || temp < Scalar(.1)) - temp = Scalar(.1); - /* Computing MIN */ - delta = temp * (std::min)(delta, pnorm / Scalar(.1)); - par /= temp; - } else if (!(par != 0. && ratio < Scalar(.75))) { - delta = pnorm / Scalar(.5); - par = Scalar(.5) * par; - } - - /* test for successful iteration. */ - if (ratio >= Scalar(1e-4)) { - /* successful iteration. update x, fvec, and their norms. */ - x = wa2; - wa2 = diag.cwiseProduct(x); - fvec = wa4; - xnorm = wa2.stableNorm(); - fnorm = fnorm1; - ++iter; - } - - /* tests for convergence. */ - if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1. && delta <= parameters.xtol * xnorm) - return LevenbergMarquardtSpace::RelativeErrorAndReductionTooSmall; - if (abs(actred) <= parameters.ftol && prered <= parameters.ftol && Scalar(.5) * ratio <= 1.) - return LevenbergMarquardtSpace::RelativeReductionTooSmall; - if (delta <= parameters.xtol * xnorm) - return LevenbergMarquardtSpace::RelativeErrorTooSmall; - - /* tests for termination and stringent tolerances. */ - if (nfev >= parameters.maxfev) - return LevenbergMarquardtSpace::TooManyFunctionEvaluation; - if (abs(actred) <= NumTraits<Scalar>::epsilon() && prered <= NumTraits<Scalar>::epsilon() && Scalar(.5) * ratio <= 1.) - return LevenbergMarquardtSpace::FtolTooSmall; - if (delta <= NumTraits<Scalar>::epsilon() * xnorm) - return LevenbergMarquardtSpace::XtolTooSmall; - if (gnorm <= NumTraits<Scalar>::epsilon()) - return LevenbergMarquardtSpace::GtolTooSmall; - - } while (ratio < Scalar(1e-4)); - - return LevenbergMarquardtSpace::Running; -} - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorage(FVectorType &x) -{ - LevenbergMarquardtSpace::Status status = minimizeOptimumStorageInit(x); - if (status==LevenbergMarquardtSpace::ImproperInputParameters) - return status; - do { - status = minimizeOptimumStorageOneStep(x); - } while (status==LevenbergMarquardtSpace::Running); - return status; -} - -template<typename FunctorType, typename Scalar> -LevenbergMarquardtSpace::Status -LevenbergMarquardt<FunctorType,Scalar>::lmdif1( - FunctorType &functor, - FVectorType &x, - Index *nfev, - const Scalar tol - ) -{ - Index n = x.size(); - Index m = functor.values(); - - /* check the input parameters for errors. */ - if (n <= 0 || m < n || tol < 0.) - return LevenbergMarquardtSpace::ImproperInputParameters; - - NumericalDiff<FunctorType> numDiff(functor); - // embedded LevenbergMarquardt - LevenbergMarquardt<NumericalDiff<FunctorType>, Scalar > lm(numDiff); - lm.parameters.ftol = tol; - lm.parameters.xtol = tol; - lm.parameters.maxfev = 200*(n+1); - - LevenbergMarquardtSpace::Status info = LevenbergMarquardtSpace::Status(lm.minimize(x)); - if (nfev) - * nfev = lm.nfev; - return info; -} - -} // end namespace Eigen - -#endif // EIGEN_LEVENBERGMARQUARDT__H - -//vim: ai ts=4 sts=4 et sw=4 diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/chkder.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/chkder.h deleted file mode 100644 index db8ff7d..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/chkder.h +++ /dev/null @@ -1,66 +0,0 @@ -#define chkder_log10e 0.43429448190325182765 -#define chkder_factor 100. - -namespace Eigen { - -namespace internal { - -template<typename Scalar> -void chkder( - const Matrix< Scalar, Dynamic, 1 > &x, - const Matrix< Scalar, Dynamic, 1 > &fvec, - const Matrix< Scalar, Dynamic, Dynamic > &fjac, - Matrix< Scalar, Dynamic, 1 > &xp, - const Matrix< Scalar, Dynamic, 1 > &fvecp, - int mode, - Matrix< Scalar, Dynamic, 1 > &err - ) -{ - using std::sqrt; - using std::abs; - using std::log; - - typedef DenseIndex Index; - - const Scalar eps = sqrt(NumTraits<Scalar>::epsilon()); - const Scalar epsf = chkder_factor * NumTraits<Scalar>::epsilon(); - const Scalar epslog = chkder_log10e * log(eps); - Scalar temp; - - const Index m = fvec.size(), n = x.size(); - - if (mode != 2) { - /* mode = 1. */ - xp.resize(n); - for (Index j = 0; j < n; ++j) { - temp = eps * abs(x[j]); - if (temp == 0.) - temp = eps; - xp[j] = x[j] + temp; - } - } - else { - /* mode = 2. */ - err.setZero(m); - for (Index j = 0; j < n; ++j) { - temp = abs(x[j]); - if (temp == 0.) - temp = 1.; - err += temp * fjac.col(j); - } - for (Index i = 0; i < m; ++i) { - temp = 1.; - if (fvec[i] != 0. && fvecp[i] != 0. && abs(fvecp[i] - fvec[i]) >= epsf * abs(fvec[i])) - temp = eps * abs((fvecp[i] - fvec[i]) / eps - err[i]) / (abs(fvec[i]) + abs(fvecp[i])); - err[i] = 1.; - if (temp > NumTraits<Scalar>::epsilon() && temp < eps) - err[i] = (chkder_log10e * log(temp) - epslog) / epslog; - if (temp >= eps) - err[i] = 0.; - } - } -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/covar.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/covar.h deleted file mode 100644 index 68260d1..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/covar.h +++ /dev/null @@ -1,70 +0,0 @@ -namespace Eigen { - -namespace internal { - -template <typename Scalar> -void covar( - Matrix< Scalar, Dynamic, Dynamic > &r, - const VectorXi &ipvt, - Scalar tol = std::sqrt(NumTraits<Scalar>::epsilon()) ) -{ - using std::abs; - typedef DenseIndex Index; - - /* Local variables */ - Index i, j, k, l, ii, jj; - bool sing; - Scalar temp; - - /* Function Body */ - const Index n = r.cols(); - const Scalar tolr = tol * abs(r(0,0)); - Matrix< Scalar, Dynamic, 1 > wa(n); - eigen_assert(ipvt.size()==n); - - /* form the inverse of r in the full upper triangle of r. */ - l = -1; - for (k = 0; k < n; ++k) - if (abs(r(k,k)) > tolr) { - r(k,k) = 1. / r(k,k); - for (j = 0; j <= k-1; ++j) { - temp = r(k,k) * r(j,k); - r(j,k) = 0.; - r.col(k).head(j+1) -= r.col(j).head(j+1) * temp; - } - l = k; - } - - /* form the full upper triangle of the inverse of (r transpose)*r */ - /* in the full upper triangle of r. */ - for (k = 0; k <= l; ++k) { - for (j = 0; j <= k-1; ++j) - r.col(j).head(j+1) += r.col(k).head(j+1) * r(j,k); - r.col(k).head(k+1) *= r(k,k); - } - - /* form the full lower triangle of the covariance matrix */ - /* in the strict lower triangle of r and in wa. */ - for (j = 0; j < n; ++j) { - jj = ipvt[j]; - sing = j > l; - for (i = 0; i <= j; ++i) { - if (sing) - r(i,j) = 0.; - ii = ipvt[i]; - if (ii > jj) - r(ii,jj) = r(i,j); - if (ii < jj) - r(jj,ii) = r(i,j); - } - wa[jj] = r(j,j); - } - - /* symmetrize the covariance matrix in r. */ - r.topLeftCorner(n,n).template triangularView<StrictlyUpper>() = r.topLeftCorner(n,n).transpose(); - r.diagonal() = wa; -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/dogleg.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/dogleg.h deleted file mode 100644 index 80c5d27..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/dogleg.h +++ /dev/null @@ -1,107 +0,0 @@ -namespace Eigen { - -namespace internal { - -template <typename Scalar> -void dogleg( - const Matrix< Scalar, Dynamic, Dynamic > &qrfac, - const Matrix< Scalar, Dynamic, 1 > &diag, - const Matrix< Scalar, Dynamic, 1 > &qtb, - Scalar delta, - Matrix< Scalar, Dynamic, 1 > &x) -{ - using std::abs; - using std::sqrt; - - typedef DenseIndex Index; - - /* Local variables */ - Index i, j; - Scalar sum, temp, alpha, bnorm; - Scalar gnorm, qnorm; - Scalar sgnorm; - - /* Function Body */ - const Scalar epsmch = NumTraits<Scalar>::epsilon(); - const Index n = qrfac.cols(); - eigen_assert(n==qtb.size()); - eigen_assert(n==x.size()); - eigen_assert(n==diag.size()); - Matrix< Scalar, Dynamic, 1 > wa1(n), wa2(n); - - /* first, calculate the gauss-newton direction. */ - for (j = n-1; j >=0; --j) { - temp = qrfac(j,j); - if (temp == 0.) { - temp = epsmch * qrfac.col(j).head(j+1).maxCoeff(); - if (temp == 0.) - temp = epsmch; - } - if (j==n-1) - x[j] = qtb[j] / temp; - else - x[j] = (qtb[j] - qrfac.row(j).tail(n-j-1).dot(x.tail(n-j-1))) / temp; - } - - /* test whether the gauss-newton direction is acceptable. */ - qnorm = diag.cwiseProduct(x).stableNorm(); - if (qnorm <= delta) - return; - - // TODO : this path is not tested by Eigen unit tests - - /* the gauss-newton direction is not acceptable. */ - /* next, calculate the scaled gradient direction. */ - - wa1.fill(0.); - for (j = 0; j < n; ++j) { - wa1.tail(n-j) += qrfac.row(j).tail(n-j) * qtb[j]; - wa1[j] /= diag[j]; - } - - /* calculate the norm of the scaled gradient and test for */ - /* the special case in which the scaled gradient is zero. */ - gnorm = wa1.stableNorm(); - sgnorm = 0.; - alpha = delta / qnorm; - if (gnorm == 0.) - goto algo_end; - - /* calculate the point along the scaled gradient */ - /* at which the quadratic is minimized. */ - wa1.array() /= (diag*gnorm).array(); - // TODO : once unit tests cover this part,: - // wa2 = qrfac.template triangularView<Upper>() * wa1; - for (j = 0; j < n; ++j) { - sum = 0.; - for (i = j; i < n; ++i) { - sum += qrfac(j,i) * wa1[i]; - } - wa2[j] = sum; - } - temp = wa2.stableNorm(); - sgnorm = gnorm / temp / temp; - - /* test whether the scaled gradient direction is acceptable. */ - alpha = 0.; - if (sgnorm >= delta) - goto algo_end; - - /* the scaled gradient direction is not acceptable. */ - /* finally, calculate the point along the dogleg */ - /* at which the quadratic is minimized. */ - bnorm = qtb.stableNorm(); - temp = bnorm / gnorm * (bnorm / qnorm) * (sgnorm / delta); - temp = temp - delta / qnorm * numext::abs2(sgnorm / delta) + sqrt(numext::abs2(temp - delta / qnorm) + (1.-numext::abs2(delta / qnorm)) * (1.-numext::abs2(sgnorm / delta))); - alpha = delta / qnorm * (1. - numext::abs2(sgnorm / delta)) / temp; -algo_end: - - /* form appropriate convex combination of the gauss-newton */ - /* direction and the scaled gradient direction. */ - temp = (1.-alpha) * (std::min)(sgnorm,delta); - x = temp * wa1 + alpha * x; -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h deleted file mode 100644 index bb7cf26..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/fdjac1.h +++ /dev/null @@ -1,79 +0,0 @@ -namespace Eigen { - -namespace internal { - -template<typename FunctorType, typename Scalar> -DenseIndex fdjac1( - const FunctorType &Functor, - Matrix< Scalar, Dynamic, 1 > &x, - Matrix< Scalar, Dynamic, 1 > &fvec, - Matrix< Scalar, Dynamic, Dynamic > &fjac, - DenseIndex ml, DenseIndex mu, - Scalar epsfcn) -{ - using std::sqrt; - using std::abs; - - typedef DenseIndex Index; - - /* Local variables */ - Scalar h; - Index j, k; - Scalar eps, temp; - Index msum; - int iflag; - Index start, length; - - /* Function Body */ - const Scalar epsmch = NumTraits<Scalar>::epsilon(); - const Index n = x.size(); - eigen_assert(fvec.size()==n); - Matrix< Scalar, Dynamic, 1 > wa1(n); - Matrix< Scalar, Dynamic, 1 > wa2(n); - - eps = sqrt((std::max)(epsfcn,epsmch)); - msum = ml + mu + 1; - if (msum >= n) { - /* computation of dense approximate jacobian. */ - for (j = 0; j < n; ++j) { - temp = x[j]; - h = eps * abs(temp); - if (h == 0.) - h = eps; - x[j] = temp + h; - iflag = Functor(x, wa1); - if (iflag < 0) - return iflag; - x[j] = temp; - fjac.col(j) = (wa1-fvec)/h; - } - - }else { - /* computation of banded approximate jacobian. */ - for (k = 0; k < msum; ++k) { - for (j = k; (msum<0) ? (j>n): (j<n); j += msum) { - wa2[j] = x[j]; - h = eps * abs(wa2[j]); - if (h == 0.) h = eps; - x[j] = wa2[j] + h; - } - iflag = Functor(x, wa1); - if (iflag < 0) - return iflag; - for (j = k; (msum<0) ? (j>n): (j<n); j += msum) { - x[j] = wa2[j]; - h = eps * abs(wa2[j]); - if (h == 0.) h = eps; - fjac.col(j).setZero(); - start = std::max<Index>(0,j-mu); - length = (std::min)(n-1, j+ml) - start + 1; - fjac.col(j).segment(start, length) = ( wa1.segment(start, length)-fvec.segment(start, length))/h; - } - } - } - return 0; -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/lmpar.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/lmpar.h deleted file mode 100644 index 4c17d4c..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/lmpar.h +++ /dev/null @@ -1,298 +0,0 @@ -namespace Eigen { - -namespace internal { - -template <typename Scalar> -void lmpar( - Matrix< Scalar, Dynamic, Dynamic > &r, - const VectorXi &ipvt, - const Matrix< Scalar, Dynamic, 1 > &diag, - const Matrix< Scalar, Dynamic, 1 > &qtb, - Scalar delta, - Scalar &par, - Matrix< Scalar, Dynamic, 1 > &x) -{ - using std::abs; - using std::sqrt; - typedef DenseIndex Index; - - /* Local variables */ - Index i, j, l; - Scalar fp; - Scalar parc, parl; - Index iter; - Scalar temp, paru; - Scalar gnorm; - Scalar dxnorm; - - - /* Function Body */ - const Scalar dwarf = (std::numeric_limits<Scalar>::min)(); - const Index n = r.cols(); - eigen_assert(n==diag.size()); - eigen_assert(n==qtb.size()); - eigen_assert(n==x.size()); - - Matrix< Scalar, Dynamic, 1 > wa1, wa2; - - /* compute and store in x the gauss-newton direction. if the */ - /* jacobian is rank-deficient, obtain a least squares solution. */ - Index nsing = n-1; - wa1 = qtb; - for (j = 0; j < n; ++j) { - if (r(j,j) == 0. && nsing == n-1) - nsing = j - 1; - if (nsing < n-1) - wa1[j] = 0.; - } - for (j = nsing; j>=0; --j) { - wa1[j] /= r(j,j); - temp = wa1[j]; - for (i = 0; i < j ; ++i) - wa1[i] -= r(i,j) * temp; - } - - for (j = 0; j < n; ++j) - x[ipvt[j]] = wa1[j]; - - /* initialize the iteration counter. */ - /* evaluate the function at the origin, and test */ - /* for acceptance of the gauss-newton direction. */ - iter = 0; - wa2 = diag.cwiseProduct(x); - dxnorm = wa2.blueNorm(); - fp = dxnorm - delta; - if (fp <= Scalar(0.1) * delta) { - par = 0; - return; - } - - /* if the jacobian is not rank deficient, the newton */ - /* step provides a lower bound, parl, for the zero of */ - /* the function. otherwise set this bound to zero. */ - parl = 0.; - if (nsing >= n-1) { - for (j = 0; j < n; ++j) { - l = ipvt[j]; - wa1[j] = diag[l] * (wa2[l] / dxnorm); - } - // it's actually a triangularView.solveInplace(), though in a weird - // way: - for (j = 0; j < n; ++j) { - Scalar sum = 0.; - for (i = 0; i < j; ++i) - sum += r(i,j) * wa1[i]; - wa1[j] = (wa1[j] - sum) / r(j,j); - } - temp = wa1.blueNorm(); - parl = fp / delta / temp / temp; - } - - /* calculate an upper bound, paru, for the zero of the function. */ - for (j = 0; j < n; ++j) - wa1[j] = r.col(j).head(j+1).dot(qtb.head(j+1)) / diag[ipvt[j]]; - - gnorm = wa1.stableNorm(); - paru = gnorm / delta; - if (paru == 0.) - paru = dwarf / (std::min)(delta,Scalar(0.1)); - - /* if the input par lies outside of the interval (parl,paru), */ - /* set par to the closer endpoint. */ - par = (std::max)(par,parl); - par = (std::min)(par,paru); - if (par == 0.) - par = gnorm / dxnorm; - - /* beginning of an iteration. */ - while (true) { - ++iter; - - /* evaluate the function at the current value of par. */ - if (par == 0.) - par = (std::max)(dwarf,Scalar(.001) * paru); /* Computing MAX */ - wa1 = sqrt(par)* diag; - - Matrix< Scalar, Dynamic, 1 > sdiag(n); - qrsolv<Scalar>(r, ipvt, wa1, qtb, x, sdiag); - - wa2 = diag.cwiseProduct(x); - dxnorm = wa2.blueNorm(); - temp = fp; - fp = dxnorm - delta; - - /* if the function is small enough, accept the current value */ - /* of par. also test for the exceptional cases where parl */ - /* is zero or the number of iterations has reached 10. */ - if (abs(fp) <= Scalar(0.1) * delta || (parl == 0. && fp <= temp && temp < 0.) || iter == 10) - break; - - /* compute the newton correction. */ - for (j = 0; j < n; ++j) { - l = ipvt[j]; - wa1[j] = diag[l] * (wa2[l] / dxnorm); - } - for (j = 0; j < n; ++j) { - wa1[j] /= sdiag[j]; - temp = wa1[j]; - for (i = j+1; i < n; ++i) - wa1[i] -= r(i,j) * temp; - } - temp = wa1.blueNorm(); - parc = fp / delta / temp / temp; - - /* depending on the sign of the function, update parl or paru. */ - if (fp > 0.) - parl = (std::max)(parl,par); - if (fp < 0.) - paru = (std::min)(paru,par); - - /* compute an improved estimate for par. */ - /* Computing MAX */ - par = (std::max)(parl,par+parc); - - /* end of an iteration. */ - } - - /* termination. */ - if (iter == 0) - par = 0.; - return; -} - -template <typename Scalar> -void lmpar2( - const ColPivHouseholderQR<Matrix< Scalar, Dynamic, Dynamic> > &qr, - const Matrix< Scalar, Dynamic, 1 > &diag, - const Matrix< Scalar, Dynamic, 1 > &qtb, - Scalar delta, - Scalar &par, - Matrix< Scalar, Dynamic, 1 > &x) - -{ - using std::sqrt; - using std::abs; - typedef DenseIndex Index; - - /* Local variables */ - Index j; - Scalar fp; - Scalar parc, parl; - Index iter; - Scalar temp, paru; - Scalar gnorm; - Scalar dxnorm; - - - /* Function Body */ - const Scalar dwarf = (std::numeric_limits<Scalar>::min)(); - const Index n = qr.matrixQR().cols(); - eigen_assert(n==diag.size()); - eigen_assert(n==qtb.size()); - - Matrix< Scalar, Dynamic, 1 > wa1, wa2; - - /* compute and store in x the gauss-newton direction. if the */ - /* jacobian is rank-deficient, obtain a least squares solution. */ - -// const Index rank = qr.nonzeroPivots(); // exactly double(0.) - const Index rank = qr.rank(); // use a threshold - wa1 = qtb; - wa1.tail(n-rank).setZero(); - qr.matrixQR().topLeftCorner(rank, rank).template triangularView<Upper>().solveInPlace(wa1.head(rank)); - - x = qr.colsPermutation()*wa1; - - /* initialize the iteration counter. */ - /* evaluate the function at the origin, and test */ - /* for acceptance of the gauss-newton direction. */ - iter = 0; - wa2 = diag.cwiseProduct(x); - dxnorm = wa2.blueNorm(); - fp = dxnorm - delta; - if (fp <= Scalar(0.1) * delta) { - par = 0; - return; - } - - /* if the jacobian is not rank deficient, the newton */ - /* step provides a lower bound, parl, for the zero of */ - /* the function. otherwise set this bound to zero. */ - parl = 0.; - if (rank==n) { - wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2)/dxnorm; - qr.matrixQR().topLeftCorner(n, n).transpose().template triangularView<Lower>().solveInPlace(wa1); - temp = wa1.blueNorm(); - parl = fp / delta / temp / temp; - } - - /* calculate an upper bound, paru, for the zero of the function. */ - for (j = 0; j < n; ++j) - wa1[j] = qr.matrixQR().col(j).head(j+1).dot(qtb.head(j+1)) / diag[qr.colsPermutation().indices()(j)]; - - gnorm = wa1.stableNorm(); - paru = gnorm / delta; - if (paru == 0.) - paru = dwarf / (std::min)(delta,Scalar(0.1)); - - /* if the input par lies outside of the interval (parl,paru), */ - /* set par to the closer endpoint. */ - par = (std::max)(par,parl); - par = (std::min)(par,paru); - if (par == 0.) - par = gnorm / dxnorm; - - /* beginning of an iteration. */ - Matrix< Scalar, Dynamic, Dynamic > s = qr.matrixQR(); - while (true) { - ++iter; - - /* evaluate the function at the current value of par. */ - if (par == 0.) - par = (std::max)(dwarf,Scalar(.001) * paru); /* Computing MAX */ - wa1 = sqrt(par)* diag; - - Matrix< Scalar, Dynamic, 1 > sdiag(n); - qrsolv<Scalar>(s, qr.colsPermutation().indices(), wa1, qtb, x, sdiag); - - wa2 = diag.cwiseProduct(x); - dxnorm = wa2.blueNorm(); - temp = fp; - fp = dxnorm - delta; - - /* if the function is small enough, accept the current value */ - /* of par. also test for the exceptional cases where parl */ - /* is zero or the number of iterations has reached 10. */ - if (abs(fp) <= Scalar(0.1) * delta || (parl == 0. && fp <= temp && temp < 0.) || iter == 10) - break; - - /* compute the newton correction. */ - wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2/dxnorm); - // we could almost use this here, but the diagonal is outside qr, in sdiag[] - // qr.matrixQR().topLeftCorner(n, n).transpose().template triangularView<Lower>().solveInPlace(wa1); - for (j = 0; j < n; ++j) { - wa1[j] /= sdiag[j]; - temp = wa1[j]; - for (Index i = j+1; i < n; ++i) - wa1[i] -= s(i,j) * temp; - } - temp = wa1.blueNorm(); - parc = fp / delta / temp / temp; - - /* depending on the sign of the function, update parl or paru. */ - if (fp > 0.) - parl = (std::max)(parl,par); - if (fp < 0.) - paru = (std::min)(paru,par); - - /* compute an improved estimate for par. */ - par = (std::max)(parl,par+parc); - } - if (iter == 0) - par = 0.; - return; -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h deleted file mode 100644 index feafd62..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h +++ /dev/null @@ -1,91 +0,0 @@ -namespace Eigen { - -namespace internal { - -// TODO : once qrsolv2 is removed, use ColPivHouseholderQR or PermutationMatrix instead of ipvt -template <typename Scalar> -void qrsolv( - Matrix< Scalar, Dynamic, Dynamic > &s, - // TODO : use a PermutationMatrix once lmpar is no more: - const VectorXi &ipvt, - const Matrix< Scalar, Dynamic, 1 > &diag, - const Matrix< Scalar, Dynamic, 1 > &qtb, - Matrix< Scalar, Dynamic, 1 > &x, - Matrix< Scalar, Dynamic, 1 > &sdiag) - -{ - typedef DenseIndex Index; - - /* Local variables */ - Index i, j, k, l; - Scalar temp; - Index n = s.cols(); - Matrix< Scalar, Dynamic, 1 > wa(n); - JacobiRotation<Scalar> givens; - - /* Function Body */ - // the following will only change the lower triangular part of s, including - // the diagonal, though the diagonal is restored afterward - - /* copy r and (q transpose)*b to preserve input and initialize s. */ - /* in particular, save the diagonal elements of r in x. */ - x = s.diagonal(); - wa = qtb; - - s.topLeftCorner(n,n).template triangularView<StrictlyLower>() = s.topLeftCorner(n,n).transpose(); - - /* eliminate the diagonal matrix d using a givens rotation. */ - for (j = 0; j < n; ++j) { - - /* prepare the row of d to be eliminated, locating the */ - /* diagonal element using p from the qr factorization. */ - l = ipvt[j]; - if (diag[l] == 0.) - break; - sdiag.tail(n-j).setZero(); - sdiag[j] = diag[l]; - - /* the transformations to eliminate the row of d */ - /* modify only a single element of (q transpose)*b */ - /* beyond the first n, which is initially zero. */ - Scalar qtbpj = 0.; - for (k = j; k < n; ++k) { - /* determine a givens rotation which eliminates the */ - /* appropriate element in the current row of d. */ - givens.makeGivens(-s(k,k), sdiag[k]); - - /* compute the modified diagonal element of r and */ - /* the modified element of ((q transpose)*b,0). */ - s(k,k) = givens.c() * s(k,k) + givens.s() * sdiag[k]; - temp = givens.c() * wa[k] + givens.s() * qtbpj; - qtbpj = -givens.s() * wa[k] + givens.c() * qtbpj; - wa[k] = temp; - - /* accumulate the tranformation in the row of s. */ - for (i = k+1; i<n; ++i) { - temp = givens.c() * s(i,k) + givens.s() * sdiag[i]; - sdiag[i] = -givens.s() * s(i,k) + givens.c() * sdiag[i]; - s(i,k) = temp; - } - } - } - - /* solve the triangular system for z. if the system is */ - /* singular, then obtain a least squares solution. */ - Index nsing; - for(nsing=0; nsing<n && sdiag[nsing]!=0; nsing++) {} - - wa.tail(n-nsing).setZero(); - s.topLeftCorner(nsing, nsing).transpose().template triangularView<Upper>().solveInPlace(wa.head(nsing)); - - // restore - sdiag = s.diagonal(); - s.diagonal() = x; - - /* permute the components of z back to components of x. */ - for (j = 0; j < n; ++j) x[ipvt[j]] = wa[j]; -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/r1mpyq.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/r1mpyq.h deleted file mode 100644 index 36ff700..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/r1mpyq.h +++ /dev/null @@ -1,30 +0,0 @@ -namespace Eigen { - -namespace internal { - -// TODO : move this to GivensQR once there's such a thing in Eigen - -template <typename Scalar> -void r1mpyq(DenseIndex m, DenseIndex n, Scalar *a, const std::vector<JacobiRotation<Scalar> > &v_givens, const std::vector<JacobiRotation<Scalar> > &w_givens) -{ - typedef DenseIndex Index; - - /* apply the first set of givens rotations to a. */ - for (Index j = n-2; j>=0; --j) - for (Index i = 0; i<m; ++i) { - Scalar temp = v_givens[j].c() * a[i+m*j] - v_givens[j].s() * a[i+m*(n-1)]; - a[i+m*(n-1)] = v_givens[j].s() * a[i+m*j] + v_givens[j].c() * a[i+m*(n-1)]; - a[i+m*j] = temp; - } - /* apply the second set of givens rotations to a. */ - for (Index j = 0; j<n-1; ++j) - for (Index i = 0; i<m; ++i) { - Scalar temp = w_givens[j].c() * a[i+m*j] + w_givens[j].s() * a[i+m*(n-1)]; - a[i+m*(n-1)] = -w_givens[j].s() * a[i+m*j] + w_givens[j].c() * a[i+m*(n-1)]; - a[i+m*j] = temp; - } -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/r1updt.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/r1updt.h deleted file mode 100644 index f287660..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/r1updt.h +++ /dev/null @@ -1,99 +0,0 @@ -namespace Eigen { - -namespace internal { - -template <typename Scalar> -void r1updt( - Matrix< Scalar, Dynamic, Dynamic > &s, - const Matrix< Scalar, Dynamic, 1> &u, - std::vector<JacobiRotation<Scalar> > &v_givens, - std::vector<JacobiRotation<Scalar> > &w_givens, - Matrix< Scalar, Dynamic, 1> &v, - Matrix< Scalar, Dynamic, 1> &w, - bool *sing) -{ - typedef DenseIndex Index; - const JacobiRotation<Scalar> IdentityRotation = JacobiRotation<Scalar>(1,0); - - /* Local variables */ - const Index m = s.rows(); - const Index n = s.cols(); - Index i, j=1; - Scalar temp; - JacobiRotation<Scalar> givens; - - // r1updt had a broader usecase, but we dont use it here. And, more - // importantly, we can not test it. - eigen_assert(m==n); - eigen_assert(u.size()==m); - eigen_assert(v.size()==n); - eigen_assert(w.size()==n); - - /* move the nontrivial part of the last column of s into w. */ - w[n-1] = s(n-1,n-1); - - /* rotate the vector v into a multiple of the n-th unit vector */ - /* in such a way that a spike is introduced into w. */ - for (j=n-2; j>=0; --j) { - w[j] = 0.; - if (v[j] != 0.) { - /* determine a givens rotation which eliminates the */ - /* j-th element of v. */ - givens.makeGivens(-v[n-1], v[j]); - - /* apply the transformation to v and store the information */ - /* necessary to recover the givens rotation. */ - v[n-1] = givens.s() * v[j] + givens.c() * v[n-1]; - v_givens[j] = givens; - - /* apply the transformation to s and extend the spike in w. */ - for (i = j; i < m; ++i) { - temp = givens.c() * s(j,i) - givens.s() * w[i]; - w[i] = givens.s() * s(j,i) + givens.c() * w[i]; - s(j,i) = temp; - } - } else - v_givens[j] = IdentityRotation; - } - - /* add the spike from the rank 1 update to w. */ - w += v[n-1] * u; - - /* eliminate the spike. */ - *sing = false; - for (j = 0; j < n-1; ++j) { - if (w[j] != 0.) { - /* determine a givens rotation which eliminates the */ - /* j-th element of the spike. */ - givens.makeGivens(-s(j,j), w[j]); - - /* apply the transformation to s and reduce the spike in w. */ - for (i = j; i < m; ++i) { - temp = givens.c() * s(j,i) + givens.s() * w[i]; - w[i] = -givens.s() * s(j,i) + givens.c() * w[i]; - s(j,i) = temp; - } - - /* store the information necessary to recover the */ - /* givens rotation. */ - w_givens[j] = givens; - } else - v_givens[j] = IdentityRotation; - - /* test for zero diagonal elements in the output s. */ - if (s(j,j) == 0.) { - *sing = true; - } - } - /* move w back into the last column of the output s. */ - s(n-1,n-1) = w[n-1]; - - if (s(j,j) == 0.) { - *sing = true; - } - return; -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h b/eigen/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h deleted file mode 100644 index 6ebf856..0000000 --- a/eigen/unsupported/Eigen/src/NonLinearOptimization/rwupdt.h +++ /dev/null @@ -1,49 +0,0 @@ -namespace Eigen { - -namespace internal { - -template <typename Scalar> -void rwupdt( - Matrix< Scalar, Dynamic, Dynamic > &r, - const Matrix< Scalar, Dynamic, 1> &w, - Matrix< Scalar, Dynamic, 1> &b, - Scalar alpha) -{ - typedef DenseIndex Index; - - const Index n = r.cols(); - eigen_assert(r.rows()>=n); - std::vector<JacobiRotation<Scalar> > givens(n); - - /* Local variables */ - Scalar temp, rowj; - - /* Function Body */ - for (Index j = 0; j < n; ++j) { - rowj = w[j]; - - /* apply the previous transformations to */ - /* r(i,j), i=0,1,...,j-1, and to w(j). */ - for (Index i = 0; i < j; ++i) { - temp = givens[i].c() * r(i,j) + givens[i].s() * rowj; - rowj = -givens[i].s() * r(i,j) + givens[i].c() * rowj; - r(i,j) = temp; - } - - /* determine a givens rotation which eliminates w(j). */ - givens[j].makeGivens(-r(j,j), rowj); - - if (rowj == 0.) - continue; // givens[j] is identity - - /* apply the current transformation to r(j,j), b(j), and alpha. */ - r(j,j) = givens[j].c() * r(j,j) + givens[j].s() * rowj; - temp = givens[j].c() * b[j] + givens[j].s() * alpha; - alpha = -givens[j].s() * b[j] + givens[j].c() * alpha; - b[j] = temp; - } -} - -} // end namespace internal - -} // end namespace Eigen diff --git a/eigen/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h b/eigen/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h deleted file mode 100644 index ea5d8bc..0000000 --- a/eigen/unsupported/Eigen/src/NumericalDiff/NumericalDiff.h +++ /dev/null @@ -1,130 +0,0 @@ -// -*- coding: utf-8 -// vim: set fileencoding=utf-8 - -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_NUMERICAL_DIFF_H -#define EIGEN_NUMERICAL_DIFF_H - -namespace Eigen { - -enum NumericalDiffMode { - Forward, - Central -}; - - -/** - * This class allows you to add a method df() to your functor, which will - * use numerical differentiation to compute an approximate of the - * derivative for the functor. Of course, if you have an analytical form - * for the derivative, you should rather implement df() by yourself. - * - * More information on - * http://en.wikipedia.org/wiki/Numerical_differentiation - * - * Currently only "Forward" and "Central" scheme are implemented. - */ -template<typename _Functor, NumericalDiffMode mode=Forward> -class NumericalDiff : public _Functor -{ -public: - typedef _Functor Functor; - typedef typename Functor::Scalar Scalar; - typedef typename Functor::InputType InputType; - typedef typename Functor::ValueType ValueType; - typedef typename Functor::JacobianType JacobianType; - - NumericalDiff(Scalar _epsfcn=0.) : Functor(), epsfcn(_epsfcn) {} - NumericalDiff(const Functor& f, Scalar _epsfcn=0.) : Functor(f), epsfcn(_epsfcn) {} - - // forward constructors - template<typename T0> - NumericalDiff(const T0& a0) : Functor(a0), epsfcn(0) {} - template<typename T0, typename T1> - NumericalDiff(const T0& a0, const T1& a1) : Functor(a0, a1), epsfcn(0) {} - template<typename T0, typename T1, typename T2> - NumericalDiff(const T0& a0, const T1& a1, const T2& a2) : Functor(a0, a1, a2), epsfcn(0) {} - - enum { - InputsAtCompileTime = Functor::InputsAtCompileTime, - ValuesAtCompileTime = Functor::ValuesAtCompileTime - }; - - /** - * return the number of evaluation of functor - */ - int df(const InputType& _x, JacobianType &jac) const - { - using std::sqrt; - using std::abs; - /* Local variables */ - Scalar h; - int nfev=0; - const typename InputType::Index n = _x.size(); - const Scalar eps = sqrt(((std::max)(epsfcn,NumTraits<Scalar>::epsilon() ))); - ValueType val1, val2; - InputType x = _x; - // TODO : we should do this only if the size is not already known - val1.resize(Functor::values()); - val2.resize(Functor::values()); - - // initialization - switch(mode) { - case Forward: - // compute f(x) - Functor::operator()(x, val1); nfev++; - break; - case Central: - // do nothing - break; - default: - eigen_assert(false); - }; - - // Function Body - for (int j = 0; j < n; ++j) { - h = eps * abs(x[j]); - if (h == 0.) { - h = eps; - } - switch(mode) { - case Forward: - x[j] += h; - Functor::operator()(x, val2); - nfev++; - x[j] = _x[j]; - jac.col(j) = (val2-val1)/h; - break; - case Central: - x[j] += h; - Functor::operator()(x, val2); nfev++; - x[j] -= 2*h; - Functor::operator()(x, val1); nfev++; - x[j] = _x[j]; - jac.col(j) = (val2-val1)/(2*h); - break; - default: - eigen_assert(false); - }; - } - return nfev; - } -private: - Scalar epsfcn; - - NumericalDiff& operator=(const NumericalDiff&); -}; - -} // end namespace Eigen - -//vim: ai ts=4 sts=4 et sw=4 -#endif // EIGEN_NUMERICAL_DIFF_H - diff --git a/eigen/unsupported/Eigen/src/Polynomials/Companion.h b/eigen/unsupported/Eigen/src/Polynomials/Companion.h deleted file mode 100644 index b515c29..0000000 --- a/eigen/unsupported/Eigen/src/Polynomials/Companion.h +++ /dev/null @@ -1,276 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_COMPANION_H -#define EIGEN_COMPANION_H - -// This file requires the user to include -// * Eigen/Core -// * Eigen/src/PolynomialSolver.h - -namespace Eigen { - -namespace internal { - -#ifndef EIGEN_PARSED_BY_DOXYGEN - -template <typename T> -T radix(){ return 2; } - -template <typename T> -T radix2(){ return radix<T>()*radix<T>(); } - -template<int Size> -struct decrement_if_fixed_size -{ - enum { - ret = (Size == Dynamic) ? Dynamic : Size-1 }; -}; - -#endif - -template< typename _Scalar, int _Deg > -class companion -{ - public: - EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Deg==Dynamic ? Dynamic : _Deg) - - enum { - Deg = _Deg, - Deg_1=decrement_if_fixed_size<Deg>::ret - }; - - typedef _Scalar Scalar; - typedef typename NumTraits<Scalar>::Real RealScalar; - typedef Matrix<Scalar, Deg, 1> RightColumn; - //typedef DiagonalMatrix< Scalar, Deg_1, Deg_1 > BottomLeftDiagonal; - typedef Matrix<Scalar, Deg_1, 1> BottomLeftDiagonal; - - typedef Matrix<Scalar, Deg, Deg> DenseCompanionMatrixType; - typedef Matrix< Scalar, _Deg, Deg_1 > LeftBlock; - typedef Matrix< Scalar, Deg_1, Deg_1 > BottomLeftBlock; - typedef Matrix< Scalar, 1, Deg_1 > LeftBlockFirstRow; - - typedef DenseIndex Index; - - public: - EIGEN_STRONG_INLINE const _Scalar operator()(Index row, Index col ) const - { - if( m_bl_diag.rows() > col ) - { - if( 0 < row ){ return m_bl_diag[col]; } - else{ return 0; } - } - else{ return m_monic[row]; } - } - - public: - template<typename VectorType> - void setPolynomial( const VectorType& poly ) - { - const Index deg = poly.size()-1; - m_monic = -1/poly[deg] * poly.head(deg); - //m_bl_diag.setIdentity( deg-1 ); - m_bl_diag.setOnes(deg-1); - } - - template<typename VectorType> - companion( const VectorType& poly ){ - setPolynomial( poly ); } - - public: - DenseCompanionMatrixType denseMatrix() const - { - const Index deg = m_monic.size(); - const Index deg_1 = deg-1; - DenseCompanionMatrixType companion(deg,deg); - companion << - ( LeftBlock(deg,deg_1) - << LeftBlockFirstRow::Zero(1,deg_1), - BottomLeftBlock::Identity(deg-1,deg-1)*m_bl_diag.asDiagonal() ).finished() - , m_monic; - return companion; - } - - - - protected: - /** Helper function for the balancing algorithm. - * \returns true if the row and the column, having colNorm and rowNorm - * as norms, are balanced, false otherwise. - * colB and rowB are repectively the multipliers for - * the column and the row in order to balance them. - * */ - bool balanced( Scalar colNorm, Scalar rowNorm, - bool& isBalanced, Scalar& colB, Scalar& rowB ); - - /** Helper function for the balancing algorithm. - * \returns true if the row and the column, having colNorm and rowNorm - * as norms, are balanced, false otherwise. - * colB and rowB are repectively the multipliers for - * the column and the row in order to balance them. - * */ - bool balancedR( Scalar colNorm, Scalar rowNorm, - bool& isBalanced, Scalar& colB, Scalar& rowB ); - - public: - /** - * Balancing algorithm from B. N. PARLETT and C. REINSCH (1969) - * "Balancing a matrix for calculation of eigenvalues and eigenvectors" - * adapted to the case of companion matrices. - * A matrix with non zero row and non zero column is balanced - * for a certain norm if the i-th row and the i-th column - * have same norm for all i. - */ - void balance(); - - protected: - RightColumn m_monic; - BottomLeftDiagonal m_bl_diag; -}; - - - -template< typename _Scalar, int _Deg > -inline -bool companion<_Scalar,_Deg>::balanced( Scalar colNorm, Scalar rowNorm, - bool& isBalanced, Scalar& colB, Scalar& rowB ) -{ - if( Scalar(0) == colNorm || Scalar(0) == rowNorm ){ return true; } - else - { - //To find the balancing coefficients, if the radix is 2, - //one finds \f$ \sigma \f$ such that - // \f$ 2^{2\sigma-1} < rowNorm / colNorm \le 2^{2\sigma+1} \f$ - // then the balancing coefficient for the row is \f$ 1/2^{\sigma} \f$ - // and the balancing coefficient for the column is \f$ 2^{\sigma} \f$ - rowB = rowNorm / radix<Scalar>(); - colB = Scalar(1); - const Scalar s = colNorm + rowNorm; - - while (colNorm < rowB) - { - colB *= radix<Scalar>(); - colNorm *= radix2<Scalar>(); - } - - rowB = rowNorm * radix<Scalar>(); - - while (colNorm >= rowB) - { - colB /= radix<Scalar>(); - colNorm /= radix2<Scalar>(); - } - - //This line is used to avoid insubstantial balancing - if ((rowNorm + colNorm) < Scalar(0.95) * s * colB) - { - isBalanced = false; - rowB = Scalar(1) / colB; - return false; - } - else{ - return true; } - } -} - -template< typename _Scalar, int _Deg > -inline -bool companion<_Scalar,_Deg>::balancedR( Scalar colNorm, Scalar rowNorm, - bool& isBalanced, Scalar& colB, Scalar& rowB ) -{ - if( Scalar(0) == colNorm || Scalar(0) == rowNorm ){ return true; } - else - { - /** - * Set the norm of the column and the row to the geometric mean - * of the row and column norm - */ - const _Scalar q = colNorm/rowNorm; - if( !isApprox( q, _Scalar(1) ) ) - { - rowB = sqrt( colNorm/rowNorm ); - colB = Scalar(1)/rowB; - - isBalanced = false; - return false; - } - else{ - return true; } - } -} - - -template< typename _Scalar, int _Deg > -void companion<_Scalar,_Deg>::balance() -{ - using std::abs; - EIGEN_STATIC_ASSERT( Deg == Dynamic || 1 < Deg, YOU_MADE_A_PROGRAMMING_MISTAKE ); - const Index deg = m_monic.size(); - const Index deg_1 = deg-1; - - bool hasConverged=false; - while( !hasConverged ) - { - hasConverged = true; - Scalar colNorm,rowNorm; - Scalar colB,rowB; - - //First row, first column excluding the diagonal - //============================================== - colNorm = abs(m_bl_diag[0]); - rowNorm = abs(m_monic[0]); - - //Compute balancing of the row and the column - if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) ) - { - m_bl_diag[0] *= colB; - m_monic[0] *= rowB; - } - - //Middle rows and columns excluding the diagonal - //============================================== - for( Index i=1; i<deg_1; ++i ) - { - // column norm, excluding the diagonal - colNorm = abs(m_bl_diag[i]); - - // row norm, excluding the diagonal - rowNorm = abs(m_bl_diag[i-1]) + abs(m_monic[i]); - - //Compute balancing of the row and the column - if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) ) - { - m_bl_diag[i] *= colB; - m_bl_diag[i-1] *= rowB; - m_monic[i] *= rowB; - } - } - - //Last row, last column excluding the diagonal - //============================================ - const Index ebl = m_bl_diag.size()-1; - VectorBlock<RightColumn,Deg_1> headMonic( m_monic, 0, deg_1 ); - colNorm = headMonic.array().abs().sum(); - rowNorm = abs( m_bl_diag[ebl] ); - - //Compute balancing of the row and the column - if( !balanced( colNorm, rowNorm, hasConverged, colB, rowB ) ) - { - headMonic *= colB; - m_bl_diag[ebl] *= rowB; - } - } -} - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_COMPANION_H diff --git a/eigen/unsupported/Eigen/src/Polynomials/PolynomialSolver.h b/eigen/unsupported/Eigen/src/Polynomials/PolynomialSolver.h deleted file mode 100644 index 03198ec..0000000 --- a/eigen/unsupported/Eigen/src/Polynomials/PolynomialSolver.h +++ /dev/null @@ -1,406 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_POLYNOMIAL_SOLVER_H -#define EIGEN_POLYNOMIAL_SOLVER_H - -namespace Eigen { - -/** \ingroup Polynomials_Module - * \class PolynomialSolverBase. - * - * \brief Defined to be inherited by polynomial solvers: it provides - * convenient methods such as - * - real roots, - * - greatest, smallest complex roots, - * - real roots with greatest, smallest absolute real value, - * - greatest, smallest real roots. - * - * It stores the set of roots as a vector of complexes. - * - */ -template< typename _Scalar, int _Deg > -class PolynomialSolverBase -{ - public: - EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Deg==Dynamic ? Dynamic : _Deg) - - typedef _Scalar Scalar; - typedef typename NumTraits<Scalar>::Real RealScalar; - typedef std::complex<RealScalar> RootType; - typedef Matrix<RootType,_Deg,1> RootsType; - - typedef DenseIndex Index; - - protected: - template< typename OtherPolynomial > - inline void setPolynomial( const OtherPolynomial& poly ){ - m_roots.resize(poly.size()-1); } - - public: - template< typename OtherPolynomial > - inline PolynomialSolverBase( const OtherPolynomial& poly ){ - setPolynomial( poly() ); } - - inline PolynomialSolverBase(){} - - public: - /** \returns the complex roots of the polynomial */ - inline const RootsType& roots() const { return m_roots; } - - public: - /** Clear and fills the back insertion sequence with the real roots of the polynomial - * i.e. the real part of the complex roots that have an imaginary part which - * absolute value is smaller than absImaginaryThreshold. - * absImaginaryThreshold takes the dummy_precision associated - * with the _Scalar template parameter of the PolynomialSolver class as the default value. - * - * \param[out] bi_seq : the back insertion sequence (stl concept) - * \param[in] absImaginaryThreshold : the maximum bound of the imaginary part of a complex - * number that is considered as real. - * */ - template<typename Stl_back_insertion_sequence> - inline void realRoots( Stl_back_insertion_sequence& bi_seq, - const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const - { - using std::abs; - bi_seq.clear(); - for(Index i=0; i<m_roots.size(); ++i ) - { - if( abs( m_roots[i].imag() ) < absImaginaryThreshold ){ - bi_seq.push_back( m_roots[i].real() ); } - } - } - - protected: - template<typename squaredNormBinaryPredicate> - inline const RootType& selectComplexRoot_withRespectToNorm( squaredNormBinaryPredicate& pred ) const - { - Index res=0; - RealScalar norm2 = numext::abs2( m_roots[0] ); - for( Index i=1; i<m_roots.size(); ++i ) - { - const RealScalar currNorm2 = numext::abs2( m_roots[i] ); - if( pred( currNorm2, norm2 ) ){ - res=i; norm2=currNorm2; } - } - return m_roots[res]; - } - - public: - /** - * \returns the complex root with greatest norm. - */ - inline const RootType& greatestRoot() const - { - std::greater<Scalar> greater; - return selectComplexRoot_withRespectToNorm( greater ); - } - - /** - * \returns the complex root with smallest norm. - */ - inline const RootType& smallestRoot() const - { - std::less<Scalar> less; - return selectComplexRoot_withRespectToNorm( less ); - } - - protected: - template<typename squaredRealPartBinaryPredicate> - inline const RealScalar& selectRealRoot_withRespectToAbsRealPart( - squaredRealPartBinaryPredicate& pred, - bool& hasArealRoot, - const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const - { - using std::abs; - hasArealRoot = false; - Index res=0; - RealScalar abs2(0); - - for( Index i=0; i<m_roots.size(); ++i ) - { - if( abs( m_roots[i].imag() ) < absImaginaryThreshold ) - { - if( !hasArealRoot ) - { - hasArealRoot = true; - res = i; - abs2 = m_roots[i].real() * m_roots[i].real(); - } - else - { - const RealScalar currAbs2 = m_roots[i].real() * m_roots[i].real(); - if( pred( currAbs2, abs2 ) ) - { - abs2 = currAbs2; - res = i; - } - } - } - else - { - if( abs( m_roots[i].imag() ) < abs( m_roots[res].imag() ) ){ - res = i; } - } - } - return numext::real_ref(m_roots[res]); - } - - - template<typename RealPartBinaryPredicate> - inline const RealScalar& selectRealRoot_withRespectToRealPart( - RealPartBinaryPredicate& pred, - bool& hasArealRoot, - const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const - { - using std::abs; - hasArealRoot = false; - Index res=0; - RealScalar val(0); - - for( Index i=0; i<m_roots.size(); ++i ) - { - if( abs( m_roots[i].imag() ) < absImaginaryThreshold ) - { - if( !hasArealRoot ) - { - hasArealRoot = true; - res = i; - val = m_roots[i].real(); - } - else - { - const RealScalar curr = m_roots[i].real(); - if( pred( curr, val ) ) - { - val = curr; - res = i; - } - } - } - else - { - if( abs( m_roots[i].imag() ) < abs( m_roots[res].imag() ) ){ - res = i; } - } - } - return numext::real_ref(m_roots[res]); - } - - public: - /** - * \returns a real root with greatest absolute magnitude. - * A real root is defined as the real part of a complex root with absolute imaginary - * part smallest than absImaginaryThreshold. - * absImaginaryThreshold takes the dummy_precision associated - * with the _Scalar template parameter of the PolynomialSolver class as the default value. - * If no real root is found the boolean hasArealRoot is set to false and the real part of - * the root with smallest absolute imaginary part is returned instead. - * - * \param[out] hasArealRoot : boolean true if a real root is found according to the - * absImaginaryThreshold criterion, false otherwise. - * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide - * whether or not a root is real. - */ - inline const RealScalar& absGreatestRealRoot( - bool& hasArealRoot, - const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const - { - std::greater<Scalar> greater; - return selectRealRoot_withRespectToAbsRealPart( greater, hasArealRoot, absImaginaryThreshold ); - } - - - /** - * \returns a real root with smallest absolute magnitude. - * A real root is defined as the real part of a complex root with absolute imaginary - * part smallest than absImaginaryThreshold. - * absImaginaryThreshold takes the dummy_precision associated - * with the _Scalar template parameter of the PolynomialSolver class as the default value. - * If no real root is found the boolean hasArealRoot is set to false and the real part of - * the root with smallest absolute imaginary part is returned instead. - * - * \param[out] hasArealRoot : boolean true if a real root is found according to the - * absImaginaryThreshold criterion, false otherwise. - * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide - * whether or not a root is real. - */ - inline const RealScalar& absSmallestRealRoot( - bool& hasArealRoot, - const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const - { - std::less<Scalar> less; - return selectRealRoot_withRespectToAbsRealPart( less, hasArealRoot, absImaginaryThreshold ); - } - - - /** - * \returns the real root with greatest value. - * A real root is defined as the real part of a complex root with absolute imaginary - * part smallest than absImaginaryThreshold. - * absImaginaryThreshold takes the dummy_precision associated - * with the _Scalar template parameter of the PolynomialSolver class as the default value. - * If no real root is found the boolean hasArealRoot is set to false and the real part of - * the root with smallest absolute imaginary part is returned instead. - * - * \param[out] hasArealRoot : boolean true if a real root is found according to the - * absImaginaryThreshold criterion, false otherwise. - * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide - * whether or not a root is real. - */ - inline const RealScalar& greatestRealRoot( - bool& hasArealRoot, - const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const - { - std::greater<Scalar> greater; - return selectRealRoot_withRespectToRealPart( greater, hasArealRoot, absImaginaryThreshold ); - } - - - /** - * \returns the real root with smallest value. - * A real root is defined as the real part of a complex root with absolute imaginary - * part smallest than absImaginaryThreshold. - * absImaginaryThreshold takes the dummy_precision associated - * with the _Scalar template parameter of the PolynomialSolver class as the default value. - * If no real root is found the boolean hasArealRoot is set to false and the real part of - * the root with smallest absolute imaginary part is returned instead. - * - * \param[out] hasArealRoot : boolean true if a real root is found according to the - * absImaginaryThreshold criterion, false otherwise. - * \param[in] absImaginaryThreshold : threshold on the absolute imaginary part to decide - * whether or not a root is real. - */ - inline const RealScalar& smallestRealRoot( - bool& hasArealRoot, - const RealScalar& absImaginaryThreshold = NumTraits<Scalar>::dummy_precision() ) const - { - std::less<Scalar> less; - return selectRealRoot_withRespectToRealPart( less, hasArealRoot, absImaginaryThreshold ); - } - - protected: - RootsType m_roots; -}; - -#define EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES( BASE ) \ - typedef typename BASE::Scalar Scalar; \ - typedef typename BASE::RealScalar RealScalar; \ - typedef typename BASE::RootType RootType; \ - typedef typename BASE::RootsType RootsType; - - - -/** \ingroup Polynomials_Module - * - * \class PolynomialSolver - * - * \brief A polynomial solver - * - * Computes the complex roots of a real polynomial. - * - * \param _Scalar the scalar type, i.e., the type of the polynomial coefficients - * \param _Deg the degree of the polynomial, can be a compile time value or Dynamic. - * Notice that the number of polynomial coefficients is _Deg+1. - * - * This class implements a polynomial solver and provides convenient methods such as - * - real roots, - * - greatest, smallest complex roots, - * - real roots with greatest, smallest absolute real value. - * - greatest, smallest real roots. - * - * WARNING: this polynomial solver is experimental, part of the unsupported Eigen modules. - * - * - * Currently a QR algorithm is used to compute the eigenvalues of the companion matrix of - * the polynomial to compute its roots. - * This supposes that the complex moduli of the roots are all distinct: e.g. there should - * be no multiple roots or conjugate roots for instance. - * With 32bit (float) floating types this problem shows up frequently. - * However, almost always, correct accuracy is reached even in these cases for 64bit - * (double) floating types and small polynomial degree (<20). - */ -template< typename _Scalar, int _Deg > -class PolynomialSolver : public PolynomialSolverBase<_Scalar,_Deg> -{ - public: - EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Deg==Dynamic ? Dynamic : _Deg) - - typedef PolynomialSolverBase<_Scalar,_Deg> PS_Base; - EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES( PS_Base ) - - typedef Matrix<Scalar,_Deg,_Deg> CompanionMatrixType; - typedef EigenSolver<CompanionMatrixType> EigenSolverType; - - public: - /** Computes the complex roots of a new polynomial. */ - template< typename OtherPolynomial > - void compute( const OtherPolynomial& poly ) - { - eigen_assert( Scalar(0) != poly[poly.size()-1] ); - eigen_assert( poly.size() > 1 ); - if(poly.size() > 2 ) - { - internal::companion<Scalar,_Deg> companion( poly ); - companion.balance(); - m_eigenSolver.compute( companion.denseMatrix() ); - m_roots = m_eigenSolver.eigenvalues(); - } - else if(poly.size () == 2) - { - m_roots.resize(1); - m_roots[0] = -poly[0]/poly[1]; - } - } - - public: - template< typename OtherPolynomial > - inline PolynomialSolver( const OtherPolynomial& poly ){ - compute( poly ); } - - inline PolynomialSolver(){} - - protected: - using PS_Base::m_roots; - EigenSolverType m_eigenSolver; -}; - - -template< typename _Scalar > -class PolynomialSolver<_Scalar,1> : public PolynomialSolverBase<_Scalar,1> -{ - public: - typedef PolynomialSolverBase<_Scalar,1> PS_Base; - EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES( PS_Base ) - - public: - /** Computes the complex roots of a new polynomial. */ - template< typename OtherPolynomial > - void compute( const OtherPolynomial& poly ) - { - eigen_assert( poly.size() == 2 ); - eigen_assert( Scalar(0) != poly[1] ); - m_roots[0] = -poly[0]/poly[1]; - } - - public: - template< typename OtherPolynomial > - inline PolynomialSolver( const OtherPolynomial& poly ){ - compute( poly ); } - - inline PolynomialSolver(){} - - protected: - using PS_Base::m_roots; -}; - -} // end namespace Eigen - -#endif // EIGEN_POLYNOMIAL_SOLVER_H diff --git a/eigen/unsupported/Eigen/src/Polynomials/PolynomialUtils.h b/eigen/unsupported/Eigen/src/Polynomials/PolynomialUtils.h deleted file mode 100644 index 394e857..0000000 --- a/eigen/unsupported/Eigen/src/Polynomials/PolynomialUtils.h +++ /dev/null @@ -1,143 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2010 Manuel Yguel <manuel.yguel@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_POLYNOMIAL_UTILS_H -#define EIGEN_POLYNOMIAL_UTILS_H - -namespace Eigen { - -/** \ingroup Polynomials_Module - * \returns the evaluation of the polynomial at x using Horner algorithm. - * - * \param[in] poly : the vector of coefficients of the polynomial ordered - * by degrees i.e. poly[i] is the coefficient of degree i of the polynomial - * e.g. \f$ 1 + 3x^2 \f$ is stored as a vector \f$ [ 1, 0, 3 ] \f$. - * \param[in] x : the value to evaluate the polynomial at. - * - * \note for stability: - * \f$ |x| \le 1 \f$ - */ -template <typename Polynomials, typename T> -inline -T poly_eval_horner( const Polynomials& poly, const T& x ) -{ - T val=poly[poly.size()-1]; - for(DenseIndex i=poly.size()-2; i>=0; --i ){ - val = val*x + poly[i]; } - return val; -} - -/** \ingroup Polynomials_Module - * \returns the evaluation of the polynomial at x using stabilized Horner algorithm. - * - * \param[in] poly : the vector of coefficients of the polynomial ordered - * by degrees i.e. poly[i] is the coefficient of degree i of the polynomial - * e.g. \f$ 1 + 3x^2 \f$ is stored as a vector \f$ [ 1, 0, 3 ] \f$. - * \param[in] x : the value to evaluate the polynomial at. - */ -template <typename Polynomials, typename T> -inline -T poly_eval( const Polynomials& poly, const T& x ) -{ - typedef typename NumTraits<T>::Real Real; - - if( numext::abs2( x ) <= Real(1) ){ - return poly_eval_horner( poly, x ); } - else - { - T val=poly[0]; - T inv_x = T(1)/x; - for( DenseIndex i=1; i<poly.size(); ++i ){ - val = val*inv_x + poly[i]; } - - return numext::pow(x,(T)(poly.size()-1)) * val; - } -} - -/** \ingroup Polynomials_Module - * \returns a maximum bound for the absolute value of any root of the polynomial. - * - * \param[in] poly : the vector of coefficients of the polynomial ordered - * by degrees i.e. poly[i] is the coefficient of degree i of the polynomial - * e.g. \f$ 1 + 3x^2 \f$ is stored as a vector \f$ [ 1, 0, 3 ] \f$. - * - * \pre - * the leading coefficient of the input polynomial poly must be non zero - */ -template <typename Polynomial> -inline -typename NumTraits<typename Polynomial::Scalar>::Real cauchy_max_bound( const Polynomial& poly ) -{ - using std::abs; - typedef typename Polynomial::Scalar Scalar; - typedef typename NumTraits<Scalar>::Real Real; - - eigen_assert( Scalar(0) != poly[poly.size()-1] ); - const Scalar inv_leading_coeff = Scalar(1)/poly[poly.size()-1]; - Real cb(0); - - for( DenseIndex i=0; i<poly.size()-1; ++i ){ - cb += abs(poly[i]*inv_leading_coeff); } - return cb + Real(1); -} - -/** \ingroup Polynomials_Module - * \returns a minimum bound for the absolute value of any non zero root of the polynomial. - * \param[in] poly : the vector of coefficients of the polynomial ordered - * by degrees i.e. poly[i] is the coefficient of degree i of the polynomial - * e.g. \f$ 1 + 3x^2 \f$ is stored as a vector \f$ [ 1, 0, 3 ] \f$. - */ -template <typename Polynomial> -inline -typename NumTraits<typename Polynomial::Scalar>::Real cauchy_min_bound( const Polynomial& poly ) -{ - using std::abs; - typedef typename Polynomial::Scalar Scalar; - typedef typename NumTraits<Scalar>::Real Real; - - DenseIndex i=0; - while( i<poly.size()-1 && Scalar(0) == poly(i) ){ ++i; } - if( poly.size()-1 == i ){ - return Real(1); } - - const Scalar inv_min_coeff = Scalar(1)/poly[i]; - Real cb(1); - for( DenseIndex j=i+1; j<poly.size(); ++j ){ - cb += abs(poly[j]*inv_min_coeff); } - return Real(1)/cb; -} - -/** \ingroup Polynomials_Module - * Given the roots of a polynomial compute the coefficients in the - * monomial basis of the monic polynomial with same roots and minimal degree. - * If RootVector is a vector of complexes, Polynomial should also be a vector - * of complexes. - * \param[in] rv : a vector containing the roots of a polynomial. - * \param[out] poly : the vector of coefficients of the polynomial ordered - * by degrees i.e. poly[i] is the coefficient of degree i of the polynomial - * e.g. \f$ 3 + x^2 \f$ is stored as a vector \f$ [ 3, 0, 1 ] \f$. - */ -template <typename RootVector, typename Polynomial> -void roots_to_monicPolynomial( const RootVector& rv, Polynomial& poly ) -{ - - typedef typename Polynomial::Scalar Scalar; - - poly.setZero( rv.size()+1 ); - poly[0] = -rv[0]; poly[1] = Scalar(1); - for( DenseIndex i=1; i< rv.size(); ++i ) - { - for( DenseIndex j=i+1; j>0; --j ){ poly[j] = poly[j-1] - rv[i]*poly[j]; } - poly[0] = -rv[i]*poly[0]; - } -} - -} // end namespace Eigen - -#endif // EIGEN_POLYNOMIAL_UTILS_H diff --git a/eigen/unsupported/Eigen/src/Skyline/SkylineInplaceLU.h b/eigen/unsupported/Eigen/src/Skyline/SkylineInplaceLU.h deleted file mode 100644 index a1f54ed..0000000 --- a/eigen/unsupported/Eigen/src/Skyline/SkylineInplaceLU.h +++ /dev/null @@ -1,352 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008 Guillaume Saupin <guillaume.saupin@cea.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SKYLINEINPLACELU_H -#define EIGEN_SKYLINEINPLACELU_H - -namespace Eigen { - -/** \ingroup Skyline_Module - * - * \class SkylineInplaceLU - * - * \brief Inplace LU decomposition of a skyline matrix and associated features - * - * \param MatrixType the type of the matrix of which we are computing the LU factorization - * - */ -template<typename MatrixType> -class SkylineInplaceLU { -protected: - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::Index Index; - - typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar; - -public: - - /** Creates a LU object and compute the respective factorization of \a matrix using - * flags \a flags. */ - SkylineInplaceLU(MatrixType& matrix, int flags = 0) - : /*m_matrix(matrix.rows(), matrix.cols()),*/ m_flags(flags), m_status(0), m_lu(matrix) { - m_precision = RealScalar(0.1) * Eigen::dummy_precision<RealScalar > (); - m_lu.IsRowMajor ? computeRowMajor() : compute(); - } - - /** Sets the relative threshold value used to prune zero coefficients during the decomposition. - * - * Setting a value greater than zero speeds up computation, and yields to an imcomplete - * factorization with fewer non zero coefficients. Such approximate factors are especially - * useful to initialize an iterative solver. - * - * Note that the exact meaning of this parameter might depends on the actual - * backend. Moreover, not all backends support this feature. - * - * \sa precision() */ - void setPrecision(RealScalar v) { - m_precision = v; - } - - /** \returns the current precision. - * - * \sa setPrecision() */ - RealScalar precision() const { - return m_precision; - } - - /** Sets the flags. Possible values are: - * - CompleteFactorization - * - IncompleteFactorization - * - MemoryEfficient - * - one of the ordering methods - * - etc... - * - * \sa flags() */ - void setFlags(int f) { - m_flags = f; - } - - /** \returns the current flags */ - int flags() const { - return m_flags; - } - - void setOrderingMethod(int m) { - m_flags = m; - } - - int orderingMethod() const { - return m_flags; - } - - /** Computes/re-computes the LU factorization */ - void compute(); - void computeRowMajor(); - - /** \returns the lower triangular matrix L */ - //inline const MatrixType& matrixL() const { return m_matrixL; } - - /** \returns the upper triangular matrix U */ - //inline const MatrixType& matrixU() const { return m_matrixU; } - - template<typename BDerived, typename XDerived> - bool solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x, - const int transposed = 0) const; - - /** \returns true if the factorization succeeded */ - inline bool succeeded(void) const { - return m_succeeded; - } - -protected: - RealScalar m_precision; - int m_flags; - mutable int m_status; - bool m_succeeded; - MatrixType& m_lu; -}; - -/** Computes / recomputes the in place LU decomposition of the SkylineInplaceLU. - * using the default algorithm. - */ -template<typename MatrixType> -//template<typename _Scalar> -void SkylineInplaceLU<MatrixType>::compute() { - const size_t rows = m_lu.rows(); - const size_t cols = m_lu.cols(); - - eigen_assert(rows == cols && "We do not (yet) support rectangular LU."); - eigen_assert(!m_lu.IsRowMajor && "LU decomposition does not work with rowMajor Storage"); - - for (Index row = 0; row < rows; row++) { - const double pivot = m_lu.coeffDiag(row); - - //Lower matrix Columns update - const Index& col = row; - for (typename MatrixType::InnerLowerIterator lIt(m_lu, col); lIt; ++lIt) { - lIt.valueRef() /= pivot; - } - - //Upper matrix update -> contiguous memory access - typename MatrixType::InnerLowerIterator lIt(m_lu, col); - for (Index rrow = row + 1; rrow < m_lu.rows(); rrow++) { - typename MatrixType::InnerUpperIterator uItPivot(m_lu, row); - typename MatrixType::InnerUpperIterator uIt(m_lu, rrow); - const double coef = lIt.value(); - - uItPivot += (rrow - row - 1); - - //update upper part -> contiguous memory access - for (++uItPivot; uIt && uItPivot;) { - uIt.valueRef() -= uItPivot.value() * coef; - - ++uIt; - ++uItPivot; - } - ++lIt; - } - - //Upper matrix update -> non contiguous memory access - typename MatrixType::InnerLowerIterator lIt3(m_lu, col); - for (Index rrow = row + 1; rrow < m_lu.rows(); rrow++) { - typename MatrixType::InnerUpperIterator uItPivot(m_lu, row); - const double coef = lIt3.value(); - - //update lower part -> non contiguous memory access - for (Index i = 0; i < rrow - row - 1; i++) { - m_lu.coeffRefLower(rrow, row + i + 1) -= uItPivot.value() * coef; - ++uItPivot; - } - ++lIt3; - } - //update diag -> contiguous - typename MatrixType::InnerLowerIterator lIt2(m_lu, col); - for (Index rrow = row + 1; rrow < m_lu.rows(); rrow++) { - - typename MatrixType::InnerUpperIterator uItPivot(m_lu, row); - typename MatrixType::InnerUpperIterator uIt(m_lu, rrow); - const double coef = lIt2.value(); - - uItPivot += (rrow - row - 1); - m_lu.coeffRefDiag(rrow) -= uItPivot.value() * coef; - ++lIt2; - } - } -} - -template<typename MatrixType> -void SkylineInplaceLU<MatrixType>::computeRowMajor() { - const size_t rows = m_lu.rows(); - const size_t cols = m_lu.cols(); - - eigen_assert(rows == cols && "We do not (yet) support rectangular LU."); - eigen_assert(m_lu.IsRowMajor && "You're trying to apply rowMajor decomposition on a ColMajor matrix !"); - - for (Index row = 0; row < rows; row++) { - typename MatrixType::InnerLowerIterator llIt(m_lu, row); - - - for (Index col = llIt.col(); col < row; col++) { - if (m_lu.coeffExistLower(row, col)) { - const double diag = m_lu.coeffDiag(col); - - typename MatrixType::InnerLowerIterator lIt(m_lu, row); - typename MatrixType::InnerUpperIterator uIt(m_lu, col); - - - const Index offset = lIt.col() - uIt.row(); - - - Index stop = offset > 0 ? col - lIt.col() : col - uIt.row(); - - //#define VECTORIZE -#ifdef VECTORIZE - Map<VectorXd > rowVal(lIt.valuePtr() + (offset > 0 ? 0 : -offset), stop); - Map<VectorXd > colVal(uIt.valuePtr() + (offset > 0 ? offset : 0), stop); - - - Scalar newCoeff = m_lu.coeffLower(row, col) - rowVal.dot(colVal); -#else - if (offset > 0) //Skip zero value of lIt - uIt += offset; - else //Skip zero values of uIt - lIt += -offset; - Scalar newCoeff = m_lu.coeffLower(row, col); - - for (Index k = 0; k < stop; ++k) { - const Scalar tmp = newCoeff; - newCoeff = tmp - lIt.value() * uIt.value(); - ++lIt; - ++uIt; - } -#endif - - m_lu.coeffRefLower(row, col) = newCoeff / diag; - } - } - - //Upper matrix update - const Index col = row; - typename MatrixType::InnerUpperIterator uuIt(m_lu, col); - for (Index rrow = uuIt.row(); rrow < col; rrow++) { - - typename MatrixType::InnerLowerIterator lIt(m_lu, rrow); - typename MatrixType::InnerUpperIterator uIt(m_lu, col); - const Index offset = lIt.col() - uIt.row(); - - Index stop = offset > 0 ? rrow - lIt.col() : rrow - uIt.row(); - -#ifdef VECTORIZE - Map<VectorXd > rowVal(lIt.valuePtr() + (offset > 0 ? 0 : -offset), stop); - Map<VectorXd > colVal(uIt.valuePtr() + (offset > 0 ? offset : 0), stop); - - Scalar newCoeff = m_lu.coeffUpper(rrow, col) - rowVal.dot(colVal); -#else - if (offset > 0) //Skip zero value of lIt - uIt += offset; - else //Skip zero values of uIt - lIt += -offset; - Scalar newCoeff = m_lu.coeffUpper(rrow, col); - for (Index k = 0; k < stop; ++k) { - const Scalar tmp = newCoeff; - newCoeff = tmp - lIt.value() * uIt.value(); - - ++lIt; - ++uIt; - } -#endif - m_lu.coeffRefUpper(rrow, col) = newCoeff; - } - - - //Diag matrix update - typename MatrixType::InnerLowerIterator lIt(m_lu, row); - typename MatrixType::InnerUpperIterator uIt(m_lu, row); - - const Index offset = lIt.col() - uIt.row(); - - - Index stop = offset > 0 ? lIt.size() : uIt.size(); -#ifdef VECTORIZE - Map<VectorXd > rowVal(lIt.valuePtr() + (offset > 0 ? 0 : -offset), stop); - Map<VectorXd > colVal(uIt.valuePtr() + (offset > 0 ? offset : 0), stop); - Scalar newCoeff = m_lu.coeffDiag(row) - rowVal.dot(colVal); -#else - if (offset > 0) //Skip zero value of lIt - uIt += offset; - else //Skip zero values of uIt - lIt += -offset; - Scalar newCoeff = m_lu.coeffDiag(row); - for (Index k = 0; k < stop; ++k) { - const Scalar tmp = newCoeff; - newCoeff = tmp - lIt.value() * uIt.value(); - ++lIt; - ++uIt; - } -#endif - m_lu.coeffRefDiag(row) = newCoeff; - } -} - -/** Computes *x = U^-1 L^-1 b - * - * If \a transpose is set to SvTranspose or SvAdjoint, the solution - * of the transposed/adjoint system is computed instead. - * - * Not all backends implement the solution of the transposed or - * adjoint system. - */ -template<typename MatrixType> -template<typename BDerived, typename XDerived> -bool SkylineInplaceLU<MatrixType>::solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x, const int transposed) const { - const size_t rows = m_lu.rows(); - const size_t cols = m_lu.cols(); - - - for (Index row = 0; row < rows; row++) { - x->coeffRef(row) = b.coeff(row); - Scalar newVal = x->coeff(row); - typename MatrixType::InnerLowerIterator lIt(m_lu, row); - - Index col = lIt.col(); - while (lIt.col() < row) { - - newVal -= x->coeff(col++) * lIt.value(); - ++lIt; - } - - x->coeffRef(row) = newVal; - } - - - for (Index col = rows - 1; col > 0; col--) { - x->coeffRef(col) = x->coeff(col) / m_lu.coeffDiag(col); - - const Scalar x_col = x->coeff(col); - - typename MatrixType::InnerUpperIterator uIt(m_lu, col); - uIt += uIt.size()-1; - - - while (uIt) { - x->coeffRef(uIt.row()) -= x_col * uIt.value(); - //TODO : introduce --operator - uIt += -1; - } - - - } - x->coeffRef(0) = x->coeff(0) / m_lu.coeffDiag(0); - - return true; -} - -} // end namespace Eigen - -#endif // EIGEN_SKYLINELU_H diff --git a/eigen/unsupported/Eigen/src/Skyline/SkylineMatrix.h b/eigen/unsupported/Eigen/src/Skyline/SkylineMatrix.h deleted file mode 100644 index a2a8933..0000000 --- a/eigen/unsupported/Eigen/src/Skyline/SkylineMatrix.h +++ /dev/null @@ -1,862 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Guillaume Saupin <guillaume.saupin@cea.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SKYLINEMATRIX_H -#define EIGEN_SKYLINEMATRIX_H - -#include "SkylineStorage.h" -#include "SkylineMatrixBase.h" - -namespace Eigen { - -/** \ingroup Skyline_Module - * - * \class SkylineMatrix - * - * \brief The main skyline matrix class - * - * This class implements a skyline matrix using the very uncommon storage - * scheme. - * - * \param _Scalar the scalar type, i.e. the type of the coefficients - * \param _Options Union of bit flags controlling the storage scheme. Currently the only possibility - * is RowMajor. The default is 0 which means column-major. - * - * - */ -namespace internal { -template<typename _Scalar, int _Options> -struct traits<SkylineMatrix<_Scalar, _Options> > { - typedef _Scalar Scalar; - typedef Sparse StorageKind; - - enum { - RowsAtCompileTime = Dynamic, - ColsAtCompileTime = Dynamic, - MaxRowsAtCompileTime = Dynamic, - MaxColsAtCompileTime = Dynamic, - Flags = SkylineBit | _Options, - CoeffReadCost = NumTraits<Scalar>::ReadCost, - }; -}; -} - -template<typename _Scalar, int _Options> -class SkylineMatrix -: public SkylineMatrixBase<SkylineMatrix<_Scalar, _Options> > { -public: - EIGEN_SKYLINE_GENERIC_PUBLIC_INTERFACE(SkylineMatrix) - EIGEN_SKYLINE_INHERIT_ASSIGNMENT_OPERATOR(SkylineMatrix, +=) - EIGEN_SKYLINE_INHERIT_ASSIGNMENT_OPERATOR(SkylineMatrix, -=) - - using Base::IsRowMajor; - -protected: - - typedef SkylineMatrix<Scalar, (Flags&~RowMajorBit) | (IsRowMajor ? RowMajorBit : 0) > TransposedSkylineMatrix; - - Index m_outerSize; - Index m_innerSize; - -public: - Index* m_colStartIndex; - Index* m_rowStartIndex; - SkylineStorage<Scalar> m_data; - -public: - - inline Index rows() const { - return IsRowMajor ? m_outerSize : m_innerSize; - } - - inline Index cols() const { - return IsRowMajor ? m_innerSize : m_outerSize; - } - - inline Index innerSize() const { - return m_innerSize; - } - - inline Index outerSize() const { - return m_outerSize; - } - - inline Index upperNonZeros() const { - return m_data.upperSize(); - } - - inline Index lowerNonZeros() const { - return m_data.lowerSize(); - } - - inline Index upperNonZeros(Index j) const { - return m_colStartIndex[j + 1] - m_colStartIndex[j]; - } - - inline Index lowerNonZeros(Index j) const { - return m_rowStartIndex[j + 1] - m_rowStartIndex[j]; - } - - inline const Scalar* _diagPtr() const { - return &m_data.diag(0); - } - - inline Scalar* _diagPtr() { - return &m_data.diag(0); - } - - inline const Scalar* _upperPtr() const { - return &m_data.upper(0); - } - - inline Scalar* _upperPtr() { - return &m_data.upper(0); - } - - inline const Scalar* _lowerPtr() const { - return &m_data.lower(0); - } - - inline Scalar* _lowerPtr() { - return &m_data.lower(0); - } - - inline const Index* _upperProfilePtr() const { - return &m_data.upperProfile(0); - } - - inline Index* _upperProfilePtr() { - return &m_data.upperProfile(0); - } - - inline const Index* _lowerProfilePtr() const { - return &m_data.lowerProfile(0); - } - - inline Index* _lowerProfilePtr() { - return &m_data.lowerProfile(0); - } - - inline Scalar coeff(Index row, Index col) const { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - - if (outer == inner) - return this->m_data.diag(outer); - - if (IsRowMajor) { - if (inner > outer) //upper matrix - { - const Index minOuterIndex = inner - m_data.upperProfile(inner); - if (outer >= minOuterIndex) - return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner))); - else - return Scalar(0); - } - if (inner < outer) //lower matrix - { - const Index minInnerIndex = outer - m_data.lowerProfile(outer); - if (inner >= minInnerIndex) - return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer))); - else - return Scalar(0); - } - return m_data.upper(m_colStartIndex[inner] + outer - inner); - } else { - if (outer > inner) //upper matrix - { - const Index maxOuterIndex = inner + m_data.upperProfile(inner); - if (outer <= maxOuterIndex) - return this->m_data.upper(m_colStartIndex[inner] + (outer - inner)); - else - return Scalar(0); - } - if (outer < inner) //lower matrix - { - const Index maxInnerIndex = outer + m_data.lowerProfile(outer); - - if (inner <= maxInnerIndex) - return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer)); - else - return Scalar(0); - } - } - } - - inline Scalar& coeffRef(Index row, Index col) { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - - if (outer == inner) - return this->m_data.diag(outer); - - if (IsRowMajor) { - if (col > row) //upper matrix - { - const Index minOuterIndex = inner - m_data.upperProfile(inner); - eigen_assert(outer >= minOuterIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner))); - } - if (col < row) //lower matrix - { - const Index minInnerIndex = outer - m_data.lowerProfile(outer); - eigen_assert(inner >= minInnerIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer))); - } - } else { - if (outer > inner) //upper matrix - { - const Index maxOuterIndex = inner + m_data.upperProfile(inner); - eigen_assert(outer <= maxOuterIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.upper(m_colStartIndex[inner] + (outer - inner)); - } - if (outer < inner) //lower matrix - { - const Index maxInnerIndex = outer + m_data.lowerProfile(outer); - eigen_assert(inner <= maxInnerIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer)); - } - } - } - - inline Scalar coeffDiag(Index idx) const { - eigen_assert(idx < outerSize()); - eigen_assert(idx < innerSize()); - return this->m_data.diag(idx); - } - - inline Scalar coeffLower(Index row, Index col) const { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - eigen_assert(inner != outer); - - if (IsRowMajor) { - const Index minInnerIndex = outer - m_data.lowerProfile(outer); - if (inner >= minInnerIndex) - return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer))); - else - return Scalar(0); - - } else { - const Index maxInnerIndex = outer + m_data.lowerProfile(outer); - if (inner <= maxInnerIndex) - return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer)); - else - return Scalar(0); - } - } - - inline Scalar coeffUpper(Index row, Index col) const { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - eigen_assert(inner != outer); - - if (IsRowMajor) { - const Index minOuterIndex = inner - m_data.upperProfile(inner); - if (outer >= minOuterIndex) - return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner))); - else - return Scalar(0); - } else { - const Index maxOuterIndex = inner + m_data.upperProfile(inner); - if (outer <= maxOuterIndex) - return this->m_data.upper(m_colStartIndex[inner] + (outer - inner)); - else - return Scalar(0); - } - } - - inline Scalar& coeffRefDiag(Index idx) { - eigen_assert(idx < outerSize()); - eigen_assert(idx < innerSize()); - return this->m_data.diag(idx); - } - - inline Scalar& coeffRefLower(Index row, Index col) { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - eigen_assert(inner != outer); - - if (IsRowMajor) { - const Index minInnerIndex = outer - m_data.lowerProfile(outer); - eigen_assert(inner >= minInnerIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer))); - } else { - const Index maxInnerIndex = outer + m_data.lowerProfile(outer); - eigen_assert(inner <= maxInnerIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.lower(m_rowStartIndex[outer] + (inner - outer)); - } - } - - inline bool coeffExistLower(Index row, Index col) { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - eigen_assert(inner != outer); - - if (IsRowMajor) { - const Index minInnerIndex = outer - m_data.lowerProfile(outer); - return inner >= minInnerIndex; - } else { - const Index maxInnerIndex = outer + m_data.lowerProfile(outer); - return inner <= maxInnerIndex; - } - } - - inline Scalar& coeffRefUpper(Index row, Index col) { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - eigen_assert(inner != outer); - - if (IsRowMajor) { - const Index minOuterIndex = inner - m_data.upperProfile(inner); - eigen_assert(outer >= minOuterIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner))); - } else { - const Index maxOuterIndex = inner + m_data.upperProfile(inner); - eigen_assert(outer <= maxOuterIndex && "you try to acces a coeff that do not exist in the storage"); - return this->m_data.upper(m_colStartIndex[inner] + (outer - inner)); - } - } - - inline bool coeffExistUpper(Index row, Index col) { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - eigen_assert(inner != outer); - - if (IsRowMajor) { - const Index minOuterIndex = inner - m_data.upperProfile(inner); - return outer >= minOuterIndex; - } else { - const Index maxOuterIndex = inner + m_data.upperProfile(inner); - return outer <= maxOuterIndex; - } - } - - -protected: - -public: - class InnerUpperIterator; - class InnerLowerIterator; - - class OuterUpperIterator; - class OuterLowerIterator; - - /** Removes all non zeros */ - inline void setZero() { - m_data.clear(); - memset(m_colStartIndex, 0, (m_outerSize + 1) * sizeof (Index)); - memset(m_rowStartIndex, 0, (m_outerSize + 1) * sizeof (Index)); - } - - /** \returns the number of non zero coefficients */ - inline Index nonZeros() const { - return m_data.diagSize() + m_data.upperSize() + m_data.lowerSize(); - } - - /** Preallocates \a reserveSize non zeros */ - inline void reserve(Index reserveSize, Index reserveUpperSize, Index reserveLowerSize) { - m_data.reserve(reserveSize, reserveUpperSize, reserveLowerSize); - } - - /** \returns a reference to a novel non zero coefficient with coordinates \a row x \a col. - - * - * \warning This function can be extremely slow if the non zero coefficients - * are not inserted in a coherent order. - * - * After an insertion session, you should call the finalize() function. - */ - EIGEN_DONT_INLINE Scalar & insert(Index row, Index col) { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - eigen_assert(outer < outerSize()); - eigen_assert(inner < innerSize()); - - if (outer == inner) - return m_data.diag(col); - - if (IsRowMajor) { - if (outer < inner) //upper matrix - { - Index minOuterIndex = 0; - minOuterIndex = inner - m_data.upperProfile(inner); - - if (outer < minOuterIndex) //The value does not yet exist - { - const Index previousProfile = m_data.upperProfile(inner); - - m_data.upperProfile(inner) = inner - outer; - - - const Index bandIncrement = m_data.upperProfile(inner) - previousProfile; - //shift data stored after this new one - const Index stop = m_colStartIndex[cols()]; - const Index start = m_colStartIndex[inner]; - - - for (Index innerIdx = stop; innerIdx >= start; innerIdx--) { - m_data.upper(innerIdx + bandIncrement) = m_data.upper(innerIdx); - } - - for (Index innerIdx = cols(); innerIdx > inner; innerIdx--) { - m_colStartIndex[innerIdx] += bandIncrement; - } - - //zeros new data - memset(this->_upperPtr() + start, 0, (bandIncrement - 1) * sizeof (Scalar)); - - return m_data.upper(m_colStartIndex[inner]); - } else { - return m_data.upper(m_colStartIndex[inner] + outer - (inner - m_data.upperProfile(inner))); - } - } - - if (outer > inner) //lower matrix - { - const Index minInnerIndex = outer - m_data.lowerProfile(outer); - if (inner < minInnerIndex) //The value does not yet exist - { - const Index previousProfile = m_data.lowerProfile(outer); - m_data.lowerProfile(outer) = outer - inner; - - const Index bandIncrement = m_data.lowerProfile(outer) - previousProfile; - //shift data stored after this new one - const Index stop = m_rowStartIndex[rows()]; - const Index start = m_rowStartIndex[outer]; - - - for (Index innerIdx = stop; innerIdx >= start; innerIdx--) { - m_data.lower(innerIdx + bandIncrement) = m_data.lower(innerIdx); - } - - for (Index innerIdx = rows(); innerIdx > outer; innerIdx--) { - m_rowStartIndex[innerIdx] += bandIncrement; - } - - //zeros new data - memset(this->_lowerPtr() + start, 0, (bandIncrement - 1) * sizeof (Scalar)); - return m_data.lower(m_rowStartIndex[outer]); - } else { - return m_data.lower(m_rowStartIndex[outer] + inner - (outer - m_data.lowerProfile(outer))); - } - } - } else { - if (outer > inner) //upper matrix - { - const Index maxOuterIndex = inner + m_data.upperProfile(inner); - if (outer > maxOuterIndex) //The value does not yet exist - { - const Index previousProfile = m_data.upperProfile(inner); - m_data.upperProfile(inner) = outer - inner; - - const Index bandIncrement = m_data.upperProfile(inner) - previousProfile; - //shift data stored after this new one - const Index stop = m_rowStartIndex[rows()]; - const Index start = m_rowStartIndex[inner + 1]; - - for (Index innerIdx = stop; innerIdx >= start; innerIdx--) { - m_data.upper(innerIdx + bandIncrement) = m_data.upper(innerIdx); - } - - for (Index innerIdx = inner + 1; innerIdx < outerSize() + 1; innerIdx++) { - m_rowStartIndex[innerIdx] += bandIncrement; - } - memset(this->_upperPtr() + m_rowStartIndex[inner] + previousProfile + 1, 0, (bandIncrement - 1) * sizeof (Scalar)); - return m_data.upper(m_rowStartIndex[inner] + m_data.upperProfile(inner)); - } else { - return m_data.upper(m_rowStartIndex[inner] + (outer - inner)); - } - } - - if (outer < inner) //lower matrix - { - const Index maxInnerIndex = outer + m_data.lowerProfile(outer); - if (inner > maxInnerIndex) //The value does not yet exist - { - const Index previousProfile = m_data.lowerProfile(outer); - m_data.lowerProfile(outer) = inner - outer; - - const Index bandIncrement = m_data.lowerProfile(outer) - previousProfile; - //shift data stored after this new one - const Index stop = m_colStartIndex[cols()]; - const Index start = m_colStartIndex[outer + 1]; - - for (Index innerIdx = stop; innerIdx >= start; innerIdx--) { - m_data.lower(innerIdx + bandIncrement) = m_data.lower(innerIdx); - } - - for (Index innerIdx = outer + 1; innerIdx < outerSize() + 1; innerIdx++) { - m_colStartIndex[innerIdx] += bandIncrement; - } - memset(this->_lowerPtr() + m_colStartIndex[outer] + previousProfile + 1, 0, (bandIncrement - 1) * sizeof (Scalar)); - return m_data.lower(m_colStartIndex[outer] + m_data.lowerProfile(outer)); - } else { - return m_data.lower(m_colStartIndex[outer] + (inner - outer)); - } - } - } - } - - /** Must be called after inserting a set of non zero entries. - */ - inline void finalize() { - if (IsRowMajor) { - if (rows() > cols()) - m_data.resize(cols(), cols(), rows(), m_colStartIndex[cols()] + 1, m_rowStartIndex[rows()] + 1); - else - m_data.resize(rows(), cols(), rows(), m_colStartIndex[cols()] + 1, m_rowStartIndex[rows()] + 1); - - // eigen_assert(rows() == cols() && "memory reorganisatrion only works with suare matrix"); - // - // Scalar* newArray = new Scalar[m_colStartIndex[cols()] + 1 + m_rowStartIndex[rows()] + 1]; - // Index dataIdx = 0; - // for (Index row = 0; row < rows(); row++) { - // - // const Index nbLowerElts = m_rowStartIndex[row + 1] - m_rowStartIndex[row]; - // // std::cout << "nbLowerElts" << nbLowerElts << std::endl; - // memcpy(newArray + dataIdx, m_data.m_lower + m_rowStartIndex[row], nbLowerElts * sizeof (Scalar)); - // m_rowStartIndex[row] = dataIdx; - // dataIdx += nbLowerElts; - // - // const Index nbUpperElts = m_colStartIndex[row + 1] - m_colStartIndex[row]; - // memcpy(newArray + dataIdx, m_data.m_upper + m_colStartIndex[row], nbUpperElts * sizeof (Scalar)); - // m_colStartIndex[row] = dataIdx; - // dataIdx += nbUpperElts; - // - // - // } - // //todo : don't access m_data profile directly : add an accessor from SkylineMatrix - // m_rowStartIndex[rows()] = m_rowStartIndex[rows()-1] + m_data.lowerProfile(rows()-1); - // m_colStartIndex[cols()] = m_colStartIndex[cols()-1] + m_data.upperProfile(cols()-1); - // - // delete[] m_data.m_lower; - // delete[] m_data.m_upper; - // - // m_data.m_lower = newArray; - // m_data.m_upper = newArray; - } else { - if (rows() > cols()) - m_data.resize(cols(), rows(), cols(), m_rowStartIndex[cols()] + 1, m_colStartIndex[cols()] + 1); - else - m_data.resize(rows(), rows(), cols(), m_rowStartIndex[rows()] + 1, m_colStartIndex[rows()] + 1); - } - } - - inline void squeeze() { - finalize(); - m_data.squeeze(); - } - - void prune(Scalar reference, RealScalar epsilon = dummy_precision<RealScalar > ()) { - //TODO - } - - /** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero - * \sa resizeNonZeros(Index), reserve(), setZero() - */ - void resize(size_t rows, size_t cols) { - const Index diagSize = rows > cols ? cols : rows; - m_innerSize = IsRowMajor ? cols : rows; - - eigen_assert(rows == cols && "Skyline matrix must be square matrix"); - - if (diagSize % 2) { // diagSize is odd - const Index k = (diagSize - 1) / 2; - - m_data.resize(diagSize, IsRowMajor ? cols : rows, IsRowMajor ? rows : cols, - 2 * k * k + k + 1, - 2 * k * k + k + 1); - - } else // diagSize is even - { - const Index k = diagSize / 2; - m_data.resize(diagSize, IsRowMajor ? cols : rows, IsRowMajor ? rows : cols, - 2 * k * k - k + 1, - 2 * k * k - k + 1); - } - - if (m_colStartIndex && m_rowStartIndex) { - delete[] m_colStartIndex; - delete[] m_rowStartIndex; - } - m_colStartIndex = new Index [cols + 1]; - m_rowStartIndex = new Index [rows + 1]; - m_outerSize = diagSize; - - m_data.reset(); - m_data.clear(); - - m_outerSize = diagSize; - memset(m_colStartIndex, 0, (cols + 1) * sizeof (Index)); - memset(m_rowStartIndex, 0, (rows + 1) * sizeof (Index)); - } - - void resizeNonZeros(Index size) { - m_data.resize(size); - } - - inline SkylineMatrix() - : m_outerSize(-1), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) { - resize(0, 0); - } - - inline SkylineMatrix(size_t rows, size_t cols) - : m_outerSize(0), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) { - resize(rows, cols); - } - - template<typename OtherDerived> - inline SkylineMatrix(const SkylineMatrixBase<OtherDerived>& other) - : m_outerSize(0), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) { - *this = other.derived(); - } - - inline SkylineMatrix(const SkylineMatrix & other) - : Base(), m_outerSize(0), m_innerSize(0), m_colStartIndex(0), m_rowStartIndex(0) { - *this = other.derived(); - } - - inline void swap(SkylineMatrix & other) { - //EIGEN_DBG_SKYLINE(std::cout << "SkylineMatrix:: swap\n"); - std::swap(m_colStartIndex, other.m_colStartIndex); - std::swap(m_rowStartIndex, other.m_rowStartIndex); - std::swap(m_innerSize, other.m_innerSize); - std::swap(m_outerSize, other.m_outerSize); - m_data.swap(other.m_data); - } - - inline SkylineMatrix & operator=(const SkylineMatrix & other) { - std::cout << "SkylineMatrix& operator=(const SkylineMatrix& other)\n"; - if (other.isRValue()) { - swap(other.const_cast_derived()); - } else { - resize(other.rows(), other.cols()); - memcpy(m_colStartIndex, other.m_colStartIndex, (m_outerSize + 1) * sizeof (Index)); - memcpy(m_rowStartIndex, other.m_rowStartIndex, (m_outerSize + 1) * sizeof (Index)); - m_data = other.m_data; - } - return *this; - } - - template<typename OtherDerived> - inline SkylineMatrix & operator=(const SkylineMatrixBase<OtherDerived>& other) { - const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); - if (needToTranspose) { - // TODO - // return *this; - } else { - // there is no special optimization - return SkylineMatrixBase<SkylineMatrix>::operator=(other.derived()); - } - } - - friend std::ostream & operator <<(std::ostream & s, const SkylineMatrix & m) { - - EIGEN_DBG_SKYLINE( - std::cout << "upper elements : " << std::endl; - for (Index i = 0; i < m.m_data.upperSize(); i++) - std::cout << m.m_data.upper(i) << "\t"; - std::cout << std::endl; - std::cout << "upper profile : " << std::endl; - for (Index i = 0; i < m.m_data.upperProfileSize(); i++) - std::cout << m.m_data.upperProfile(i) << "\t"; - std::cout << std::endl; - std::cout << "lower startIdx : " << std::endl; - for (Index i = 0; i < m.m_data.upperProfileSize(); i++) - std::cout << (IsRowMajor ? m.m_colStartIndex[i] : m.m_rowStartIndex[i]) << "\t"; - std::cout << std::endl; - - - std::cout << "lower elements : " << std::endl; - for (Index i = 0; i < m.m_data.lowerSize(); i++) - std::cout << m.m_data.lower(i) << "\t"; - std::cout << std::endl; - std::cout << "lower profile : " << std::endl; - for (Index i = 0; i < m.m_data.lowerProfileSize(); i++) - std::cout << m.m_data.lowerProfile(i) << "\t"; - std::cout << std::endl; - std::cout << "lower startIdx : " << std::endl; - for (Index i = 0; i < m.m_data.lowerProfileSize(); i++) - std::cout << (IsRowMajor ? m.m_rowStartIndex[i] : m.m_colStartIndex[i]) << "\t"; - std::cout << std::endl; - ); - for (Index rowIdx = 0; rowIdx < m.rows(); rowIdx++) { - for (Index colIdx = 0; colIdx < m.cols(); colIdx++) { - s << m.coeff(rowIdx, colIdx) << "\t"; - } - s << std::endl; - } - return s; - } - - /** Destructor */ - inline ~SkylineMatrix() { - delete[] m_colStartIndex; - delete[] m_rowStartIndex; - } - - /** Overloaded for performance */ - Scalar sum() const; -}; - -template<typename Scalar, int _Options> -class SkylineMatrix<Scalar, _Options>::InnerUpperIterator { -public: - - InnerUpperIterator(const SkylineMatrix& mat, Index outer) - : m_matrix(mat), m_outer(outer), - m_id(_Options == RowMajor ? mat.m_colStartIndex[outer] : mat.m_rowStartIndex[outer] + 1), - m_start(m_id), - m_end(_Options == RowMajor ? mat.m_colStartIndex[outer + 1] : mat.m_rowStartIndex[outer + 1] + 1) { - } - - inline InnerUpperIterator & operator++() { - m_id++; - return *this; - } - - inline InnerUpperIterator & operator+=(Index shift) { - m_id += shift; - return *this; - } - - inline Scalar value() const { - return m_matrix.m_data.upper(m_id); - } - - inline Scalar* valuePtr() { - return const_cast<Scalar*> (&(m_matrix.m_data.upper(m_id))); - } - - inline Scalar& valueRef() { - return const_cast<Scalar&> (m_matrix.m_data.upper(m_id)); - } - - inline Index index() const { - return IsRowMajor ? m_outer - m_matrix.m_data.upperProfile(m_outer) + (m_id - m_start) : - m_outer + (m_id - m_start) + 1; - } - - inline Index row() const { - return IsRowMajor ? index() : m_outer; - } - - inline Index col() const { - return IsRowMajor ? m_outer : index(); - } - - inline size_t size() const { - return m_matrix.m_data.upperProfile(m_outer); - } - - inline operator bool() const { - return (m_id < m_end) && (m_id >= m_start); - } - -protected: - const SkylineMatrix& m_matrix; - const Index m_outer; - Index m_id; - const Index m_start; - const Index m_end; -}; - -template<typename Scalar, int _Options> -class SkylineMatrix<Scalar, _Options>::InnerLowerIterator { -public: - - InnerLowerIterator(const SkylineMatrix& mat, Index outer) - : m_matrix(mat), - m_outer(outer), - m_id(_Options == RowMajor ? mat.m_rowStartIndex[outer] : mat.m_colStartIndex[outer] + 1), - m_start(m_id), - m_end(_Options == RowMajor ? mat.m_rowStartIndex[outer + 1] : mat.m_colStartIndex[outer + 1] + 1) { - } - - inline InnerLowerIterator & operator++() { - m_id++; - return *this; - } - - inline InnerLowerIterator & operator+=(Index shift) { - m_id += shift; - return *this; - } - - inline Scalar value() const { - return m_matrix.m_data.lower(m_id); - } - - inline Scalar* valuePtr() { - return const_cast<Scalar*> (&(m_matrix.m_data.lower(m_id))); - } - - inline Scalar& valueRef() { - return const_cast<Scalar&> (m_matrix.m_data.lower(m_id)); - } - - inline Index index() const { - return IsRowMajor ? m_outer - m_matrix.m_data.lowerProfile(m_outer) + (m_id - m_start) : - m_outer + (m_id - m_start) + 1; - ; - } - - inline Index row() const { - return IsRowMajor ? m_outer : index(); - } - - inline Index col() const { - return IsRowMajor ? index() : m_outer; - } - - inline size_t size() const { - return m_matrix.m_data.lowerProfile(m_outer); - } - - inline operator bool() const { - return (m_id < m_end) && (m_id >= m_start); - } - -protected: - const SkylineMatrix& m_matrix; - const Index m_outer; - Index m_id; - const Index m_start; - const Index m_end; -}; - -} // end namespace Eigen - -#endif // EIGEN_SkylineMatrix_H diff --git a/eigen/unsupported/Eigen/src/Skyline/SkylineMatrixBase.h b/eigen/unsupported/Eigen/src/Skyline/SkylineMatrixBase.h deleted file mode 100644 index b3a2372..0000000 --- a/eigen/unsupported/Eigen/src/Skyline/SkylineMatrixBase.h +++ /dev/null @@ -1,212 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Guillaume Saupin <guillaume.saupin@cea.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SKYLINEMATRIXBASE_H -#define EIGEN_SKYLINEMATRIXBASE_H - -#include "SkylineUtil.h" - -namespace Eigen { - -/** \ingroup Skyline_Module - * - * \class SkylineMatrixBase - * - * \brief Base class of any skyline matrices or skyline expressions - * - * \param Derived - * - */ -template<typename Derived> class SkylineMatrixBase : public EigenBase<Derived> { -public: - - typedef typename internal::traits<Derived>::Scalar Scalar; - typedef typename internal::traits<Derived>::StorageKind StorageKind; - typedef typename internal::index<StorageKind>::type Index; - - enum { - RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime, - /**< The number of rows at compile-time. This is just a copy of the value provided - * by the \a Derived type. If a value is not known at compile-time, - * it is set to the \a Dynamic constant. - * \sa MatrixBase::rows(), MatrixBase::cols(), ColsAtCompileTime, SizeAtCompileTime */ - - ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime, - /**< The number of columns at compile-time. This is just a copy of the value provided - * by the \a Derived type. If a value is not known at compile-time, - * it is set to the \a Dynamic constant. - * \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */ - - - SizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::RowsAtCompileTime, - internal::traits<Derived>::ColsAtCompileTime>::ret), - /**< This is equal to the number of coefficients, i.e. the number of - * rows times the number of columns, or to \a Dynamic if this is not - * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */ - - MaxRowsAtCompileTime = RowsAtCompileTime, - MaxColsAtCompileTime = ColsAtCompileTime, - - MaxSizeAtCompileTime = (internal::size_at_compile_time<MaxRowsAtCompileTime, - MaxColsAtCompileTime>::ret), - - IsVectorAtCompileTime = RowsAtCompileTime == 1 || ColsAtCompileTime == 1, - /**< This is set to true if either the number of rows or the number of - * columns is known at compile-time to be equal to 1. Indeed, in that case, - * we are dealing with a column-vector (if there is only one column) or with - * a row-vector (if there is only one row). */ - - Flags = internal::traits<Derived>::Flags, - /**< This stores expression \ref flags flags which may or may not be inherited by new expressions - * constructed from this one. See the \ref flags "list of flags". - */ - - CoeffReadCost = internal::traits<Derived>::CoeffReadCost, - /**< This is a rough measure of how expensive it is to read one coefficient from - * this expression. - */ - - IsRowMajor = Flags & RowMajorBit ? 1 : 0 - }; - -#ifndef EIGEN_PARSED_BY_DOXYGEN - /** This is the "real scalar" type; if the \a Scalar type is already real numbers - * (e.g. int, float or double) then \a RealScalar is just the same as \a Scalar. If - * \a Scalar is \a std::complex<T> then RealScalar is \a T. - * - * \sa class NumTraits - */ - typedef typename NumTraits<Scalar>::Real RealScalar; - - /** type of the equivalent square matrix */ - typedef Matrix<Scalar, EIGEN_SIZE_MAX(RowsAtCompileTime, ColsAtCompileTime), - EIGEN_SIZE_MAX(RowsAtCompileTime, ColsAtCompileTime) > SquareMatrixType; - - inline const Derived& derived() const { - return *static_cast<const Derived*> (this); - } - - inline Derived& derived() { - return *static_cast<Derived*> (this); - } - - inline Derived& const_cast_derived() const { - return *static_cast<Derived*> (const_cast<SkylineMatrixBase*> (this)); - } -#endif // not EIGEN_PARSED_BY_DOXYGEN - - /** \returns the number of rows. \sa cols(), RowsAtCompileTime */ - inline Index rows() const { - return derived().rows(); - } - - /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/ - inline Index cols() const { - return derived().cols(); - } - - /** \returns the number of coefficients, which is \a rows()*cols(). - * \sa rows(), cols(), SizeAtCompileTime. */ - inline Index size() const { - return rows() * cols(); - } - - /** \returns the number of nonzero coefficients which is in practice the number - * of stored coefficients. */ - inline Index nonZeros() const { - return derived().nonZeros(); - } - - /** \returns the size of the storage major dimension, - * i.e., the number of columns for a columns major matrix, and the number of rows otherwise */ - Index outerSize() const { - return (int(Flags) & RowMajorBit) ? this->rows() : this->cols(); - } - - /** \returns the size of the inner dimension according to the storage order, - * i.e., the number of rows for a columns major matrix, and the number of cols otherwise */ - Index innerSize() const { - return (int(Flags) & RowMajorBit) ? this->cols() : this->rows(); - } - - bool isRValue() const { - return m_isRValue; - } - - Derived& markAsRValue() { - m_isRValue = true; - return derived(); - } - - SkylineMatrixBase() : m_isRValue(false) { - /* TODO check flags */ - } - - inline Derived & operator=(const Derived& other) { - this->operator=<Derived > (other); - return derived(); - } - - template<typename OtherDerived> - inline void assignGeneric(const OtherDerived& other) { - derived().resize(other.rows(), other.cols()); - for (Index row = 0; row < rows(); row++) - for (Index col = 0; col < cols(); col++) { - if (other.coeff(row, col) != Scalar(0)) - derived().insert(row, col) = other.coeff(row, col); - } - derived().finalize(); - } - - template<typename OtherDerived> - inline Derived & operator=(const SkylineMatrixBase<OtherDerived>& other) { - //TODO - } - - template<typename Lhs, typename Rhs> - inline Derived & operator=(const SkylineProduct<Lhs, Rhs, SkylineTimeSkylineProduct>& product); - - friend std::ostream & operator <<(std::ostream & s, const SkylineMatrixBase& m) { - s << m.derived(); - return s; - } - - template<typename OtherDerived> - const typename SkylineProductReturnType<Derived, OtherDerived>::Type - operator*(const MatrixBase<OtherDerived> &other) const; - - /** \internal use operator= */ - template<typename DenseDerived> - void evalTo(MatrixBase<DenseDerived>& dst) const { - dst.setZero(); - for (Index i = 0; i < rows(); i++) - for (Index j = 0; j < rows(); j++) - dst(i, j) = derived().coeff(i, j); - } - - Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime> toDense() const { - return derived(); - } - - /** \returns the matrix or vector obtained by evaluating this expression. - * - * Notice that in the case of a plain matrix or vector (not an expression) this function just returns - * a const reference, in order to avoid a useless copy. - */ - EIGEN_STRONG_INLINE const typename internal::eval<Derived, IsSkyline>::type eval() const { - return typename internal::eval<Derived>::type(derived()); - } - -protected: - bool m_isRValue; -}; - -} // end namespace Eigen - -#endif // EIGEN_SkylineMatrixBase_H diff --git a/eigen/unsupported/Eigen/src/Skyline/SkylineProduct.h b/eigen/unsupported/Eigen/src/Skyline/SkylineProduct.h deleted file mode 100644 index d9eb814..0000000 --- a/eigen/unsupported/Eigen/src/Skyline/SkylineProduct.h +++ /dev/null @@ -1,295 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Guillaume Saupin <guillaume.saupin@cea.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SKYLINEPRODUCT_H -#define EIGEN_SKYLINEPRODUCT_H - -namespace Eigen { - -template<typename Lhs, typename Rhs, int ProductMode> -struct SkylineProductReturnType { - typedef const typename internal::nested_eval<Lhs, Rhs::RowsAtCompileTime>::type LhsNested; - typedef const typename internal::nested_eval<Rhs, Lhs::RowsAtCompileTime>::type RhsNested; - - typedef SkylineProduct<LhsNested, RhsNested, ProductMode> Type; -}; - -template<typename LhsNested, typename RhsNested, int ProductMode> -struct internal::traits<SkylineProduct<LhsNested, RhsNested, ProductMode> > { - // clean the nested types: - typedef typename internal::remove_all<LhsNested>::type _LhsNested; - typedef typename internal::remove_all<RhsNested>::type _RhsNested; - typedef typename _LhsNested::Scalar Scalar; - - enum { - LhsCoeffReadCost = _LhsNested::CoeffReadCost, - RhsCoeffReadCost = _RhsNested::CoeffReadCost, - LhsFlags = _LhsNested::Flags, - RhsFlags = _RhsNested::Flags, - - RowsAtCompileTime = _LhsNested::RowsAtCompileTime, - ColsAtCompileTime = _RhsNested::ColsAtCompileTime, - InnerSize = EIGEN_SIZE_MIN_PREFER_FIXED(_LhsNested::ColsAtCompileTime, _RhsNested::RowsAtCompileTime), - - MaxRowsAtCompileTime = _LhsNested::MaxRowsAtCompileTime, - MaxColsAtCompileTime = _RhsNested::MaxColsAtCompileTime, - - EvalToRowMajor = (RhsFlags & LhsFlags & RowMajorBit), - ResultIsSkyline = ProductMode == SkylineTimeSkylineProduct, - - RemovedBits = ~((EvalToRowMajor ? 0 : RowMajorBit) | (ResultIsSkyline ? 0 : SkylineBit)), - - Flags = (int(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits) - | EvalBeforeAssigningBit - | EvalBeforeNestingBit, - - CoeffReadCost = HugeCost - }; - - typedef typename internal::conditional<ResultIsSkyline, - SkylineMatrixBase<SkylineProduct<LhsNested, RhsNested, ProductMode> >, - MatrixBase<SkylineProduct<LhsNested, RhsNested, ProductMode> > >::type Base; -}; - -namespace internal { -template<typename LhsNested, typename RhsNested, int ProductMode> -class SkylineProduct : no_assignment_operator, -public traits<SkylineProduct<LhsNested, RhsNested, ProductMode> >::Base { -public: - - EIGEN_GENERIC_PUBLIC_INTERFACE(SkylineProduct) - -private: - - typedef typename traits<SkylineProduct>::_LhsNested _LhsNested; - typedef typename traits<SkylineProduct>::_RhsNested _RhsNested; - -public: - - template<typename Lhs, typename Rhs> - EIGEN_STRONG_INLINE SkylineProduct(const Lhs& lhs, const Rhs& rhs) - : m_lhs(lhs), m_rhs(rhs) { - eigen_assert(lhs.cols() == rhs.rows()); - - enum { - ProductIsValid = _LhsNested::ColsAtCompileTime == Dynamic - || _RhsNested::RowsAtCompileTime == Dynamic - || int(_LhsNested::ColsAtCompileTime) == int(_RhsNested::RowsAtCompileTime), - AreVectors = _LhsNested::IsVectorAtCompileTime && _RhsNested::IsVectorAtCompileTime, - SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(_LhsNested, _RhsNested) - }; - // note to the lost user: - // * for a dot product use: v1.dot(v2) - // * for a coeff-wise product use: v1.cwise()*v2 - EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes), - INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) - EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), - INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) - EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) - } - - EIGEN_STRONG_INLINE Index rows() const { - return m_lhs.rows(); - } - - EIGEN_STRONG_INLINE Index cols() const { - return m_rhs.cols(); - } - - EIGEN_STRONG_INLINE const _LhsNested& lhs() const { - return m_lhs; - } - - EIGEN_STRONG_INLINE const _RhsNested& rhs() const { - return m_rhs; - } - -protected: - LhsNested m_lhs; - RhsNested m_rhs; -}; - -// dense = skyline * dense -// Note that here we force no inlining and separate the setZero() because GCC messes up otherwise - -template<typename Lhs, typename Rhs, typename Dest> -EIGEN_DONT_INLINE void skyline_row_major_time_dense_product(const Lhs& lhs, const Rhs& rhs, Dest& dst) { - typedef typename remove_all<Lhs>::type _Lhs; - typedef typename remove_all<Rhs>::type _Rhs; - typedef typename traits<Lhs>::Scalar Scalar; - - enum { - LhsIsRowMajor = (_Lhs::Flags & RowMajorBit) == RowMajorBit, - LhsIsSelfAdjoint = (_Lhs::Flags & SelfAdjointBit) == SelfAdjointBit, - ProcessFirstHalf = LhsIsSelfAdjoint - && (((_Lhs::Flags & (UpperTriangularBit | LowerTriangularBit)) == 0) - || ((_Lhs::Flags & UpperTriangularBit) && !LhsIsRowMajor) - || ((_Lhs::Flags & LowerTriangularBit) && LhsIsRowMajor)), - ProcessSecondHalf = LhsIsSelfAdjoint && (!ProcessFirstHalf) - }; - - //Use matrix diagonal part <- Improvement : use inner iterator on dense matrix. - for (Index col = 0; col < rhs.cols(); col++) { - for (Index row = 0; row < lhs.rows(); row++) { - dst(row, col) = lhs.coeffDiag(row) * rhs(row, col); - } - } - //Use matrix lower triangular part - for (Index row = 0; row < lhs.rows(); row++) { - typename _Lhs::InnerLowerIterator lIt(lhs, row); - const Index stop = lIt.col() + lIt.size(); - for (Index col = 0; col < rhs.cols(); col++) { - - Index k = lIt.col(); - Scalar tmp = 0; - while (k < stop) { - tmp += - lIt.value() * - rhs(k++, col); - ++lIt; - } - dst(row, col) += tmp; - lIt += -lIt.size(); - } - - } - - //Use matrix upper triangular part - for (Index lhscol = 0; lhscol < lhs.cols(); lhscol++) { - typename _Lhs::InnerUpperIterator uIt(lhs, lhscol); - const Index stop = uIt.size() + uIt.row(); - for (Index rhscol = 0; rhscol < rhs.cols(); rhscol++) { - - - const Scalar rhsCoeff = rhs.coeff(lhscol, rhscol); - Index k = uIt.row(); - while (k < stop) { - dst(k++, rhscol) += - uIt.value() * - rhsCoeff; - ++uIt; - } - uIt += -uIt.size(); - } - } - -} - -template<typename Lhs, typename Rhs, typename Dest> -EIGEN_DONT_INLINE void skyline_col_major_time_dense_product(const Lhs& lhs, const Rhs& rhs, Dest& dst) { - typedef typename remove_all<Lhs>::type _Lhs; - typedef typename remove_all<Rhs>::type _Rhs; - typedef typename traits<Lhs>::Scalar Scalar; - - enum { - LhsIsRowMajor = (_Lhs::Flags & RowMajorBit) == RowMajorBit, - LhsIsSelfAdjoint = (_Lhs::Flags & SelfAdjointBit) == SelfAdjointBit, - ProcessFirstHalf = LhsIsSelfAdjoint - && (((_Lhs::Flags & (UpperTriangularBit | LowerTriangularBit)) == 0) - || ((_Lhs::Flags & UpperTriangularBit) && !LhsIsRowMajor) - || ((_Lhs::Flags & LowerTriangularBit) && LhsIsRowMajor)), - ProcessSecondHalf = LhsIsSelfAdjoint && (!ProcessFirstHalf) - }; - - //Use matrix diagonal part <- Improvement : use inner iterator on dense matrix. - for (Index col = 0; col < rhs.cols(); col++) { - for (Index row = 0; row < lhs.rows(); row++) { - dst(row, col) = lhs.coeffDiag(row) * rhs(row, col); - } - } - - //Use matrix upper triangular part - for (Index row = 0; row < lhs.rows(); row++) { - typename _Lhs::InnerUpperIterator uIt(lhs, row); - const Index stop = uIt.col() + uIt.size(); - for (Index col = 0; col < rhs.cols(); col++) { - - Index k = uIt.col(); - Scalar tmp = 0; - while (k < stop) { - tmp += - uIt.value() * - rhs(k++, col); - ++uIt; - } - - - dst(row, col) += tmp; - uIt += -uIt.size(); - } - } - - //Use matrix lower triangular part - for (Index lhscol = 0; lhscol < lhs.cols(); lhscol++) { - typename _Lhs::InnerLowerIterator lIt(lhs, lhscol); - const Index stop = lIt.size() + lIt.row(); - for (Index rhscol = 0; rhscol < rhs.cols(); rhscol++) { - - const Scalar rhsCoeff = rhs.coeff(lhscol, rhscol); - Index k = lIt.row(); - while (k < stop) { - dst(k++, rhscol) += - lIt.value() * - rhsCoeff; - ++lIt; - } - lIt += -lIt.size(); - } - } - -} - -template<typename Lhs, typename Rhs, typename ResultType, - int LhsStorageOrder = traits<Lhs>::Flags&RowMajorBit> - struct skyline_product_selector; - -template<typename Lhs, typename Rhs, typename ResultType> -struct skyline_product_selector<Lhs, Rhs, ResultType, RowMajor> { - typedef typename traits<typename remove_all<Lhs>::type>::Scalar Scalar; - - static void run(const Lhs& lhs, const Rhs& rhs, ResultType & res) { - skyline_row_major_time_dense_product<Lhs, Rhs, ResultType > (lhs, rhs, res); - } -}; - -template<typename Lhs, typename Rhs, typename ResultType> -struct skyline_product_selector<Lhs, Rhs, ResultType, ColMajor> { - typedef typename traits<typename remove_all<Lhs>::type>::Scalar Scalar; - - static void run(const Lhs& lhs, const Rhs& rhs, ResultType & res) { - skyline_col_major_time_dense_product<Lhs, Rhs, ResultType > (lhs, rhs, res); - } -}; - -} // end namespace internal - -// template<typename Derived> -// template<typename Lhs, typename Rhs > -// Derived & MatrixBase<Derived>::lazyAssign(const SkylineProduct<Lhs, Rhs, SkylineTimeDenseProduct>& product) { -// typedef typename internal::remove_all<Lhs>::type _Lhs; -// internal::skyline_product_selector<typename internal::remove_all<Lhs>::type, -// typename internal::remove_all<Rhs>::type, -// Derived>::run(product.lhs(), product.rhs(), derived()); -// -// return derived(); -// } - -// skyline * dense - -template<typename Derived> -template<typename OtherDerived > -EIGEN_STRONG_INLINE const typename SkylineProductReturnType<Derived, OtherDerived>::Type -SkylineMatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const { - - return typename SkylineProductReturnType<Derived, OtherDerived>::Type(derived(), other.derived()); -} - -} // end namespace Eigen - -#endif // EIGEN_SKYLINEPRODUCT_H diff --git a/eigen/unsupported/Eigen/src/Skyline/SkylineStorage.h b/eigen/unsupported/Eigen/src/Skyline/SkylineStorage.h deleted file mode 100644 index 378a8de..0000000 --- a/eigen/unsupported/Eigen/src/Skyline/SkylineStorage.h +++ /dev/null @@ -1,259 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Guillaume Saupin <guillaume.saupin@cea.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SKYLINE_STORAGE_H -#define EIGEN_SKYLINE_STORAGE_H - -namespace Eigen { - -/** Stores a skyline set of values in three structures : - * The diagonal elements - * The upper elements - * The lower elements - * - */ -template<typename Scalar> -class SkylineStorage { - typedef typename NumTraits<Scalar>::Real RealScalar; - typedef SparseIndex Index; -public: - - SkylineStorage() - : m_diag(0), - m_lower(0), - m_upper(0), - m_lowerProfile(0), - m_upperProfile(0), - m_diagSize(0), - m_upperSize(0), - m_lowerSize(0), - m_upperProfileSize(0), - m_lowerProfileSize(0), - m_allocatedSize(0) { - } - - SkylineStorage(const SkylineStorage& other) - : m_diag(0), - m_lower(0), - m_upper(0), - m_lowerProfile(0), - m_upperProfile(0), - m_diagSize(0), - m_upperSize(0), - m_lowerSize(0), - m_upperProfileSize(0), - m_lowerProfileSize(0), - m_allocatedSize(0) { - *this = other; - } - - SkylineStorage & operator=(const SkylineStorage& other) { - resize(other.diagSize(), other.m_upperProfileSize, other.m_lowerProfileSize, other.upperSize(), other.lowerSize()); - memcpy(m_diag, other.m_diag, m_diagSize * sizeof (Scalar)); - memcpy(m_upper, other.m_upper, other.upperSize() * sizeof (Scalar)); - memcpy(m_lower, other.m_lower, other.lowerSize() * sizeof (Scalar)); - memcpy(m_upperProfile, other.m_upperProfile, m_upperProfileSize * sizeof (Index)); - memcpy(m_lowerProfile, other.m_lowerProfile, m_lowerProfileSize * sizeof (Index)); - return *this; - } - - void swap(SkylineStorage& other) { - std::swap(m_diag, other.m_diag); - std::swap(m_upper, other.m_upper); - std::swap(m_lower, other.m_lower); - std::swap(m_upperProfile, other.m_upperProfile); - std::swap(m_lowerProfile, other.m_lowerProfile); - std::swap(m_diagSize, other.m_diagSize); - std::swap(m_upperSize, other.m_upperSize); - std::swap(m_lowerSize, other.m_lowerSize); - std::swap(m_allocatedSize, other.m_allocatedSize); - } - - ~SkylineStorage() { - delete[] m_diag; - delete[] m_upper; - if (m_upper != m_lower) - delete[] m_lower; - delete[] m_upperProfile; - delete[] m_lowerProfile; - } - - void reserve(Index size, Index upperProfileSize, Index lowerProfileSize, Index upperSize, Index lowerSize) { - Index newAllocatedSize = size + upperSize + lowerSize; - if (newAllocatedSize > m_allocatedSize) - reallocate(size, upperProfileSize, lowerProfileSize, upperSize, lowerSize); - } - - void squeeze() { - if (m_allocatedSize > m_diagSize + m_upperSize + m_lowerSize) - reallocate(m_diagSize, m_upperProfileSize, m_lowerProfileSize, m_upperSize, m_lowerSize); - } - - void resize(Index diagSize, Index upperProfileSize, Index lowerProfileSize, Index upperSize, Index lowerSize, float reserveSizeFactor = 0) { - if (m_allocatedSize < diagSize + upperSize + lowerSize) - reallocate(diagSize, upperProfileSize, lowerProfileSize, upperSize + Index(reserveSizeFactor * upperSize), lowerSize + Index(reserveSizeFactor * lowerSize)); - m_diagSize = diagSize; - m_upperSize = upperSize; - m_lowerSize = lowerSize; - m_upperProfileSize = upperProfileSize; - m_lowerProfileSize = lowerProfileSize; - } - - inline Index diagSize() const { - return m_diagSize; - } - - inline Index upperSize() const { - return m_upperSize; - } - - inline Index lowerSize() const { - return m_lowerSize; - } - - inline Index upperProfileSize() const { - return m_upperProfileSize; - } - - inline Index lowerProfileSize() const { - return m_lowerProfileSize; - } - - inline Index allocatedSize() const { - return m_allocatedSize; - } - - inline void clear() { - m_diagSize = 0; - } - - inline Scalar& diag(Index i) { - return m_diag[i]; - } - - inline const Scalar& diag(Index i) const { - return m_diag[i]; - } - - inline Scalar& upper(Index i) { - return m_upper[i]; - } - - inline const Scalar& upper(Index i) const { - return m_upper[i]; - } - - inline Scalar& lower(Index i) { - return m_lower[i]; - } - - inline const Scalar& lower(Index i) const { - return m_lower[i]; - } - - inline Index& upperProfile(Index i) { - return m_upperProfile[i]; - } - - inline const Index& upperProfile(Index i) const { - return m_upperProfile[i]; - } - - inline Index& lowerProfile(Index i) { - return m_lowerProfile[i]; - } - - inline const Index& lowerProfile(Index i) const { - return m_lowerProfile[i]; - } - - static SkylineStorage Map(Index* upperProfile, Index* lowerProfile, Scalar* diag, Scalar* upper, Scalar* lower, Index size, Index upperSize, Index lowerSize) { - SkylineStorage res; - res.m_upperProfile = upperProfile; - res.m_lowerProfile = lowerProfile; - res.m_diag = diag; - res.m_upper = upper; - res.m_lower = lower; - res.m_allocatedSize = res.m_diagSize = size; - res.m_upperSize = upperSize; - res.m_lowerSize = lowerSize; - return res; - } - - inline void reset() { - memset(m_diag, 0, m_diagSize * sizeof (Scalar)); - memset(m_upper, 0, m_upperSize * sizeof (Scalar)); - memset(m_lower, 0, m_lowerSize * sizeof (Scalar)); - memset(m_upperProfile, 0, m_diagSize * sizeof (Index)); - memset(m_lowerProfile, 0, m_diagSize * sizeof (Index)); - } - - void prune(Scalar reference, RealScalar epsilon = dummy_precision<RealScalar>()) { - //TODO - } - -protected: - - inline void reallocate(Index diagSize, Index upperProfileSize, Index lowerProfileSize, Index upperSize, Index lowerSize) { - - Scalar* diag = new Scalar[diagSize]; - Scalar* upper = new Scalar[upperSize]; - Scalar* lower = new Scalar[lowerSize]; - Index* upperProfile = new Index[upperProfileSize]; - Index* lowerProfile = new Index[lowerProfileSize]; - - Index copyDiagSize = (std::min)(diagSize, m_diagSize); - Index copyUpperSize = (std::min)(upperSize, m_upperSize); - Index copyLowerSize = (std::min)(lowerSize, m_lowerSize); - Index copyUpperProfileSize = (std::min)(upperProfileSize, m_upperProfileSize); - Index copyLowerProfileSize = (std::min)(lowerProfileSize, m_lowerProfileSize); - - // copy - memcpy(diag, m_diag, copyDiagSize * sizeof (Scalar)); - memcpy(upper, m_upper, copyUpperSize * sizeof (Scalar)); - memcpy(lower, m_lower, copyLowerSize * sizeof (Scalar)); - memcpy(upperProfile, m_upperProfile, copyUpperProfileSize * sizeof (Index)); - memcpy(lowerProfile, m_lowerProfile, copyLowerProfileSize * sizeof (Index)); - - - - // delete old stuff - delete[] m_diag; - delete[] m_upper; - delete[] m_lower; - delete[] m_upperProfile; - delete[] m_lowerProfile; - m_diag = diag; - m_upper = upper; - m_lower = lower; - m_upperProfile = upperProfile; - m_lowerProfile = lowerProfile; - m_allocatedSize = diagSize + upperSize + lowerSize; - m_upperSize = upperSize; - m_lowerSize = lowerSize; - } - -public: - Scalar* m_diag; - Scalar* m_upper; - Scalar* m_lower; - Index* m_upperProfile; - Index* m_lowerProfile; - Index m_diagSize; - Index m_upperSize; - Index m_lowerSize; - Index m_upperProfileSize; - Index m_lowerProfileSize; - Index m_allocatedSize; - -}; - -} // end namespace Eigen - -#endif // EIGEN_COMPRESSED_STORAGE_H diff --git a/eigen/unsupported/Eigen/src/Skyline/SkylineUtil.h b/eigen/unsupported/Eigen/src/Skyline/SkylineUtil.h deleted file mode 100644 index 75eb612..0000000 --- a/eigen/unsupported/Eigen/src/Skyline/SkylineUtil.h +++ /dev/null @@ -1,89 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Guillaume Saupin <guillaume.saupin@cea.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SKYLINEUTIL_H -#define EIGEN_SKYLINEUTIL_H - -namespace Eigen { - -#ifdef NDEBUG -#define EIGEN_DBG_SKYLINE(X) -#else -#define EIGEN_DBG_SKYLINE(X) X -#endif - -const unsigned int SkylineBit = 0x1200; -template<typename Lhs, typename Rhs, int ProductMode> class SkylineProduct; -enum AdditionalProductEvaluationMode {SkylineTimeDenseProduct, SkylineTimeSkylineProduct, DenseTimeSkylineProduct}; -enum {IsSkyline = SkylineBit}; - - -#define EIGEN_SKYLINE_INHERIT_ASSIGNMENT_OPERATOR(Derived, Op) \ -template<typename OtherDerived> \ -EIGEN_STRONG_INLINE Derived& operator Op(const Eigen::SkylineMatrixBase<OtherDerived>& other) \ -{ \ - return Base::operator Op(other.derived()); \ -} \ -EIGEN_STRONG_INLINE Derived& operator Op(const Derived& other) \ -{ \ - return Base::operator Op(other); \ -} - -#define EIGEN_SKYLINE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, Op) \ -template<typename Other> \ -EIGEN_STRONG_INLINE Derived& operator Op(const Other& scalar) \ -{ \ - return Base::operator Op(scalar); \ -} - -#define EIGEN_SKYLINE_INHERIT_ASSIGNMENT_OPERATORS(Derived) \ - EIGEN_SKYLINE_INHERIT_ASSIGNMENT_OPERATOR(Derived, =) \ - EIGEN_SKYLINE_INHERIT_ASSIGNMENT_OPERATOR(Derived, +=) \ - EIGEN_SKYLINE_INHERIT_ASSIGNMENT_OPERATOR(Derived, -=) \ - EIGEN_SKYLINE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, *=) \ - EIGEN_SKYLINE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, /=) - -#define _EIGEN_SKYLINE_GENERIC_PUBLIC_INTERFACE(Derived, BaseClass) \ - typedef BaseClass Base; \ - typedef typename Eigen::internal::traits<Derived>::Scalar Scalar; \ - typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; \ - typedef typename Eigen::internal::traits<Derived>::StorageKind StorageKind; \ - typedef typename Eigen::internal::index<StorageKind>::type Index; \ - enum { Flags = Eigen::internal::traits<Derived>::Flags, }; - -#define EIGEN_SKYLINE_GENERIC_PUBLIC_INTERFACE(Derived) \ - _EIGEN_SKYLINE_GENERIC_PUBLIC_INTERFACE(Derived, Eigen::SkylineMatrixBase<Derived>) - -template<typename Derived> class SkylineMatrixBase; -template<typename _Scalar, int _Flags = 0> class SkylineMatrix; -template<typename _Scalar, int _Flags = 0> class DynamicSkylineMatrix; -template<typename _Scalar, int _Flags = 0> class SkylineVector; -template<typename _Scalar, int _Flags = 0> class MappedSkylineMatrix; - -namespace internal { - -template<typename Lhs, typename Rhs> struct skyline_product_mode; -template<typename Lhs, typename Rhs, int ProductMode = skyline_product_mode<Lhs,Rhs>::value> struct SkylineProductReturnType; - -template<typename T> class eval<T,IsSkyline> -{ - typedef typename traits<T>::Scalar _Scalar; - enum { - _Flags = traits<T>::Flags - }; - - public: - typedef SkylineMatrix<_Scalar, _Flags> type; -}; - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_SKYLINEUTIL_H diff --git a/eigen/unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h b/eigen/unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h deleted file mode 100644 index e9ec746..0000000 --- a/eigen/unsupported/Eigen/src/SparseExtra/BlockOfDynamicSparseMatrix.h +++ /dev/null @@ -1,122 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPARSE_BLOCKFORDYNAMICMATRIX_H -#define EIGEN_SPARSE_BLOCKFORDYNAMICMATRIX_H - -namespace Eigen { - -#if 0 - -// NOTE Have to be reimplemented as a specialization of BlockImpl< DynamicSparseMatrix<_Scalar, _Options, _Index>, ... > -// See SparseBlock.h for an example - - -/*************************************************************************** -* specialisation for DynamicSparseMatrix -***************************************************************************/ - -template<typename _Scalar, int _Options, typename _Index, int Size> -class SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options, _Index>, Size> - : public SparseMatrixBase<SparseInnerVectorSet<DynamicSparseMatrix<_Scalar, _Options, _Index>, Size> > -{ - typedef DynamicSparseMatrix<_Scalar, _Options, _Index> MatrixType; - public: - - enum { IsRowMajor = internal::traits<SparseInnerVectorSet>::IsRowMajor }; - - EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet) - class InnerIterator: public MatrixType::InnerIterator - { - public: - inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer) - : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) - {} - inline Index row() const { return IsRowMajor ? m_outer : this->index(); } - inline Index col() const { return IsRowMajor ? this->index() : m_outer; } - protected: - Index m_outer; - }; - - inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize) - : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize) - { - eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) ); - } - - inline SparseInnerVectorSet(const MatrixType& matrix, Index outer) - : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size) - { - eigen_assert(Size!=Dynamic); - eigen_assert( (outer>=0) && (outer<matrix.outerSize()) ); - } - - template<typename OtherDerived> - inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other) - { - if (IsRowMajor != ((OtherDerived::Flags&RowMajorBit)==RowMajorBit)) - { - // need to transpose => perform a block evaluation followed by a big swap - DynamicSparseMatrix<Scalar,IsRowMajor?RowMajorBit:0> aux(other); - *this = aux.markAsRValue(); - } - else - { - // evaluate/copy vector per vector - for (Index j=0; j<m_outerSize.value(); ++j) - { - SparseVector<Scalar,IsRowMajor ? RowMajorBit : 0> aux(other.innerVector(j)); - m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data()); - } - } - return *this; - } - - inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other) - { - return operator=<SparseInnerVectorSet>(other); - } - - Index nonZeros() const - { - Index count = 0; - for (Index j=0; j<m_outerSize.value(); ++j) - count += m_matrix._data()[m_outerStart+j].size(); - return count; - } - - const Scalar& lastCoeff() const - { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(SparseInnerVectorSet); - eigen_assert(m_matrix.data()[m_outerStart].size()>0); - return m_matrix.data()[m_outerStart].vale(m_matrix.data()[m_outerStart].size()-1); - } - -// template<typename Sparse> -// inline SparseInnerVectorSet& operator=(const SparseMatrixBase<OtherDerived>& other) -// { -// return *this; -// } - - EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } - EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } - - protected: - - const typename MatrixType::Nested m_matrix; - Index m_outerStart; - const internal::variable_if_dynamic<Index, Size> m_outerSize; - -}; - -#endif - -} // end namespace Eigen - -#endif // EIGEN_SPARSE_BLOCKFORDYNAMICMATRIX_H diff --git a/eigen/unsupported/Eigen/src/SparseExtra/BlockSparseMatrix.h b/eigen/unsupported/Eigen/src/SparseExtra/BlockSparseMatrix.h deleted file mode 100644 index 536a0c3..0000000 --- a/eigen/unsupported/Eigen/src/SparseExtra/BlockSparseMatrix.h +++ /dev/null @@ -1,1079 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2013 Desire Nuentsa <desire.nuentsa_wakam@inria.fr> -// Copyright (C) 2013 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPARSEBLOCKMATRIX_H -#define EIGEN_SPARSEBLOCKMATRIX_H - -namespace Eigen { -/** \ingroup SparseCore_Module - * - * \class BlockSparseMatrix - * - * \brief A versatile sparse matrix representation where each element is a block - * - * This class provides routines to manipulate block sparse matrices stored in a - * BSR-like representation. There are two main types : - * - * 1. All blocks have the same number of rows and columns, called block size - * in the following. In this case, if this block size is known at compile time, - * it can be given as a template parameter like - * \code - * BlockSparseMatrix<Scalar, 3, ColMajor> bmat(b_rows, b_cols); - * \endcode - * Here, bmat is a b_rows x b_cols block sparse matrix - * where each coefficient is a 3x3 dense matrix. - * If the block size is fixed but will be given at runtime, - * \code - * BlockSparseMatrix<Scalar, Dynamic, ColMajor> bmat(b_rows, b_cols); - * bmat.setBlockSize(block_size); - * \endcode - * - * 2. The second case is for variable-block sparse matrices. - * Here each block has its own dimensions. The only restriction is that all the blocks - * in a row (resp. a column) should have the same number of rows (resp. of columns). - * It is thus required in this case to describe the layout of the matrix by calling - * setBlockLayout(rowBlocks, colBlocks). - * - * In any of the previous case, the matrix can be filled by calling setFromTriplets(). - * A regular sparse matrix can be converted to a block sparse matrix and vice versa. - * It is obviously required to describe the block layout beforehand by calling either - * setBlockSize() for fixed-size blocks or setBlockLayout for variable-size blocks. - * - * \tparam _Scalar The Scalar type - * \tparam _BlockAtCompileTime The block layout option. It takes the following values - * Dynamic : block size known at runtime - * a numeric number : fixed-size block known at compile time - */ -template<typename _Scalar, int _BlockAtCompileTime=Dynamic, int _Options=ColMajor, typename _StorageIndex=int> class BlockSparseMatrix; - -template<typename BlockSparseMatrixT> class BlockSparseMatrixView; - -namespace internal { -template<typename _Scalar, int _BlockAtCompileTime, int _Options, typename _Index> -struct traits<BlockSparseMatrix<_Scalar,_BlockAtCompileTime,_Options, _Index> > -{ - typedef _Scalar Scalar; - typedef _Index Index; - typedef Sparse StorageKind; // FIXME Where is it used ?? - typedef MatrixXpr XprKind; - enum { - RowsAtCompileTime = Dynamic, - ColsAtCompileTime = Dynamic, - MaxRowsAtCompileTime = Dynamic, - MaxColsAtCompileTime = Dynamic, - BlockSize = _BlockAtCompileTime, - Flags = _Options | NestByRefBit | LvalueBit, - CoeffReadCost = NumTraits<Scalar>::ReadCost, - SupportedAccessPatterns = InnerRandomAccessPattern - }; -}; -template<typename BlockSparseMatrixT> -struct traits<BlockSparseMatrixView<BlockSparseMatrixT> > -{ - typedef Ref<Matrix<typename BlockSparseMatrixT::Scalar, BlockSparseMatrixT::BlockSize, BlockSparseMatrixT::BlockSize> > Scalar; - typedef Ref<Matrix<typename BlockSparseMatrixT::RealScalar, BlockSparseMatrixT::BlockSize, BlockSparseMatrixT::BlockSize> > RealScalar; - -}; - -// Function object to sort a triplet list -template<typename Iterator, bool IsColMajor> -struct TripletComp -{ - typedef typename Iterator::value_type Triplet; - bool operator()(const Triplet& a, const Triplet& b) - { if(IsColMajor) - return ((a.col() == b.col() && a.row() < b.row()) || (a.col() < b.col())); - else - return ((a.row() == b.row() && a.col() < b.col()) || (a.row() < b.row())); - } -}; -} // end namespace internal - - -/* Proxy to view the block sparse matrix as a regular sparse matrix */ -template<typename BlockSparseMatrixT> -class BlockSparseMatrixView : public SparseMatrixBase<BlockSparseMatrixT> -{ - public: - typedef Ref<typename BlockSparseMatrixT::BlockScalar> Scalar; - typedef Ref<typename BlockSparseMatrixT::BlockRealScalar> RealScalar; - typedef typename BlockSparseMatrixT::Index Index; - typedef BlockSparseMatrixT Nested; - enum { - Flags = BlockSparseMatrixT::Options, - Options = BlockSparseMatrixT::Options, - RowsAtCompileTime = BlockSparseMatrixT::RowsAtCompileTime, - ColsAtCompileTime = BlockSparseMatrixT::ColsAtCompileTime, - MaxColsAtCompileTime = BlockSparseMatrixT::MaxColsAtCompileTime, - MaxRowsAtCompileTime = BlockSparseMatrixT::MaxRowsAtCompileTime - }; - public: - BlockSparseMatrixView(const BlockSparseMatrixT& spblockmat) - : m_spblockmat(spblockmat) - {} - - Index outerSize() const - { - return (Flags&RowMajorBit) == 1 ? this->rows() : this->cols(); - } - Index cols() const - { - return m_spblockmat.blockCols(); - } - Index rows() const - { - return m_spblockmat.blockRows(); - } - Scalar coeff(Index row, Index col) - { - return m_spblockmat.coeff(row, col); - } - Scalar coeffRef(Index row, Index col) - { - return m_spblockmat.coeffRef(row, col); - } - // Wrapper to iterate over all blocks - class InnerIterator : public BlockSparseMatrixT::BlockInnerIterator - { - public: - InnerIterator(const BlockSparseMatrixView& mat, Index outer) - : BlockSparseMatrixT::BlockInnerIterator(mat.m_spblockmat, outer) - {} - - }; - - protected: - const BlockSparseMatrixT& m_spblockmat; -}; - -// Proxy to view a regular vector as a block vector -template<typename BlockSparseMatrixT, typename VectorType> -class BlockVectorView -{ - public: - enum { - BlockSize = BlockSparseMatrixT::BlockSize, - ColsAtCompileTime = VectorType::ColsAtCompileTime, - RowsAtCompileTime = VectorType::RowsAtCompileTime, - Flags = VectorType::Flags - }; - typedef Ref<const Matrix<typename BlockSparseMatrixT::Scalar, (RowsAtCompileTime==1)? 1 : BlockSize, (ColsAtCompileTime==1)? 1 : BlockSize> >Scalar; - typedef typename BlockSparseMatrixT::Index Index; - public: - BlockVectorView(const BlockSparseMatrixT& spblockmat, const VectorType& vec) - : m_spblockmat(spblockmat),m_vec(vec) - { } - inline Index cols() const - { - return m_vec.cols(); - } - inline Index size() const - { - return m_spblockmat.blockRows(); - } - inline Scalar coeff(Index bi) const - { - Index startRow = m_spblockmat.blockRowsIndex(bi); - Index rowSize = m_spblockmat.blockRowsIndex(bi+1) - startRow; - return m_vec.middleRows(startRow, rowSize); - } - inline Scalar coeff(Index bi, Index j) const - { - Index startRow = m_spblockmat.blockRowsIndex(bi); - Index rowSize = m_spblockmat.blockRowsIndex(bi+1) - startRow; - return m_vec.block(startRow, j, rowSize, 1); - } - protected: - const BlockSparseMatrixT& m_spblockmat; - const VectorType& m_vec; -}; - -template<typename VectorType, typename Index> class BlockVectorReturn; - - -// Proxy to view a regular vector as a block vector -template<typename BlockSparseMatrixT, typename VectorType> -class BlockVectorReturn -{ - public: - enum { - ColsAtCompileTime = VectorType::ColsAtCompileTime, - RowsAtCompileTime = VectorType::RowsAtCompileTime, - Flags = VectorType::Flags - }; - typedef Ref<Matrix<typename VectorType::Scalar, RowsAtCompileTime, ColsAtCompileTime> > Scalar; - typedef typename BlockSparseMatrixT::Index Index; - public: - BlockVectorReturn(const BlockSparseMatrixT& spblockmat, VectorType& vec) - : m_spblockmat(spblockmat),m_vec(vec) - { } - inline Index size() const - { - return m_spblockmat.blockRows(); - } - inline Scalar coeffRef(Index bi) - { - Index startRow = m_spblockmat.blockRowsIndex(bi); - Index rowSize = m_spblockmat.blockRowsIndex(bi+1) - startRow; - return m_vec.middleRows(startRow, rowSize); - } - inline Scalar coeffRef(Index bi, Index j) - { - Index startRow = m_spblockmat.blockRowsIndex(bi); - Index rowSize = m_spblockmat.blockRowsIndex(bi+1) - startRow; - return m_vec.block(startRow, j, rowSize, 1); - } - - protected: - const BlockSparseMatrixT& m_spblockmat; - VectorType& m_vec; -}; - -// Block version of the sparse dense product -template<typename Lhs, typename Rhs> -class BlockSparseTimeDenseProduct; - -namespace internal { - -template<typename BlockSparseMatrixT, typename VecType> -struct traits<BlockSparseTimeDenseProduct<BlockSparseMatrixT, VecType> > -{ - typedef Dense StorageKind; - typedef MatrixXpr XprKind; - typedef typename BlockSparseMatrixT::Scalar Scalar; - typedef typename BlockSparseMatrixT::Index Index; - enum { - RowsAtCompileTime = Dynamic, - ColsAtCompileTime = Dynamic, - MaxRowsAtCompileTime = Dynamic, - MaxColsAtCompileTime = Dynamic, - Flags = 0, - CoeffReadCost = internal::traits<BlockSparseMatrixT>::CoeffReadCost - }; -}; -} // end namespace internal - -template<typename Lhs, typename Rhs> -class BlockSparseTimeDenseProduct - : public ProductBase<BlockSparseTimeDenseProduct<Lhs,Rhs>, Lhs, Rhs> -{ - public: - EIGEN_PRODUCT_PUBLIC_INTERFACE(BlockSparseTimeDenseProduct) - - BlockSparseTimeDenseProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) - {} - - template<typename Dest> void scaleAndAddTo(Dest& dest, const typename Rhs::Scalar& alpha) const - { - BlockVectorReturn<Lhs,Dest> tmpDest(m_lhs, dest); - internal::sparse_time_dense_product( BlockSparseMatrixView<Lhs>(m_lhs), BlockVectorView<Lhs, Rhs>(m_lhs, m_rhs), tmpDest, alpha); - } - - private: - BlockSparseTimeDenseProduct& operator=(const BlockSparseTimeDenseProduct&); -}; - -template<typename _Scalar, int _BlockAtCompileTime, int _Options, typename _StorageIndex> -class BlockSparseMatrix : public SparseMatrixBase<BlockSparseMatrix<_Scalar,_BlockAtCompileTime, _Options,_StorageIndex> > -{ - public: - typedef _Scalar Scalar; - typedef typename NumTraits<Scalar>::Real RealScalar; - typedef _StorageIndex StorageIndex; - typedef typename internal::ref_selector<BlockSparseMatrix<_Scalar, _BlockAtCompileTime, _Options, _StorageIndex> >::type Nested; - - enum { - Options = _Options, - Flags = Options, - BlockSize=_BlockAtCompileTime, - RowsAtCompileTime = Dynamic, - ColsAtCompileTime = Dynamic, - MaxRowsAtCompileTime = Dynamic, - MaxColsAtCompileTime = Dynamic, - IsVectorAtCompileTime = 0, - IsColMajor = Flags&RowMajorBit ? 0 : 1 - }; - typedef Matrix<Scalar, _BlockAtCompileTime, _BlockAtCompileTime,IsColMajor ? ColMajor : RowMajor> BlockScalar; - typedef Matrix<RealScalar, _BlockAtCompileTime, _BlockAtCompileTime,IsColMajor ? ColMajor : RowMajor> BlockRealScalar; - typedef typename internal::conditional<_BlockAtCompileTime==Dynamic, Scalar, BlockScalar>::type BlockScalarReturnType; - typedef BlockSparseMatrix<Scalar, BlockSize, IsColMajor ? ColMajor : RowMajor, StorageIndex> PlainObject; - public: - // Default constructor - BlockSparseMatrix() - : m_innerBSize(0),m_outerBSize(0),m_innerOffset(0),m_outerOffset(0), - m_nonzerosblocks(0),m_values(0),m_blockPtr(0),m_indices(0), - m_outerIndex(0),m_blockSize(BlockSize) - { } - - - /** - * \brief Construct and resize - * - */ - BlockSparseMatrix(Index brow, Index bcol) - : m_innerBSize(IsColMajor ? brow : bcol), - m_outerBSize(IsColMajor ? bcol : brow), - m_innerOffset(0),m_outerOffset(0),m_nonzerosblocks(0), - m_values(0),m_blockPtr(0),m_indices(0), - m_outerIndex(0),m_blockSize(BlockSize) - { } - - /** - * \brief Copy-constructor - */ - BlockSparseMatrix(const BlockSparseMatrix& other) - : m_innerBSize(other.m_innerBSize),m_outerBSize(other.m_outerBSize), - m_nonzerosblocks(other.m_nonzerosblocks),m_nonzeros(other.m_nonzeros), - m_blockPtr(0),m_blockSize(other.m_blockSize) - { - // should we allow copying between variable-size blocks and fixed-size blocks ?? - eigen_assert(m_blockSize == BlockSize && " CAN NOT COPY BETWEEN FIXED-SIZE AND VARIABLE-SIZE BLOCKS"); - - std::copy(other.m_innerOffset, other.m_innerOffset+m_innerBSize+1, m_innerOffset); - std::copy(other.m_outerOffset, other.m_outerOffset+m_outerBSize+1, m_outerOffset); - std::copy(other.m_values, other.m_values+m_nonzeros, m_values); - - if(m_blockSize != Dynamic) - std::copy(other.m_blockPtr, other.m_blockPtr+m_nonzerosblocks, m_blockPtr); - - std::copy(other.m_indices, other.m_indices+m_nonzerosblocks, m_indices); - std::copy(other.m_outerIndex, other.m_outerIndex+m_outerBSize, m_outerIndex); - } - - friend void swap(BlockSparseMatrix& first, BlockSparseMatrix& second) - { - std::swap(first.m_innerBSize, second.m_innerBSize); - std::swap(first.m_outerBSize, second.m_outerBSize); - std::swap(first.m_innerOffset, second.m_innerOffset); - std::swap(first.m_outerOffset, second.m_outerOffset); - std::swap(first.m_nonzerosblocks, second.m_nonzerosblocks); - std::swap(first.m_nonzeros, second.m_nonzeros); - std::swap(first.m_values, second.m_values); - std::swap(first.m_blockPtr, second.m_blockPtr); - std::swap(first.m_indices, second.m_indices); - std::swap(first.m_outerIndex, second.m_outerIndex); - std::swap(first.m_BlockSize, second.m_blockSize); - } - - BlockSparseMatrix& operator=(BlockSparseMatrix other) - { - //Copy-and-swap paradigm ... avoid leaked data if thrown - swap(*this, other); - return *this; - } - - // Destructor - ~BlockSparseMatrix() - { - delete[] m_outerIndex; - delete[] m_innerOffset; - delete[] m_outerOffset; - delete[] m_indices; - delete[] m_blockPtr; - delete[] m_values; - } - - - /** - * \brief Constructor from a sparse matrix - * - */ - template<typename MatrixType> - inline BlockSparseMatrix(const MatrixType& spmat) : m_blockSize(BlockSize) - { - EIGEN_STATIC_ASSERT((m_blockSize != Dynamic), THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE); - - *this = spmat; - } - - /** - * \brief Assignment from a sparse matrix with the same storage order - * - * Convert from a sparse matrix to block sparse matrix. - * \warning Before calling this function, tt is necessary to call - * either setBlockLayout() (matrices with variable-size blocks) - * or setBlockSize() (for fixed-size blocks). - */ - template<typename MatrixType> - inline BlockSparseMatrix& operator=(const MatrixType& spmat) - { - eigen_assert((m_innerBSize != 0 && m_outerBSize != 0) - && "Trying to assign to a zero-size matrix, call resize() first"); - eigen_assert(((MatrixType::Options&RowMajorBit) != IsColMajor) && "Wrong storage order"); - typedef SparseMatrix<bool,MatrixType::Options,typename MatrixType::Index> MatrixPatternType; - MatrixPatternType blockPattern(blockRows(), blockCols()); - m_nonzeros = 0; - - // First, compute the number of nonzero blocks and their locations - for(StorageIndex bj = 0; bj < m_outerBSize; ++bj) - { - // Browse each outer block and compute the structure - std::vector<bool> nzblocksFlag(m_innerBSize,false); // Record the existing blocks - blockPattern.startVec(bj); - for(StorageIndex j = blockOuterIndex(bj); j < blockOuterIndex(bj+1); ++j) - { - typename MatrixType::InnerIterator it_spmat(spmat, j); - for(; it_spmat; ++it_spmat) - { - StorageIndex bi = innerToBlock(it_spmat.index()); // Index of the current nonzero block - if(!nzblocksFlag[bi]) - { - // Save the index of this nonzero block - nzblocksFlag[bi] = true; - blockPattern.insertBackByOuterInnerUnordered(bj, bi) = true; - // Compute the total number of nonzeros (including explicit zeros in blocks) - m_nonzeros += blockOuterSize(bj) * blockInnerSize(bi); - } - } - } // end current outer block - } - blockPattern.finalize(); - - // Allocate the internal arrays - setBlockStructure(blockPattern); - - for(StorageIndex nz = 0; nz < m_nonzeros; ++nz) m_values[nz] = Scalar(0); - for(StorageIndex bj = 0; bj < m_outerBSize; ++bj) - { - // Now copy the values - for(StorageIndex j = blockOuterIndex(bj); j < blockOuterIndex(bj+1); ++j) - { - // Browse the outer block column by column (for column-major matrices) - typename MatrixType::InnerIterator it_spmat(spmat, j); - for(; it_spmat; ++it_spmat) - { - StorageIndex idx = 0; // Position of this block in the column block - StorageIndex bi = innerToBlock(it_spmat.index()); // Index of the current nonzero block - // Go to the inner block where this element belongs to - while(bi > m_indices[m_outerIndex[bj]+idx]) ++idx; // Not expensive for ordered blocks - StorageIndex idxVal;// Get the right position in the array of values for this element - if(m_blockSize == Dynamic) - { - // Offset from all blocks before ... - idxVal = m_blockPtr[m_outerIndex[bj]+idx]; - // ... and offset inside the block - idxVal += (j - blockOuterIndex(bj)) * blockOuterSize(bj) + it_spmat.index() - m_innerOffset[bi]; - } - else - { - // All blocks before - idxVal = (m_outerIndex[bj] + idx) * m_blockSize * m_blockSize; - // inside the block - idxVal += (j - blockOuterIndex(bj)) * m_blockSize + (it_spmat.index()%m_blockSize); - } - // Insert the value - m_values[idxVal] = it_spmat.value(); - } // end of this column - } // end of this block - } // end of this outer block - - return *this; - } - - /** - * \brief Set the nonzero block pattern of the matrix - * - * Given a sparse matrix describing the nonzero block pattern, - * this function prepares the internal pointers for values. - * After calling this function, any *nonzero* block (bi, bj) can be set - * with a simple call to coeffRef(bi,bj). - * - * - * \warning Before calling this function, tt is necessary to call - * either setBlockLayout() (matrices with variable-size blocks) - * or setBlockSize() (for fixed-size blocks). - * - * \param blockPattern Sparse matrix of boolean elements describing the block structure - * - * \sa setBlockLayout() \sa setBlockSize() - */ - template<typename MatrixType> - void setBlockStructure(const MatrixType& blockPattern) - { - resize(blockPattern.rows(), blockPattern.cols()); - reserve(blockPattern.nonZeros()); - - // Browse the block pattern and set up the various pointers - m_outerIndex[0] = 0; - if(m_blockSize == Dynamic) m_blockPtr[0] = 0; - for(StorageIndex nz = 0; nz < m_nonzeros; ++nz) m_values[nz] = Scalar(0); - for(StorageIndex bj = 0; bj < m_outerBSize; ++bj) - { - //Browse each outer block - - //First, copy and save the indices of nonzero blocks - //FIXME : find a way to avoid this ... - std::vector<int> nzBlockIdx; - typename MatrixType::InnerIterator it(blockPattern, bj); - for(; it; ++it) - { - nzBlockIdx.push_back(it.index()); - } - std::sort(nzBlockIdx.begin(), nzBlockIdx.end()); - - // Now, fill block indices and (eventually) pointers to blocks - for(StorageIndex idx = 0; idx < nzBlockIdx.size(); ++idx) - { - StorageIndex offset = m_outerIndex[bj]+idx; // offset in m_indices - m_indices[offset] = nzBlockIdx[idx]; - if(m_blockSize == Dynamic) - m_blockPtr[offset] = m_blockPtr[offset-1] + blockInnerSize(nzBlockIdx[idx]) * blockOuterSize(bj); - // There is no blockPtr for fixed-size blocks... not needed !??? - } - // Save the pointer to the next outer block - m_outerIndex[bj+1] = m_outerIndex[bj] + nzBlockIdx.size(); - } - } - - /** - * \brief Set the number of rows and columns blocks - */ - inline void resize(Index brow, Index bcol) - { - m_innerBSize = IsColMajor ? brow : bcol; - m_outerBSize = IsColMajor ? bcol : brow; - } - - /** - * \brief set the block size at runtime for fixed-size block layout - * - * Call this only for fixed-size blocks - */ - inline void setBlockSize(Index blockSize) - { - m_blockSize = blockSize; - } - - /** - * \brief Set the row and column block layouts, - * - * This function set the size of each row and column block. - * So this function should be used only for blocks with variable size. - * \param rowBlocks : Number of rows per row block - * \param colBlocks : Number of columns per column block - * \sa resize(), setBlockSize() - */ - inline void setBlockLayout(const VectorXi& rowBlocks, const VectorXi& colBlocks) - { - const VectorXi& innerBlocks = IsColMajor ? rowBlocks : colBlocks; - const VectorXi& outerBlocks = IsColMajor ? colBlocks : rowBlocks; - eigen_assert(m_innerBSize == innerBlocks.size() && "CHECK THE NUMBER OF ROW OR COLUMN BLOCKS"); - eigen_assert(m_outerBSize == outerBlocks.size() && "CHECK THE NUMBER OF ROW OR COLUMN BLOCKS"); - m_outerBSize = outerBlocks.size(); - // starting index of blocks... cumulative sums - m_innerOffset = new StorageIndex[m_innerBSize+1]; - m_outerOffset = new StorageIndex[m_outerBSize+1]; - m_innerOffset[0] = 0; - m_outerOffset[0] = 0; - std::partial_sum(&innerBlocks[0], &innerBlocks[m_innerBSize-1]+1, &m_innerOffset[1]); - std::partial_sum(&outerBlocks[0], &outerBlocks[m_outerBSize-1]+1, &m_outerOffset[1]); - - // Compute the total number of nonzeros - m_nonzeros = 0; - for(StorageIndex bj = 0; bj < m_outerBSize; ++bj) - for(StorageIndex bi = 0; bi < m_innerBSize; ++bi) - m_nonzeros += outerBlocks[bj] * innerBlocks[bi]; - - } - - /** - * \brief Allocate the internal array of pointers to blocks and their inner indices - * - * \note For fixed-size blocks, call setBlockSize() to set the block. - * And For variable-size blocks, call setBlockLayout() before using this function - * - * \param nonzerosblocks Number of nonzero blocks. The total number of nonzeros is - * is computed in setBlockLayout() for variable-size blocks - * \sa setBlockSize() - */ - inline void reserve(const Index nonzerosblocks) - { - eigen_assert((m_innerBSize != 0 && m_outerBSize != 0) && - "TRYING TO RESERVE ZERO-SIZE MATRICES, CALL resize() first"); - - //FIXME Should free if already allocated - m_outerIndex = new StorageIndex[m_outerBSize+1]; - - m_nonzerosblocks = nonzerosblocks; - if(m_blockSize != Dynamic) - { - m_nonzeros = nonzerosblocks * (m_blockSize * m_blockSize); - m_blockPtr = 0; - } - else - { - // m_nonzeros is already computed in setBlockLayout() - m_blockPtr = new StorageIndex[m_nonzerosblocks+1]; - } - m_indices = new StorageIndex[m_nonzerosblocks+1]; - m_values = new Scalar[m_nonzeros]; - } - - - /** - * \brief Fill values in a matrix from a triplet list. - * - * Each triplet item has a block stored in an Eigen dense matrix. - * The InputIterator class should provide the functions row(), col() and value() - * - * \note For fixed-size blocks, call setBlockSize() before this function. - * - * FIXME Do not accept duplicates - */ - template<typename InputIterator> - void setFromTriplets(const InputIterator& begin, const InputIterator& end) - { - eigen_assert((m_innerBSize!=0 && m_outerBSize !=0) && "ZERO BLOCKS, PLEASE CALL resize() before"); - - /* First, sort the triplet list - * FIXME This can be unnecessarily expensive since only the inner indices have to be sorted - * The best approach is like in SparseMatrix::setFromTriplets() - */ - internal::TripletComp<InputIterator, IsColMajor> tripletcomp; - std::sort(begin, end, tripletcomp); - - /* Count the number of rows and column blocks, - * and the number of nonzero blocks per outer dimension - */ - VectorXi rowBlocks(m_innerBSize); // Size of each block row - VectorXi colBlocks(m_outerBSize); // Size of each block column - rowBlocks.setZero(); colBlocks.setZero(); - VectorXi nzblock_outer(m_outerBSize); // Number of nz blocks per outer vector - VectorXi nz_outer(m_outerBSize); // Number of nz per outer vector...for variable-size blocks - nzblock_outer.setZero(); - nz_outer.setZero(); - for(InputIterator it(begin); it !=end; ++it) - { - eigen_assert(it->row() >= 0 && it->row() < this->blockRows() && it->col() >= 0 && it->col() < this->blockCols()); - eigen_assert((it->value().rows() == it->value().cols() && (it->value().rows() == m_blockSize)) - || (m_blockSize == Dynamic)); - - if(m_blockSize == Dynamic) - { - eigen_assert((rowBlocks[it->row()] == 0 || rowBlocks[it->row()] == it->value().rows()) && - "NON CORRESPONDING SIZES FOR ROW BLOCKS"); - eigen_assert((colBlocks[it->col()] == 0 || colBlocks[it->col()] == it->value().cols()) && - "NON CORRESPONDING SIZES FOR COLUMN BLOCKS"); - rowBlocks[it->row()] =it->value().rows(); - colBlocks[it->col()] = it->value().cols(); - } - nz_outer(IsColMajor ? it->col() : it->row()) += it->value().rows() * it->value().cols(); - nzblock_outer(IsColMajor ? it->col() : it->row())++; - } - // Allocate member arrays - if(m_blockSize == Dynamic) setBlockLayout(rowBlocks, colBlocks); - StorageIndex nzblocks = nzblock_outer.sum(); - reserve(nzblocks); - - // Temporary markers - VectorXi block_id(m_outerBSize); // To be used as a block marker during insertion - - // Setup outer index pointers and markers - m_outerIndex[0] = 0; - if (m_blockSize == Dynamic) m_blockPtr[0] = 0; - for(StorageIndex bj = 0; bj < m_outerBSize; ++bj) - { - m_outerIndex[bj+1] = m_outerIndex[bj] + nzblock_outer(bj); - block_id(bj) = m_outerIndex[bj]; - if(m_blockSize==Dynamic) - { - m_blockPtr[m_outerIndex[bj+1]] = m_blockPtr[m_outerIndex[bj]] + nz_outer(bj); - } - } - - // Fill the matrix - for(InputIterator it(begin); it!=end; ++it) - { - StorageIndex outer = IsColMajor ? it->col() : it->row(); - StorageIndex inner = IsColMajor ? it->row() : it->col(); - m_indices[block_id(outer)] = inner; - StorageIndex block_size = it->value().rows()*it->value().cols(); - StorageIndex nz_marker = blockPtr(block_id[outer]); - memcpy(&(m_values[nz_marker]), it->value().data(), block_size * sizeof(Scalar)); - if(m_blockSize == Dynamic) - { - m_blockPtr[block_id(outer)+1] = m_blockPtr[block_id(outer)] + block_size; - } - block_id(outer)++; - } - - // An alternative when the outer indices are sorted...no need to use an array of markers -// for(Index bcol = 0; bcol < m_outerBSize; ++bcol) -// { -// Index id = 0, id_nz = 0, id_nzblock = 0; -// for(InputIterator it(begin); it!=end; ++it) -// { -// while (id<bcol) // one pass should do the job unless there are empty columns -// { -// id++; -// m_outerIndex[id+1]=m_outerIndex[id]; -// } -// m_outerIndex[id+1] += 1; -// m_indices[id_nzblock]=brow; -// Index block_size = it->value().rows()*it->value().cols(); -// m_blockPtr[id_nzblock+1] = m_blockPtr[id_nzblock] + block_size; -// id_nzblock++; -// memcpy(&(m_values[id_nz]),it->value().data(), block_size*sizeof(Scalar)); -// id_nz += block_size; -// } -// while(id < m_outerBSize-1) // Empty columns at the end -// { -// id++; -// m_outerIndex[id+1]=m_outerIndex[id]; -// } -// } - } - - - /** - * \returns the number of rows - */ - inline Index rows() const - { -// return blockRows(); - return (IsColMajor ? innerSize() : outerSize()); - } - - /** - * \returns the number of cols - */ - inline Index cols() const - { -// return blockCols(); - return (IsColMajor ? outerSize() : innerSize()); - } - - inline Index innerSize() const - { - if(m_blockSize == Dynamic) return m_innerOffset[m_innerBSize]; - else return (m_innerBSize * m_blockSize) ; - } - - inline Index outerSize() const - { - if(m_blockSize == Dynamic) return m_outerOffset[m_outerBSize]; - else return (m_outerBSize * m_blockSize) ; - } - /** \returns the number of rows grouped by blocks */ - inline Index blockRows() const - { - return (IsColMajor ? m_innerBSize : m_outerBSize); - } - /** \returns the number of columns grouped by blocks */ - inline Index blockCols() const - { - return (IsColMajor ? m_outerBSize : m_innerBSize); - } - - inline Index outerBlocks() const { return m_outerBSize; } - inline Index innerBlocks() const { return m_innerBSize; } - - /** \returns the block index where outer belongs to */ - inline Index outerToBlock(Index outer) const - { - eigen_assert(outer < outerSize() && "OUTER INDEX OUT OF BOUNDS"); - - if(m_blockSize != Dynamic) - return (outer / m_blockSize); // Integer division - - StorageIndex b_outer = 0; - while(m_outerOffset[b_outer] <= outer) ++b_outer; - return b_outer - 1; - } - /** \returns the block index where inner belongs to */ - inline Index innerToBlock(Index inner) const - { - eigen_assert(inner < innerSize() && "OUTER INDEX OUT OF BOUNDS"); - - if(m_blockSize != Dynamic) - return (inner / m_blockSize); // Integer division - - StorageIndex b_inner = 0; - while(m_innerOffset[b_inner] <= inner) ++b_inner; - return b_inner - 1; - } - - /** - *\returns a reference to the (i,j) block as an Eigen Dense Matrix - */ - Ref<BlockScalar> coeffRef(Index brow, Index bcol) - { - eigen_assert(brow < blockRows() && "BLOCK ROW INDEX OUT OF BOUNDS"); - eigen_assert(bcol < blockCols() && "BLOCK nzblocksFlagCOLUMN OUT OF BOUNDS"); - - StorageIndex rsize = IsColMajor ? blockInnerSize(brow): blockOuterSize(bcol); - StorageIndex csize = IsColMajor ? blockOuterSize(bcol) : blockInnerSize(brow); - StorageIndex inner = IsColMajor ? brow : bcol; - StorageIndex outer = IsColMajor ? bcol : brow; - StorageIndex offset = m_outerIndex[outer]; - while(offset < m_outerIndex[outer+1] && m_indices[offset] != inner) - offset++; - if(m_indices[offset] == inner) - { - return Map<BlockScalar>(&(m_values[blockPtr(offset)]), rsize, csize); - } - else - { - //FIXME the block does not exist, Insert it !!!!!!!!! - eigen_assert("DYNAMIC INSERTION IS NOT YET SUPPORTED"); - } - } - - /** - * \returns the value of the (i,j) block as an Eigen Dense Matrix - */ - Map<const BlockScalar> coeff(Index brow, Index bcol) const - { - eigen_assert(brow < blockRows() && "BLOCK ROW INDEX OUT OF BOUNDS"); - eigen_assert(bcol < blockCols() && "BLOCK COLUMN OUT OF BOUNDS"); - - StorageIndex rsize = IsColMajor ? blockInnerSize(brow): blockOuterSize(bcol); - StorageIndex csize = IsColMajor ? blockOuterSize(bcol) : blockInnerSize(brow); - StorageIndex inner = IsColMajor ? brow : bcol; - StorageIndex outer = IsColMajor ? bcol : brow; - StorageIndex offset = m_outerIndex[outer]; - while(offset < m_outerIndex[outer+1] && m_indices[offset] != inner) offset++; - if(m_indices[offset] == inner) - { - return Map<const BlockScalar> (&(m_values[blockPtr(offset)]), rsize, csize); - } - else -// return BlockScalar::Zero(rsize, csize); - eigen_assert("NOT YET SUPPORTED"); - } - - // Block Matrix times vector product - template<typename VecType> - BlockSparseTimeDenseProduct<BlockSparseMatrix, VecType> operator*(const VecType& lhs) const - { - return BlockSparseTimeDenseProduct<BlockSparseMatrix, VecType>(*this, lhs); - } - - /** \returns the number of nonzero blocks */ - inline Index nonZerosBlocks() const { return m_nonzerosblocks; } - /** \returns the total number of nonzero elements, including eventual explicit zeros in blocks */ - inline Index nonZeros() const { return m_nonzeros; } - - inline BlockScalarReturnType *valuePtr() {return static_cast<BlockScalarReturnType *>(m_values);} -// inline Scalar *valuePtr(){ return m_values; } - inline StorageIndex *innerIndexPtr() {return m_indices; } - inline const StorageIndex *innerIndexPtr() const {return m_indices; } - inline StorageIndex *outerIndexPtr() {return m_outerIndex; } - inline const StorageIndex* outerIndexPtr() const {return m_outerIndex; } - - /** \brief for compatibility purposes with the SparseMatrix class */ - inline bool isCompressed() const {return true;} - /** - * \returns the starting index of the bi row block - */ - inline Index blockRowsIndex(Index bi) const - { - return IsColMajor ? blockInnerIndex(bi) : blockOuterIndex(bi); - } - - /** - * \returns the starting index of the bj col block - */ - inline Index blockColsIndex(Index bj) const - { - return IsColMajor ? blockOuterIndex(bj) : blockInnerIndex(bj); - } - - inline Index blockOuterIndex(Index bj) const - { - return (m_blockSize == Dynamic) ? m_outerOffset[bj] : (bj * m_blockSize); - } - inline Index blockInnerIndex(Index bi) const - { - return (m_blockSize == Dynamic) ? m_innerOffset[bi] : (bi * m_blockSize); - } - - // Not needed ??? - inline Index blockInnerSize(Index bi) const - { - return (m_blockSize == Dynamic) ? (m_innerOffset[bi+1] - m_innerOffset[bi]) : m_blockSize; - } - inline Index blockOuterSize(Index bj) const - { - return (m_blockSize == Dynamic) ? (m_outerOffset[bj+1]- m_outerOffset[bj]) : m_blockSize; - } - - /** - * \brief Browse the matrix by outer index - */ - class InnerIterator; // Browse column by column - - /** - * \brief Browse the matrix by block outer index - */ - class BlockInnerIterator; // Browse block by block - - friend std::ostream & operator << (std::ostream & s, const BlockSparseMatrix& m) - { - for (StorageIndex j = 0; j < m.outerBlocks(); ++j) - { - BlockInnerIterator itb(m, j); - for(; itb; ++itb) - { - s << "("<<itb.row() << ", " << itb.col() << ")\n"; - s << itb.value() <<"\n"; - } - } - s << std::endl; - return s; - } - - /** - * \returns the starting position of the block \p id in the array of values - */ - Index blockPtr(Index id) const - { - if(m_blockSize == Dynamic) return m_blockPtr[id]; - else return id * m_blockSize * m_blockSize; - //return blockDynIdx(id, typename internal::conditional<(BlockSize==Dynamic), internal::true_type, internal::false_type>::type()); - } - - - protected: -// inline Index blockDynIdx(Index id, internal::true_type) const -// { -// return m_blockPtr[id]; -// } -// inline Index blockDynIdx(Index id, internal::false_type) const -// { -// return id * BlockSize * BlockSize; -// } - - // To be implemented - // Insert a block at a particular location... need to make a room for that - Map<BlockScalar> insert(Index brow, Index bcol); - - Index m_innerBSize; // Number of block rows - Index m_outerBSize; // Number of block columns - StorageIndex *m_innerOffset; // Starting index of each inner block (size m_innerBSize+1) - StorageIndex *m_outerOffset; // Starting index of each outer block (size m_outerBSize+1) - Index m_nonzerosblocks; // Total nonzeros blocks (lower than m_innerBSize x m_outerBSize) - Index m_nonzeros; // Total nonzeros elements - Scalar *m_values; //Values stored block column after block column (size m_nonzeros) - StorageIndex *m_blockPtr; // Pointer to the beginning of each block in m_values, size m_nonzeroblocks ... null for fixed-size blocks - StorageIndex *m_indices; //Inner block indices, size m_nonzerosblocks ... OK - StorageIndex *m_outerIndex; // Starting pointer of each block column in m_indices (size m_outerBSize)... OK - Index m_blockSize; // Size of a block for fixed-size blocks, otherwise -1 -}; - -template<typename _Scalar, int _BlockAtCompileTime, int _Options, typename _StorageIndex> -class BlockSparseMatrix<_Scalar, _BlockAtCompileTime, _Options, _StorageIndex>::BlockInnerIterator -{ - public: - - enum{ - Flags = _Options - }; - - BlockInnerIterator(const BlockSparseMatrix& mat, const Index outer) - : m_mat(mat),m_outer(outer), - m_id(mat.m_outerIndex[outer]), - m_end(mat.m_outerIndex[outer+1]) - { - } - - inline BlockInnerIterator& operator++() {m_id++; return *this; } - - inline const Map<const BlockScalar> value() const - { - return Map<const BlockScalar>(&(m_mat.m_values[m_mat.blockPtr(m_id)]), - rows(),cols()); - } - inline Map<BlockScalar> valueRef() - { - return Map<BlockScalar>(&(m_mat.m_values[m_mat.blockPtr(m_id)]), - rows(),cols()); - } - // Block inner index - inline Index index() const {return m_mat.m_indices[m_id]; } - inline Index outer() const { return m_outer; } - // block row index - inline Index row() const {return index(); } - // block column index - inline Index col() const {return outer(); } - // FIXME Number of rows in the current block - inline Index rows() const { return (m_mat.m_blockSize==Dynamic) ? (m_mat.m_innerOffset[index()+1] - m_mat.m_innerOffset[index()]) : m_mat.m_blockSize; } - // Number of columns in the current block ... - inline Index cols() const { return (m_mat.m_blockSize==Dynamic) ? (m_mat.m_outerOffset[m_outer+1]-m_mat.m_outerOffset[m_outer]) : m_mat.m_blockSize;} - inline operator bool() const { return (m_id < m_end); } - - protected: - const BlockSparseMatrix<_Scalar, _BlockAtCompileTime, _Options, StorageIndex>& m_mat; - const Index m_outer; - Index m_id; - Index m_end; -}; - -template<typename _Scalar, int _BlockAtCompileTime, int _Options, typename _StorageIndex> -class BlockSparseMatrix<_Scalar, _BlockAtCompileTime, _Options, _StorageIndex>::InnerIterator -{ - public: - InnerIterator(const BlockSparseMatrix& mat, Index outer) - : m_mat(mat),m_outerB(mat.outerToBlock(outer)),m_outer(outer), - itb(mat, mat.outerToBlock(outer)), - m_offset(outer - mat.blockOuterIndex(m_outerB)) - { - if (itb) - { - m_id = m_mat.blockInnerIndex(itb.index()); - m_start = m_id; - m_end = m_mat.blockInnerIndex(itb.index()+1); - } - } - inline InnerIterator& operator++() - { - m_id++; - if (m_id >= m_end) - { - ++itb; - if (itb) - { - m_id = m_mat.blockInnerIndex(itb.index()); - m_start = m_id; - m_end = m_mat.blockInnerIndex(itb.index()+1); - } - } - return *this; - } - inline const Scalar& value() const - { - return itb.value().coeff(m_id - m_start, m_offset); - } - inline Scalar& valueRef() - { - return itb.valueRef().coeff(m_id - m_start, m_offset); - } - inline Index index() const { return m_id; } - inline Index outer() const {return m_outer; } - inline Index col() const {return outer(); } - inline Index row() const { return index();} - inline operator bool() const - { - return itb; - } - protected: - const BlockSparseMatrix& m_mat; - const Index m_outer; - const Index m_outerB; - BlockInnerIterator itb; // Iterator through the blocks - const Index m_offset; // Position of this column in the block - Index m_start; // starting inner index of this block - Index m_id; // current inner index in the block - Index m_end; // starting inner index of the next block - -}; -} // end namespace Eigen - -#endif // EIGEN_SPARSEBLOCKMATRIX_H diff --git a/eigen/unsupported/Eigen/src/SparseExtra/DynamicSparseMatrix.h b/eigen/unsupported/Eigen/src/SparseExtra/DynamicSparseMatrix.h deleted file mode 100644 index 0ffbc43..0000000 --- a/eigen/unsupported/Eigen/src/SparseExtra/DynamicSparseMatrix.h +++ /dev/null @@ -1,404 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_DYNAMIC_SPARSEMATRIX_H -#define EIGEN_DYNAMIC_SPARSEMATRIX_H - -namespace Eigen { - -/** \deprecated use a SparseMatrix in an uncompressed mode - * - * \class DynamicSparseMatrix - * - * \brief A sparse matrix class designed for matrix assembly purpose - * - * \param _Scalar the scalar type, i.e. the type of the coefficients - * - * Unlike SparseMatrix, this class provides a much higher degree of flexibility. In particular, it allows - * random read/write accesses in log(rho*outer_size) where \c rho is the probability that a coefficient is - * nonzero and outer_size is the number of columns if the matrix is column-major and the number of rows - * otherwise. - * - * Internally, the data are stored as a std::vector of compressed vector. The performances of random writes might - * decrease as the number of nonzeros per inner-vector increase. In practice, we observed very good performance - * till about 100 nonzeros/vector, and the performance remains relatively good till 500 nonzeros/vectors. - * - * \see SparseMatrix - */ - -namespace internal { -template<typename _Scalar, int _Options, typename _StorageIndex> -struct traits<DynamicSparseMatrix<_Scalar, _Options, _StorageIndex> > -{ - typedef _Scalar Scalar; - typedef _StorageIndex StorageIndex; - typedef Sparse StorageKind; - typedef MatrixXpr XprKind; - enum { - RowsAtCompileTime = Dynamic, - ColsAtCompileTime = Dynamic, - MaxRowsAtCompileTime = Dynamic, - MaxColsAtCompileTime = Dynamic, - Flags = _Options | NestByRefBit | LvalueBit, - CoeffReadCost = NumTraits<Scalar>::ReadCost, - SupportedAccessPatterns = OuterRandomAccessPattern - }; -}; -} - -template<typename _Scalar, int _Options, typename _StorageIndex> - class DynamicSparseMatrix - : public SparseMatrixBase<DynamicSparseMatrix<_Scalar, _Options, _StorageIndex> > -{ - typedef SparseMatrixBase<DynamicSparseMatrix> Base; - using Base::convert_index; - public: - EIGEN_SPARSE_PUBLIC_INTERFACE(DynamicSparseMatrix) - // FIXME: why are these operator already alvailable ??? - // EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, +=) - // EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, -=) - typedef MappedSparseMatrix<Scalar,Flags> Map; - using Base::IsRowMajor; - using Base::operator=; - enum { - Options = _Options - }; - - protected: - - typedef DynamicSparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0), StorageIndex> TransposedSparseMatrix; - - Index m_innerSize; - std::vector<internal::CompressedStorage<Scalar,StorageIndex> > m_data; - - public: - - inline Index rows() const { return IsRowMajor ? outerSize() : m_innerSize; } - inline Index cols() const { return IsRowMajor ? m_innerSize : outerSize(); } - inline Index innerSize() const { return m_innerSize; } - inline Index outerSize() const { return convert_index(m_data.size()); } - inline Index innerNonZeros(Index j) const { return m_data[j].size(); } - - std::vector<internal::CompressedStorage<Scalar,StorageIndex> >& _data() { return m_data; } - const std::vector<internal::CompressedStorage<Scalar,StorageIndex> >& _data() const { return m_data; } - - /** \returns the coefficient value at given position \a row, \a col - * This operation involes a log(rho*outer_size) binary search. - */ - inline Scalar coeff(Index row, Index col) const - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return m_data[outer].at(inner); - } - - /** \returns a reference to the coefficient value at given position \a row, \a col - * This operation involes a log(rho*outer_size) binary search. If the coefficient does not - * exist yet, then a sorted insertion into a sequential buffer is performed. - */ - inline Scalar& coeffRef(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return m_data[outer].atWithInsertion(inner); - } - - class InnerIterator; - class ReverseInnerIterator; - - void setZero() - { - for (Index j=0; j<outerSize(); ++j) - m_data[j].clear(); - } - - /** \returns the number of non zero coefficients */ - Index nonZeros() const - { - Index res = 0; - for (Index j=0; j<outerSize(); ++j) - res += m_data[j].size(); - return res; - } - - - - void reserve(Index reserveSize = 1000) - { - if (outerSize()>0) - { - Index reserveSizePerVector = (std::max)(reserveSize/outerSize(),Index(4)); - for (Index j=0; j<outerSize(); ++j) - { - m_data[j].reserve(reserveSizePerVector); - } - } - } - - /** Does nothing: provided for compatibility with SparseMatrix */ - inline void startVec(Index /*outer*/) {} - - /** \returns a reference to the non zero coefficient at position \a row, \a col assuming that: - * - the nonzero does not already exist - * - the new coefficient is the last one of the given inner vector. - * - * \sa insert, insertBackByOuterInner */ - inline Scalar& insertBack(Index row, Index col) - { - return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row); - } - - /** \sa insertBack */ - inline Scalar& insertBackByOuterInner(Index outer, Index inner) - { - eigen_assert(outer<Index(m_data.size()) && inner<m_innerSize && "out of range"); - eigen_assert(((m_data[outer].size()==0) || (m_data[outer].index(m_data[outer].size()-1)<inner)) - && "wrong sorted insertion"); - m_data[outer].append(0, inner); - return m_data[outer].value(m_data[outer].size()-1); - } - - inline Scalar& insert(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - Index startId = 0; - Index id = static_cast<Index>(m_data[outer].size()) - 1; - m_data[outer].resize(id+2,1); - - while ( (id >= startId) && (m_data[outer].index(id) > inner) ) - { - m_data[outer].index(id+1) = m_data[outer].index(id); - m_data[outer].value(id+1) = m_data[outer].value(id); - --id; - } - m_data[outer].index(id+1) = inner; - m_data[outer].value(id+1) = 0; - return m_data[outer].value(id+1); - } - - /** Does nothing: provided for compatibility with SparseMatrix */ - inline void finalize() {} - - /** Suppress all nonzeros which are smaller than \a reference under the tolerence \a epsilon */ - void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision()) - { - for (Index j=0; j<outerSize(); ++j) - m_data[j].prune(reference,epsilon); - } - - /** Resize the matrix without preserving the data (the matrix is set to zero) - */ - void resize(Index rows, Index cols) - { - const Index outerSize = IsRowMajor ? rows : cols; - m_innerSize = convert_index(IsRowMajor ? cols : rows); - setZero(); - if (Index(m_data.size()) != outerSize) - { - m_data.resize(outerSize); - } - } - - void resizeAndKeepData(Index rows, Index cols) - { - const Index outerSize = IsRowMajor ? rows : cols; - const Index innerSize = IsRowMajor ? cols : rows; - if (m_innerSize>innerSize) - { - // remove all coefficients with innerCoord>=innerSize - // TODO - //std::cerr << "not implemented yet\n"; - exit(2); - } - if (m_data.size() != outerSize) - { - m_data.resize(outerSize); - } - } - - /** The class DynamicSparseMatrix is deprectaed */ - EIGEN_DEPRECATED inline DynamicSparseMatrix() - : m_innerSize(0), m_data(0) - { - #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - #endif - eigen_assert(innerSize()==0 && outerSize()==0); - } - - /** The class DynamicSparseMatrix is deprectaed */ - EIGEN_DEPRECATED inline DynamicSparseMatrix(Index rows, Index cols) - : m_innerSize(0) - { - #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - #endif - resize(rows, cols); - } - - /** The class DynamicSparseMatrix is deprectaed */ - template<typename OtherDerived> - EIGEN_DEPRECATED explicit inline DynamicSparseMatrix(const SparseMatrixBase<OtherDerived>& other) - : m_innerSize(0) - { - #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - #endif - Base::operator=(other.derived()); - } - - inline DynamicSparseMatrix(const DynamicSparseMatrix& other) - : Base(), m_innerSize(0) - { - #ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN - #endif - *this = other.derived(); - } - - inline void swap(DynamicSparseMatrix& other) - { - //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n"); - std::swap(m_innerSize, other.m_innerSize); - //std::swap(m_outerSize, other.m_outerSize); - m_data.swap(other.m_data); - } - - inline DynamicSparseMatrix& operator=(const DynamicSparseMatrix& other) - { - if (other.isRValue()) - { - swap(other.const_cast_derived()); - } - else - { - resize(other.rows(), other.cols()); - m_data = other.m_data; - } - return *this; - } - - /** Destructor */ - inline ~DynamicSparseMatrix() {} - - public: - - /** \deprecated - * Set the matrix to zero and reserve the memory for \a reserveSize nonzero coefficients. */ - EIGEN_DEPRECATED void startFill(Index reserveSize = 1000) - { - setZero(); - reserve(reserveSize); - } - - /** \deprecated use insert() - * inserts a nonzero coefficient at given coordinates \a row, \a col and returns its reference assuming that: - * 1 - the coefficient does not exist yet - * 2 - this the coefficient with greater inner coordinate for the given outer coordinate. - * In other words, assuming \c *this is column-major, then there must not exists any nonzero coefficient of coordinates - * \c i \c x \a col such that \c i >= \a row. Otherwise the matrix is invalid. - * - * \see fillrand(), coeffRef() - */ - EIGEN_DEPRECATED Scalar& fill(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return insertBack(outer,inner); - } - - /** \deprecated use insert() - * Like fill() but with random inner coordinates. - * Compared to the generic coeffRef(), the unique limitation is that we assume - * the coefficient does not exist yet. - */ - EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col) - { - return insert(row,col); - } - - /** \deprecated use finalize() - * Does nothing. Provided for compatibility with SparseMatrix. */ - EIGEN_DEPRECATED void endFill() {} - -# ifdef EIGEN_DYNAMICSPARSEMATRIX_PLUGIN -# include EIGEN_DYNAMICSPARSEMATRIX_PLUGIN -# endif - }; - -template<typename Scalar, int _Options, typename _StorageIndex> -class DynamicSparseMatrix<Scalar,_Options,_StorageIndex>::InnerIterator : public SparseVector<Scalar,_Options,_StorageIndex>::InnerIterator -{ - typedef typename SparseVector<Scalar,_Options,_StorageIndex>::InnerIterator Base; - public: - InnerIterator(const DynamicSparseMatrix& mat, Index outer) - : Base(mat.m_data[outer]), m_outer(outer) - {} - - inline Index row() const { return IsRowMajor ? m_outer : Base::index(); } - inline Index col() const { return IsRowMajor ? Base::index() : m_outer; } - inline Index outer() const { return m_outer; } - - protected: - const Index m_outer; -}; - -template<typename Scalar, int _Options, typename _StorageIndex> -class DynamicSparseMatrix<Scalar,_Options,_StorageIndex>::ReverseInnerIterator : public SparseVector<Scalar,_Options,_StorageIndex>::ReverseInnerIterator -{ - typedef typename SparseVector<Scalar,_Options,_StorageIndex>::ReverseInnerIterator Base; - public: - ReverseInnerIterator(const DynamicSparseMatrix& mat, Index outer) - : Base(mat.m_data[outer]), m_outer(outer) - {} - - inline Index row() const { return IsRowMajor ? m_outer : Base::index(); } - inline Index col() const { return IsRowMajor ? Base::index() : m_outer; } - inline Index outer() const { return m_outer; } - - protected: - const Index m_outer; -}; - -namespace internal { - -template<typename _Scalar, int _Options, typename _StorageIndex> -struct evaluator<DynamicSparseMatrix<_Scalar,_Options,_StorageIndex> > - : evaluator_base<DynamicSparseMatrix<_Scalar,_Options,_StorageIndex> > -{ - typedef _Scalar Scalar; - typedef DynamicSparseMatrix<_Scalar,_Options,_StorageIndex> SparseMatrixType; - typedef typename SparseMatrixType::InnerIterator InnerIterator; - typedef typename SparseMatrixType::ReverseInnerIterator ReverseInnerIterator; - - enum { - CoeffReadCost = NumTraits<_Scalar>::ReadCost, - Flags = SparseMatrixType::Flags - }; - - evaluator() : m_matrix(0) {} - evaluator(const SparseMatrixType &mat) : m_matrix(&mat) {} - - operator SparseMatrixType&() { return m_matrix->const_cast_derived(); } - operator const SparseMatrixType&() const { return *m_matrix; } - - Scalar coeff(Index row, Index col) const { return m_matrix->coeff(row,col); } - - Index nonZerosEstimate() const { return m_matrix->nonZeros(); } - - const SparseMatrixType *m_matrix; -}; - -} - -} // end namespace Eigen - -#endif // EIGEN_DYNAMIC_SPARSEMATRIX_H diff --git a/eigen/unsupported/Eigen/src/SparseExtra/MarketIO.h b/eigen/unsupported/Eigen/src/SparseExtra/MarketIO.h deleted file mode 100644 index 04b7d69..0000000 --- a/eigen/unsupported/Eigen/src/SparseExtra/MarketIO.h +++ /dev/null @@ -1,275 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr> -// Copyright (C) 2012 Desire NUENTSA WAKAM <desire.nuentsa_wakam@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPARSE_MARKET_IO_H -#define EIGEN_SPARSE_MARKET_IO_H - -#include <iostream> - -namespace Eigen { - -namespace internal -{ - template <typename Scalar,typename IndexType> - inline bool GetMarketLine (std::stringstream& line, IndexType& M, IndexType& N, IndexType& i, IndexType& j, Scalar& value) - { - line >> i >> j >> value; - i--; - j--; - if(i>=0 && j>=0 && i<M && j<N) - { - return true; - } - else - return false; - } - template <typename Scalar,typename IndexType> - inline bool GetMarketLine (std::stringstream& line, IndexType& M, IndexType& N, IndexType& i, IndexType& j, std::complex<Scalar>& value) - { - Scalar valR, valI; - line >> i >> j >> valR >> valI; - i--; - j--; - if(i>=0 && j>=0 && i<M && j<N) - { - value = std::complex<Scalar>(valR, valI); - return true; - } - else - return false; - } - - template <typename RealScalar> - inline void GetVectorElt (const std::string& line, RealScalar& val) - { - std::istringstream newline(line); - newline >> val; - } - - template <typename RealScalar> - inline void GetVectorElt (const std::string& line, std::complex<RealScalar>& val) - { - RealScalar valR, valI; - std::istringstream newline(line); - newline >> valR >> valI; - val = std::complex<RealScalar>(valR, valI); - } - - template<typename Scalar> - inline void putMarketHeader(std::string& header,int sym) - { - header= "%%MatrixMarket matrix coordinate "; - if(internal::is_same<Scalar, std::complex<float> >::value || internal::is_same<Scalar, std::complex<double> >::value) - { - header += " complex"; - if(sym == Symmetric) header += " symmetric"; - else if (sym == SelfAdjoint) header += " Hermitian"; - else header += " general"; - } - else - { - header += " real"; - if(sym == Symmetric) header += " symmetric"; - else header += " general"; - } - } - - template<typename Scalar> - inline void PutMatrixElt(Scalar value, int row, int col, std::ofstream& out) - { - out << row << " "<< col << " " << value << "\n"; - } - template<typename Scalar> - inline void PutMatrixElt(std::complex<Scalar> value, int row, int col, std::ofstream& out) - { - out << row << " " << col << " " << value.real() << " " << value.imag() << "\n"; - } - - - template<typename Scalar> - inline void putVectorElt(Scalar value, std::ofstream& out) - { - out << value << "\n"; - } - template<typename Scalar> - inline void putVectorElt(std::complex<Scalar> value, std::ofstream& out) - { - out << value.real << " " << value.imag()<< "\n"; - } - -} // end namepsace internal - -inline bool getMarketHeader(const std::string& filename, int& sym, bool& iscomplex, bool& isvector) -{ - sym = 0; - iscomplex = false; - isvector = false; - std::ifstream in(filename.c_str(),std::ios::in); - if(!in) - return false; - - std::string line; - // The matrix header is always the first line in the file - std::getline(in, line); eigen_assert(in.good()); - - std::stringstream fmtline(line); - std::string substr[5]; - fmtline>> substr[0] >> substr[1] >> substr[2] >> substr[3] >> substr[4]; - if(substr[2].compare("array") == 0) isvector = true; - if(substr[3].compare("complex") == 0) iscomplex = true; - if(substr[4].compare("symmetric") == 0) sym = Symmetric; - else if (substr[4].compare("Hermitian") == 0) sym = SelfAdjoint; - - return true; -} - -template<typename SparseMatrixType> -bool loadMarket(SparseMatrixType& mat, const std::string& filename) -{ - typedef typename SparseMatrixType::Scalar Scalar; - typedef typename SparseMatrixType::StorageIndex StorageIndex; - std::ifstream input(filename.c_str(),std::ios::in); - if(!input) - return false; - - const int maxBuffersize = 2048; - char buffer[maxBuffersize]; - - bool readsizes = false; - - typedef Triplet<Scalar,StorageIndex> T; - std::vector<T> elements; - - StorageIndex M(-1), N(-1), NNZ(-1); - StorageIndex count = 0; - while(input.getline(buffer, maxBuffersize)) - { - // skip comments - //NOTE An appropriate test should be done on the header to get the symmetry - if(buffer[0]=='%') - continue; - - std::stringstream line(buffer); - - if(!readsizes) - { - line >> M >> N >> NNZ; - if(M > 0 && N > 0 && NNZ > 0) - { - readsizes = true; - //std::cout << "sizes: " << M << "," << N << "," << NNZ << "\n"; - mat.resize(M,N); - mat.reserve(NNZ); - } - } - else - { - StorageIndex i(-1), j(-1); - Scalar value; - if( internal::GetMarketLine(line, M, N, i, j, value) ) - { - ++ count; - elements.push_back(T(i,j,value)); - } - else - std::cerr << "Invalid read: " << i << "," << j << "\n"; - } - } - mat.setFromTriplets(elements.begin(), elements.end()); - if(count!=NNZ) - std::cerr << count << "!=" << NNZ << "\n"; - - input.close(); - return true; -} - -template<typename VectorType> -bool loadMarketVector(VectorType& vec, const std::string& filename) -{ - typedef typename VectorType::Scalar Scalar; - std::ifstream in(filename.c_str(), std::ios::in); - if(!in) - return false; - - std::string line; - int n(0), col(0); - do - { // Skip comments - std::getline(in, line); eigen_assert(in.good()); - } while (line[0] == '%'); - std::istringstream newline(line); - newline >> n >> col; - eigen_assert(n>0 && col>0); - vec.resize(n); - int i = 0; - Scalar value; - while ( std::getline(in, line) && (i < n) ){ - internal::GetVectorElt(line, value); - vec(i++) = value; - } - in.close(); - if (i!=n){ - std::cerr<< "Unable to read all elements from file " << filename << "\n"; - return false; - } - return true; -} - -template<typename SparseMatrixType> -bool saveMarket(const SparseMatrixType& mat, const std::string& filename, int sym = 0) -{ - typedef typename SparseMatrixType::Scalar Scalar; - std::ofstream out(filename.c_str(),std::ios::out); - if(!out) - return false; - - out.flags(std::ios_base::scientific); - out.precision(64); - std::string header; - internal::putMarketHeader<Scalar>(header, sym); - out << header << std::endl; - out << mat.rows() << " " << mat.cols() << " " << mat.nonZeros() << "\n"; - int count = 0; - for(int j=0; j<mat.outerSize(); ++j) - for(typename SparseMatrixType::InnerIterator it(mat,j); it; ++it) - { - ++ count; - internal::PutMatrixElt(it.value(), it.row()+1, it.col()+1, out); - // out << it.row()+1 << " " << it.col()+1 << " " << it.value() << "\n"; - } - out.close(); - return true; -} - -template<typename VectorType> -bool saveMarketVector (const VectorType& vec, const std::string& filename) -{ - typedef typename VectorType::Scalar Scalar; - std::ofstream out(filename.c_str(),std::ios::out); - if(!out) - return false; - - out.flags(std::ios_base::scientific); - out.precision(64); - if(internal::is_same<Scalar, std::complex<float> >::value || internal::is_same<Scalar, std::complex<double> >::value) - out << "%%MatrixMarket matrix array complex general\n"; - else - out << "%%MatrixMarket matrix array real general\n"; - out << vec.size() << " "<< 1 << "\n"; - for (int i=0; i < vec.size(); i++){ - internal::putVectorElt(vec(i), out); - } - out.close(); - return true; -} - -} // end namespace Eigen - -#endif // EIGEN_SPARSE_MARKET_IO_H diff --git a/eigen/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h b/eigen/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h deleted file mode 100644 index 02916ea..0000000 --- a/eigen/unsupported/Eigen/src/SparseExtra/MatrixMarketIterator.h +++ /dev/null @@ -1,247 +0,0 @@ - -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2012 Desire NUENTSA WAKAM <desire.nuentsa_wakam@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_BROWSE_MATRICES_H -#define EIGEN_BROWSE_MATRICES_H - -namespace Eigen { - -enum { - SPD = 0x100, - NonSymmetric = 0x0 -}; - -/** - * @brief Iterator to browse matrices from a specified folder - * - * This is used to load all the matrices from a folder. - * The matrices should be in Matrix Market format - * It is assumed that the matrices are named as matname.mtx - * and matname_SPD.mtx if the matrix is Symmetric and positive definite (or Hermitian) - * The right hand side vectors are loaded as well, if they exist. - * They should be named as matname_b.mtx. - * Note that the right hand side for a SPD matrix is named as matname_SPD_b.mtx - * - * Sometimes a reference solution is available. In this case, it should be named as matname_x.mtx - * - * Sample code - * \code - * - * \endcode - * - * \tparam Scalar The scalar type - */ -template <typename Scalar> -class MatrixMarketIterator -{ - typedef typename NumTraits<Scalar>::Real RealScalar; - public: - typedef Matrix<Scalar,Dynamic,1> VectorType; - typedef SparseMatrix<Scalar,ColMajor> MatrixType; - - public: - MatrixMarketIterator(const std::string &folder) - : m_sym(0), m_isvalid(false), m_matIsLoaded(false), m_hasRhs(false), m_hasrefX(false), m_folder(folder) - { - m_folder_id = opendir(folder.c_str()); - if(m_folder_id) - Getnextvalidmatrix(); - } - - ~MatrixMarketIterator() - { - if (m_folder_id) closedir(m_folder_id); - } - - inline MatrixMarketIterator& operator++() - { - m_matIsLoaded = false; - m_hasrefX = false; - m_hasRhs = false; - Getnextvalidmatrix(); - return *this; - } - inline operator bool() const { return m_isvalid;} - - /** Return the sparse matrix corresponding to the current file */ - inline MatrixType& matrix() - { - // Read the matrix - if (m_matIsLoaded) return m_mat; - - std::string matrix_file = m_folder + "/" + m_matname + ".mtx"; - if ( !loadMarket(m_mat, matrix_file)) - { - std::cerr << "Warning loadMarket failed when loading \"" << matrix_file << "\"" << std::endl; - m_matIsLoaded = false; - return m_mat; - } - m_matIsLoaded = true; - - if (m_sym != NonSymmetric) - { - // Check whether we need to restore a full matrix: - RealScalar diag_norm = m_mat.diagonal().norm(); - RealScalar lower_norm = m_mat.template triangularView<Lower>().norm(); - RealScalar upper_norm = m_mat.template triangularView<Upper>().norm(); - if(lower_norm>diag_norm && upper_norm==diag_norm) - { - // only the lower part is stored - MatrixType tmp(m_mat); - m_mat = tmp.template selfadjointView<Lower>(); - } - else if(upper_norm>diag_norm && lower_norm==diag_norm) - { - // only the upper part is stored - MatrixType tmp(m_mat); - m_mat = tmp.template selfadjointView<Upper>(); - } - } - return m_mat; - } - - /** Return the right hand side corresponding to the current matrix. - * If the rhs file is not provided, a random rhs is generated - */ - inline VectorType& rhs() - { - // Get the right hand side - if (m_hasRhs) return m_rhs; - - std::string rhs_file; - rhs_file = m_folder + "/" + m_matname + "_b.mtx"; // The pattern is matname_b.mtx - m_hasRhs = Fileexists(rhs_file); - if (m_hasRhs) - { - m_rhs.resize(m_mat.cols()); - m_hasRhs = loadMarketVector(m_rhs, rhs_file); - } - if (!m_hasRhs) - { - // Generate a random right hand side - if (!m_matIsLoaded) this->matrix(); - m_refX.resize(m_mat.cols()); - m_refX.setRandom(); - m_rhs = m_mat * m_refX; - m_hasrefX = true; - m_hasRhs = true; - } - return m_rhs; - } - - /** Return a reference solution - * If it is not provided and if the right hand side is not available - * then refX is randomly generated such that A*refX = b - * where A and b are the matrix and the rhs. - * Note that when a rhs is provided, refX is not available - */ - inline VectorType& refX() - { - // Check if a reference solution is provided - if (m_hasrefX) return m_refX; - - std::string lhs_file; - lhs_file = m_folder + "/" + m_matname + "_x.mtx"; - m_hasrefX = Fileexists(lhs_file); - if (m_hasrefX) - { - m_refX.resize(m_mat.cols()); - m_hasrefX = loadMarketVector(m_refX, lhs_file); - } - else - m_refX.resize(0); - return m_refX; - } - - inline std::string& matname() { return m_matname; } - - inline int sym() { return m_sym; } - - bool hasRhs() {return m_hasRhs; } - bool hasrefX() {return m_hasrefX; } - bool isFolderValid() { return bool(m_folder_id); } - - protected: - - inline bool Fileexists(std::string file) - { - std::ifstream file_id(file.c_str()); - if (!file_id.good() ) - { - return false; - } - else - { - file_id.close(); - return true; - } - } - - void Getnextvalidmatrix( ) - { - m_isvalid = false; - // Here, we return with the next valid matrix in the folder - while ( (m_curs_id = readdir(m_folder_id)) != NULL) { - m_isvalid = false; - std::string curfile; - curfile = m_folder + "/" + m_curs_id->d_name; - // Discard if it is a folder - if (m_curs_id->d_type == DT_DIR) continue; //FIXME This may not be available on non BSD systems -// struct stat st_buf; -// stat (curfile.c_str(), &st_buf); -// if (S_ISDIR(st_buf.st_mode)) continue; - - // Determine from the header if it is a matrix or a right hand side - bool isvector,iscomplex=false; - if(!getMarketHeader(curfile,m_sym,iscomplex,isvector)) continue; - if(isvector) continue; - if (!iscomplex) - { - if(internal::is_same<Scalar, std::complex<float> >::value || internal::is_same<Scalar, std::complex<double> >::value) - continue; - } - if (iscomplex) - { - if(internal::is_same<Scalar, float>::value || internal::is_same<Scalar, double>::value) - continue; - } - - - // Get the matrix name - std::string filename = m_curs_id->d_name; - m_matname = filename.substr(0, filename.length()-4); - - // Find if the matrix is SPD - size_t found = m_matname.find("SPD"); - if( (found!=std::string::npos) && (m_sym != NonSymmetric) ) - m_sym = SPD; - - m_isvalid = true; - break; - } - } - int m_sym; // Symmetry of the matrix - MatrixType m_mat; // Current matrix - VectorType m_rhs; // Current vector - VectorType m_refX; // The reference solution, if exists - std::string m_matname; // Matrix Name - bool m_isvalid; - bool m_matIsLoaded; // Determine if the matrix has already been loaded from the file - bool m_hasRhs; // The right hand side exists - bool m_hasrefX; // A reference solution is provided - std::string m_folder; - DIR * m_folder_id; - struct dirent *m_curs_id; - -}; - -} // end namespace Eigen - -#endif diff --git a/eigen/unsupported/Eigen/src/SparseExtra/RandomSetter.h b/eigen/unsupported/Eigen/src/SparseExtra/RandomSetter.h deleted file mode 100644 index ee97299..0000000 --- a/eigen/unsupported/Eigen/src/SparseExtra/RandomSetter.h +++ /dev/null @@ -1,327 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_RANDOMSETTER_H -#define EIGEN_RANDOMSETTER_H - -namespace Eigen { - -/** Represents a std::map - * - * \see RandomSetter - */ -template<typename Scalar> struct StdMapTraits -{ - typedef int KeyType; - typedef std::map<KeyType,Scalar> Type; - enum { - IsSorted = 1 - }; - - static void setInvalidKey(Type&, const KeyType&) {} -}; - -#ifdef EIGEN_UNORDERED_MAP_SUPPORT -/** Represents a std::unordered_map - * - * To use it you need to both define EIGEN_UNORDERED_MAP_SUPPORT and include the unordered_map header file - * yourself making sure that unordered_map is defined in the std namespace. - * - * For instance, with current version of gcc you can either enable C++0x standard (-std=c++0x) or do: - * \code - * #include <tr1/unordered_map> - * #define EIGEN_UNORDERED_MAP_SUPPORT - * namespace std { - * using std::tr1::unordered_map; - * } - * \endcode - * - * \see RandomSetter - */ -template<typename Scalar> struct StdUnorderedMapTraits -{ - typedef int KeyType; - typedef std::unordered_map<KeyType,Scalar> Type; - enum { - IsSorted = 0 - }; - - static void setInvalidKey(Type&, const KeyType&) {} -}; -#endif // EIGEN_UNORDERED_MAP_SUPPORT - -#ifdef _DENSE_HASH_MAP_H_ -/** Represents a google::dense_hash_map - * - * \see RandomSetter - */ -template<typename Scalar> struct GoogleDenseHashMapTraits -{ - typedef int KeyType; - typedef google::dense_hash_map<KeyType,Scalar> Type; - enum { - IsSorted = 0 - }; - - static void setInvalidKey(Type& map, const KeyType& k) - { map.set_empty_key(k); } -}; -#endif - -#ifdef _SPARSE_HASH_MAP_H_ -/** Represents a google::sparse_hash_map - * - * \see RandomSetter - */ -template<typename Scalar> struct GoogleSparseHashMapTraits -{ - typedef int KeyType; - typedef google::sparse_hash_map<KeyType,Scalar> Type; - enum { - IsSorted = 0 - }; - - static void setInvalidKey(Type&, const KeyType&) {} -}; -#endif - -/** \class RandomSetter - * - * \brief The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access - * - * \tparam SparseMatrixType the type of the sparse matrix we are updating - * \tparam MapTraits a traits class representing the map implementation used for the temporary sparse storage. - * Its default value depends on the system. - * \tparam OuterPacketBits defines the number of rows (or columns) manage by a single map object - * as a power of two exponent. - * - * This class temporarily represents a sparse matrix object using a generic map implementation allowing for - * efficient random access. The conversion from the compressed representation to a hash_map object is performed - * in the RandomSetter constructor, while the sparse matrix is updated back at destruction time. This strategy - * suggest the use of nested blocks as in this example: - * - * \code - * SparseMatrix<double> m(rows,cols); - * { - * RandomSetter<SparseMatrix<double> > w(m); - * // don't use m but w instead with read/write random access to the coefficients: - * for(;;) - * w(rand(),rand()) = rand; - * } - * // when w is deleted, the data are copied back to m - * // and m is ready to use. - * \endcode - * - * Since hash_map objects are not fully sorted, representing a full matrix as a single hash_map would - * involve a big and costly sort to update the compressed matrix back. To overcome this issue, a RandomSetter - * use multiple hash_map, each representing 2^OuterPacketBits columns or rows according to the storage order. - * To reach optimal performance, this value should be adjusted according to the average number of nonzeros - * per rows/columns. - * - * The possible values for the template parameter MapTraits are: - * - \b StdMapTraits: corresponds to std::map. (does not perform very well) - * - \b GnuHashMapTraits: corresponds to __gnu_cxx::hash_map (available only with GCC) - * - \b GoogleDenseHashMapTraits: corresponds to google::dense_hash_map (best efficiency, reasonable memory consumption) - * - \b GoogleSparseHashMapTraits: corresponds to google::sparse_hash_map (best memory consumption, relatively good performance) - * - * The default map implementation depends on the availability, and the preferred order is: - * GoogleSparseHashMapTraits, GnuHashMapTraits, and finally StdMapTraits. - * - * For performance and memory consumption reasons it is highly recommended to use one of - * the Google's hash_map implementation. To enable the support for them, you have two options: - * - \#include <google/dense_hash_map> yourself \b before Eigen/Sparse header - * - define EIGEN_GOOGLEHASH_SUPPORT - * In the later case the inclusion of <google/dense_hash_map> is made for you. - * - * \see http://code.google.com/p/google-sparsehash/ - */ -template<typename SparseMatrixType, - template <typename T> class MapTraits = -#if defined _DENSE_HASH_MAP_H_ - GoogleDenseHashMapTraits -#elif defined _HASH_MAP - GnuHashMapTraits -#else - StdMapTraits -#endif - ,int OuterPacketBits = 6> -class RandomSetter -{ - typedef typename SparseMatrixType::Scalar Scalar; - typedef typename SparseMatrixType::StorageIndex StorageIndex; - - struct ScalarWrapper - { - ScalarWrapper() : value(0) {} - Scalar value; - }; - typedef typename MapTraits<ScalarWrapper>::KeyType KeyType; - typedef typename MapTraits<ScalarWrapper>::Type HashMapType; - static const int OuterPacketMask = (1 << OuterPacketBits) - 1; - enum { - SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted, - TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0, - SetterRowMajor = SwapStorage ? 1-TargetRowMajor : TargetRowMajor - }; - - public: - - /** Constructs a random setter object from the sparse matrix \a target - * - * Note that the initial value of \a target are imported. If you want to re-set - * a sparse matrix from scratch, then you must set it to zero first using the - * setZero() function. - */ - inline RandomSetter(SparseMatrixType& target) - : mp_target(&target) - { - const Index outerSize = SwapStorage ? target.innerSize() : target.outerSize(); - const Index innerSize = SwapStorage ? target.outerSize() : target.innerSize(); - m_outerPackets = outerSize >> OuterPacketBits; - if (outerSize&OuterPacketMask) - m_outerPackets += 1; - m_hashmaps = new HashMapType[m_outerPackets]; - // compute number of bits needed to store inner indices - Index aux = innerSize - 1; - m_keyBitsOffset = 0; - while (aux) - { - ++m_keyBitsOffset; - aux = aux >> 1; - } - KeyType ik = (1<<(OuterPacketBits+m_keyBitsOffset)); - for (Index k=0; k<m_outerPackets; ++k) - MapTraits<ScalarWrapper>::setInvalidKey(m_hashmaps[k],ik); - - // insert current coeffs - for (Index j=0; j<mp_target->outerSize(); ++j) - for (typename SparseMatrixType::InnerIterator it(*mp_target,j); it; ++it) - (*this)(TargetRowMajor?j:it.index(), TargetRowMajor?it.index():j) = it.value(); - } - - /** Destructor updating back the sparse matrix target */ - ~RandomSetter() - { - KeyType keyBitsMask = (1<<m_keyBitsOffset)-1; - if (!SwapStorage) // also means the map is sorted - { - mp_target->setZero(); - mp_target->makeCompressed(); - mp_target->reserve(nonZeros()); - Index prevOuter = -1; - for (Index k=0; k<m_outerPackets; ++k) - { - const Index outerOffset = (1<<OuterPacketBits) * k; - typename HashMapType::iterator end = m_hashmaps[k].end(); - for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it) - { - const Index outer = (it->first >> m_keyBitsOffset) + outerOffset; - const Index inner = it->first & keyBitsMask; - if (prevOuter!=outer) - { - for (Index j=prevOuter+1;j<=outer;++j) - mp_target->startVec(j); - prevOuter = outer; - } - mp_target->insertBackByOuterInner(outer, inner) = it->second.value; - } - } - mp_target->finalize(); - } - else - { - VectorXi positions(mp_target->outerSize()); - positions.setZero(); - // pass 1 - for (Index k=0; k<m_outerPackets; ++k) - { - typename HashMapType::iterator end = m_hashmaps[k].end(); - for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it) - { - const Index outer = it->first & keyBitsMask; - ++positions[outer]; - } - } - // prefix sum - Index count = 0; - for (Index j=0; j<mp_target->outerSize(); ++j) - { - Index tmp = positions[j]; - mp_target->outerIndexPtr()[j] = count; - positions[j] = count; - count += tmp; - } - mp_target->makeCompressed(); - mp_target->outerIndexPtr()[mp_target->outerSize()] = count; - mp_target->resizeNonZeros(count); - // pass 2 - for (Index k=0; k<m_outerPackets; ++k) - { - const Index outerOffset = (1<<OuterPacketBits) * k; - typename HashMapType::iterator end = m_hashmaps[k].end(); - for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it!=end; ++it) - { - const Index inner = (it->first >> m_keyBitsOffset) + outerOffset; - const Index outer = it->first & keyBitsMask; - // sorted insertion - // Note that we have to deal with at most 2^OuterPacketBits unsorted coefficients, - // moreover those 2^OuterPacketBits coeffs are likely to be sparse, an so only a - // small fraction of them have to be sorted, whence the following simple procedure: - Index posStart = mp_target->outerIndexPtr()[outer]; - Index i = (positions[outer]++) - 1; - while ( (i >= posStart) && (mp_target->innerIndexPtr()[i] > inner) ) - { - mp_target->valuePtr()[i+1] = mp_target->valuePtr()[i]; - mp_target->innerIndexPtr()[i+1] = mp_target->innerIndexPtr()[i]; - --i; - } - mp_target->innerIndexPtr()[i+1] = inner; - mp_target->valuePtr()[i+1] = it->second.value; - } - } - } - delete[] m_hashmaps; - } - - /** \returns a reference to the coefficient at given coordinates \a row, \a col */ - Scalar& operator() (Index row, Index col) - { - const Index outer = SetterRowMajor ? row : col; - const Index inner = SetterRowMajor ? col : row; - const Index outerMajor = outer >> OuterPacketBits; // index of the packet/map - const Index outerMinor = outer & OuterPacketMask; // index of the inner vector in the packet - const KeyType key = internal::convert_index<KeyType>((outerMinor<<m_keyBitsOffset) | inner); - return m_hashmaps[outerMajor][key].value; - } - - /** \returns the number of non zero coefficients - * - * \note According to the underlying map/hash_map implementation, - * this function might be quite expensive. - */ - Index nonZeros() const - { - Index nz = 0; - for (Index k=0; k<m_outerPackets; ++k) - nz += static_cast<Index>(m_hashmaps[k].size()); - return nz; - } - - - protected: - - HashMapType* m_hashmaps; - SparseMatrixType* mp_target; - Index m_outerPackets; - unsigned char m_keyBitsOffset; -}; - -} // end namespace Eigen - -#endif // EIGEN_RANDOMSETTER_H diff --git a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h b/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h deleted file mode 100644 index ed415db..0000000 --- a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsArrayAPI.h +++ /dev/null @@ -1,124 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2016 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -#ifndef EIGEN_SPECIALFUNCTIONS_ARRAYAPI_H -#define EIGEN_SPECIALFUNCTIONS_ARRAYAPI_H - -namespace Eigen { - -/** \cpp11 \returns an expression of the coefficient-wise igamma(\a a, \a x) to the given arrays. - * - * This function computes the coefficient-wise incomplete gamma function. - * - * \note This function supports only float and double scalar types in c++11 mode. To support other scalar types, - * or float/double in non c++11 mode, the user has to provide implementations of igammac(T,T) for any scalar - * type T to be supported. - * - * \sa Eigen::igammac(), Eigen::lgamma() - */ -template<typename Derived,typename ExponentDerived> -inline const Eigen::CwiseBinaryOp<Eigen::internal::scalar_igamma_op<typename Derived::Scalar>, const Derived, const ExponentDerived> -igamma(const Eigen::ArrayBase<Derived>& a, const Eigen::ArrayBase<ExponentDerived>& x) -{ - return Eigen::CwiseBinaryOp<Eigen::internal::scalar_igamma_op<typename Derived::Scalar>, const Derived, const ExponentDerived>( - a.derived(), - x.derived() - ); -} - -/** \cpp11 \returns an expression of the coefficient-wise igammac(\a a, \a x) to the given arrays. - * - * This function computes the coefficient-wise complementary incomplete gamma function. - * - * \note This function supports only float and double scalar types in c++11 mode. To support other scalar types, - * or float/double in non c++11 mode, the user has to provide implementations of igammac(T,T) for any scalar - * type T to be supported. - * - * \sa Eigen::igamma(), Eigen::lgamma() - */ -template<typename Derived,typename ExponentDerived> -inline const Eigen::CwiseBinaryOp<Eigen::internal::scalar_igammac_op<typename Derived::Scalar>, const Derived, const ExponentDerived> -igammac(const Eigen::ArrayBase<Derived>& a, const Eigen::ArrayBase<ExponentDerived>& x) -{ - return Eigen::CwiseBinaryOp<Eigen::internal::scalar_igammac_op<typename Derived::Scalar>, const Derived, const ExponentDerived>( - a.derived(), - x.derived() - ); -} - -/** \cpp11 \returns an expression of the coefficient-wise polygamma(\a n, \a x) to the given arrays. - * - * It returns the \a n -th derivative of the digamma(psi) evaluated at \c x. - * - * \note This function supports only float and double scalar types in c++11 mode. To support other scalar types, - * or float/double in non c++11 mode, the user has to provide implementations of polygamma(T,T) for any scalar - * type T to be supported. - * - * \sa Eigen::digamma() - */ -// * \warning Be careful with the order of the parameters: x.polygamma(n) is equivalent to polygamma(n,x) -// * \sa ArrayBase::polygamma() -template<typename DerivedN,typename DerivedX> -inline const Eigen::CwiseBinaryOp<Eigen::internal::scalar_polygamma_op<typename DerivedX::Scalar>, const DerivedN, const DerivedX> -polygamma(const Eigen::ArrayBase<DerivedN>& n, const Eigen::ArrayBase<DerivedX>& x) -{ - return Eigen::CwiseBinaryOp<Eigen::internal::scalar_polygamma_op<typename DerivedX::Scalar>, const DerivedN, const DerivedX>( - n.derived(), - x.derived() - ); -} - -/** \cpp11 \returns an expression of the coefficient-wise betainc(\a x, \a a, \a b) to the given arrays. - * - * This function computes the regularized incomplete beta function (integral). - * - * \note This function supports only float and double scalar types in c++11 mode. To support other scalar types, - * or float/double in non c++11 mode, the user has to provide implementations of betainc(T,T,T) for any scalar - * type T to be supported. - * - * \sa Eigen::betainc(), Eigen::lgamma() - */ -template<typename ArgADerived, typename ArgBDerived, typename ArgXDerived> -inline const Eigen::CwiseTernaryOp<Eigen::internal::scalar_betainc_op<typename ArgXDerived::Scalar>, const ArgADerived, const ArgBDerived, const ArgXDerived> -betainc(const Eigen::ArrayBase<ArgADerived>& a, const Eigen::ArrayBase<ArgBDerived>& b, const Eigen::ArrayBase<ArgXDerived>& x) -{ - return Eigen::CwiseTernaryOp<Eigen::internal::scalar_betainc_op<typename ArgXDerived::Scalar>, const ArgADerived, const ArgBDerived, const ArgXDerived>( - a.derived(), - b.derived(), - x.derived() - ); -} - - -/** \returns an expression of the coefficient-wise zeta(\a x, \a q) to the given arrays. - * - * It returns the Riemann zeta function of two arguments \a x and \a q: - * - * \param x is the exposent, it must be > 1 - * \param q is the shift, it must be > 0 - * - * \note This function supports only float and double scalar types. To support other scalar types, the user has - * to provide implementations of zeta(T,T) for any scalar type T to be supported. - * - * \sa ArrayBase::zeta() - */ -template<typename DerivedX,typename DerivedQ> -inline const Eigen::CwiseBinaryOp<Eigen::internal::scalar_zeta_op<typename DerivedX::Scalar>, const DerivedX, const DerivedQ> -zeta(const Eigen::ArrayBase<DerivedX>& x, const Eigen::ArrayBase<DerivedQ>& q) -{ - return Eigen::CwiseBinaryOp<Eigen::internal::scalar_zeta_op<typename DerivedX::Scalar>, const DerivedX, const DerivedQ>( - x.derived(), - q.derived() - ); -} - -} // end namespace Eigen - -#endif // EIGEN_SPECIALFUNCTIONS_ARRAYAPI_H diff --git a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h b/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h deleted file mode 100644 index d8f2363..0000000 --- a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsFunctors.h +++ /dev/null @@ -1,236 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2016 Eugene Brevdo <ebrevdo@gmail.com> -// Copyright (C) 2016 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPECIALFUNCTIONS_FUNCTORS_H -#define EIGEN_SPECIALFUNCTIONS_FUNCTORS_H - -namespace Eigen { - -namespace internal { - - -/** \internal - * \brief Template functor to compute the incomplete gamma function igamma(a, x) - * - * \sa class CwiseBinaryOp, Cwise::igamma - */ -template<typename Scalar> struct scalar_igamma_op : binary_op_base<Scalar,Scalar> -{ - EIGEN_EMPTY_STRUCT_CTOR(scalar_igamma_op) - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& x) const { - using numext::igamma; return igamma(a, x); - } - template<typename Packet> - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& x) const { - return internal::pigamma(a, x); - } -}; -template<typename Scalar> -struct functor_traits<scalar_igamma_op<Scalar> > { - enum { - // Guesstimate - Cost = 20 * NumTraits<Scalar>::MulCost + 10 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasIGamma - }; -}; - - -/** \internal - * \brief Template functor to compute the complementary incomplete gamma function igammac(a, x) - * - * \sa class CwiseBinaryOp, Cwise::igammac - */ -template<typename Scalar> struct scalar_igammac_op : binary_op_base<Scalar,Scalar> -{ - EIGEN_EMPTY_STRUCT_CTOR(scalar_igammac_op) - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a, const Scalar& x) const { - using numext::igammac; return igammac(a, x); - } - template<typename Packet> - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& x) const - { - return internal::pigammac(a, x); - } -}; -template<typename Scalar> -struct functor_traits<scalar_igammac_op<Scalar> > { - enum { - // Guesstimate - Cost = 20 * NumTraits<Scalar>::MulCost + 10 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasIGammac - }; -}; - - -/** \internal - * \brief Template functor to compute the incomplete beta integral betainc(a, b, x) - * - */ -template<typename Scalar> struct scalar_betainc_op { - EIGEN_EMPTY_STRUCT_CTOR(scalar_betainc_op) - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& x, const Scalar& a, const Scalar& b) const { - using numext::betainc; return betainc(x, a, b); - } - template<typename Packet> - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& x, const Packet& a, const Packet& b) const - { - return internal::pbetainc(x, a, b); - } -}; -template<typename Scalar> -struct functor_traits<scalar_betainc_op<Scalar> > { - enum { - // Guesstimate - Cost = 400 * NumTraits<Scalar>::MulCost + 400 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasBetaInc - }; -}; - - -/** \internal - * \brief Template functor to compute the natural log of the absolute - * value of Gamma of a scalar - * \sa class CwiseUnaryOp, Cwise::lgamma() - */ -template<typename Scalar> struct scalar_lgamma_op { - EIGEN_EMPTY_STRUCT_CTOR(scalar_lgamma_op) - EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { - using numext::lgamma; return lgamma(a); - } - typedef typename packet_traits<Scalar>::type Packet; - EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::plgamma(a); } -}; -template<typename Scalar> -struct functor_traits<scalar_lgamma_op<Scalar> > -{ - enum { - // Guesstimate - Cost = 10 * NumTraits<Scalar>::MulCost + 5 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasLGamma - }; -}; - -/** \internal - * \brief Template functor to compute psi, the derivative of lgamma of a scalar. - * \sa class CwiseUnaryOp, Cwise::digamma() - */ -template<typename Scalar> struct scalar_digamma_op { - EIGEN_EMPTY_STRUCT_CTOR(scalar_digamma_op) - EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { - using numext::digamma; return digamma(a); - } - typedef typename packet_traits<Scalar>::type Packet; - EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::pdigamma(a); } -}; -template<typename Scalar> -struct functor_traits<scalar_digamma_op<Scalar> > -{ - enum { - // Guesstimate - Cost = 10 * NumTraits<Scalar>::MulCost + 5 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasDiGamma - }; -}; - -/** \internal - * \brief Template functor to compute the Riemann Zeta function of two arguments. - * \sa class CwiseUnaryOp, Cwise::zeta() - */ -template<typename Scalar> struct scalar_zeta_op { - EIGEN_EMPTY_STRUCT_CTOR(scalar_zeta_op) - EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& x, const Scalar& q) const { - using numext::zeta; return zeta(x, q); - } - typedef typename packet_traits<Scalar>::type Packet; - EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& x, const Packet& q) const { return internal::pzeta(x, q); } -}; -template<typename Scalar> -struct functor_traits<scalar_zeta_op<Scalar> > -{ - enum { - // Guesstimate - Cost = 10 * NumTraits<Scalar>::MulCost + 5 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasZeta - }; -}; - -/** \internal - * \brief Template functor to compute the polygamma function. - * \sa class CwiseUnaryOp, Cwise::polygamma() - */ -template<typename Scalar> struct scalar_polygamma_op { - EIGEN_EMPTY_STRUCT_CTOR(scalar_polygamma_op) - EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& n, const Scalar& x) const { - using numext::polygamma; return polygamma(n, x); - } - typedef typename packet_traits<Scalar>::type Packet; - EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& n, const Packet& x) const { return internal::ppolygamma(n, x); } -}; -template<typename Scalar> -struct functor_traits<scalar_polygamma_op<Scalar> > -{ - enum { - // Guesstimate - Cost = 10 * NumTraits<Scalar>::MulCost + 5 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasPolygamma - }; -}; - -/** \internal - * \brief Template functor to compute the Gauss error function of a - * scalar - * \sa class CwiseUnaryOp, Cwise::erf() - */ -template<typename Scalar> struct scalar_erf_op { - EIGEN_EMPTY_STRUCT_CTOR(scalar_erf_op) - EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { - using numext::erf; return erf(a); - } - typedef typename packet_traits<Scalar>::type Packet; - EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::perf(a); } -}; -template<typename Scalar> -struct functor_traits<scalar_erf_op<Scalar> > -{ - enum { - // Guesstimate - Cost = 10 * NumTraits<Scalar>::MulCost + 5 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasErf - }; -}; - -/** \internal - * \brief Template functor to compute the Complementary Error Function - * of a scalar - * \sa class CwiseUnaryOp, Cwise::erfc() - */ -template<typename Scalar> struct scalar_erfc_op { - EIGEN_EMPTY_STRUCT_CTOR(scalar_erfc_op) - EIGEN_DEVICE_FUNC inline const Scalar operator() (const Scalar& a) const { - using numext::erfc; return erfc(a); - } - typedef typename packet_traits<Scalar>::type Packet; - EIGEN_DEVICE_FUNC inline Packet packetOp(const Packet& a) const { return internal::perfc(a); } -}; -template<typename Scalar> -struct functor_traits<scalar_erfc_op<Scalar> > -{ - enum { - // Guesstimate - Cost = 10 * NumTraits<Scalar>::MulCost + 5 * NumTraits<Scalar>::AddCost, - PacketAccess = packet_traits<Scalar>::HasErfc - }; -}; - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_SPECIALFUNCTIONS_FUNCTORS_H diff --git a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h b/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h deleted file mode 100644 index 553bcda..0000000 --- a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsHalf.h +++ /dev/null @@ -1,47 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPECIALFUNCTIONS_HALF_H -#define EIGEN_SPECIALFUNCTIONS_HALF_H - -namespace Eigen { -namespace numext { - -#if EIGEN_HAS_C99_MATH -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half lgamma(const Eigen::half& a) { - return Eigen::half(Eigen::numext::lgamma(static_cast<float>(a))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half digamma(const Eigen::half& a) { - return Eigen::half(Eigen::numext::digamma(static_cast<float>(a))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half zeta(const Eigen::half& x, const Eigen::half& q) { - return Eigen::half(Eigen::numext::zeta(static_cast<float>(x), static_cast<float>(q))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half polygamma(const Eigen::half& n, const Eigen::half& x) { - return Eigen::half(Eigen::numext::polygamma(static_cast<float>(n), static_cast<float>(x))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half erf(const Eigen::half& a) { - return Eigen::half(Eigen::numext::erf(static_cast<float>(a))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half erfc(const Eigen::half& a) { - return Eigen::half(Eigen::numext::erfc(static_cast<float>(a))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half igamma(const Eigen::half& a, const Eigen::half& x) { - return Eigen::half(Eigen::numext::igamma(static_cast<float>(a), static_cast<float>(x))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half igammac(const Eigen::half& a, const Eigen::half& x) { - return Eigen::half(Eigen::numext::igammac(static_cast<float>(a), static_cast<float>(x))); -} -template<> EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC Eigen::half betainc(const Eigen::half& a, const Eigen::half& b, const Eigen::half& x) { - return Eigen::half(Eigen::numext::betainc(static_cast<float>(a), static_cast<float>(b), static_cast<float>(x))); -} -#endif - -} // end namespace numext -} // end namespace Eigen - -#endif // EIGEN_SPECIALFUNCTIONS_HALF_H diff --git a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h b/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h deleted file mode 100644 index f524d71..0000000 --- a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsImpl.h +++ /dev/null @@ -1,1565 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2015 Eugene Brevdo <ebrevdo@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPECIAL_FUNCTIONS_H -#define EIGEN_SPECIAL_FUNCTIONS_H - -namespace Eigen { -namespace internal { - -// Parts of this code are based on the Cephes Math Library. -// -// Cephes Math Library Release 2.8: June, 2000 -// Copyright 1984, 1987, 1992, 2000 by Stephen L. Moshier -// -// Permission has been kindly provided by the original author -// to incorporate the Cephes software into the Eigen codebase: -// -// From: Stephen Moshier -// To: Eugene Brevdo -// Subject: Re: Permission to wrap several cephes functions in Eigen -// -// Hello Eugene, -// -// Thank you for writing. -// -// If your licensing is similar to BSD, the formal way that has been -// handled is simply to add a statement to the effect that you are incorporating -// the Cephes software by permission of the author. -// -// Good luck with your project, -// Steve - -namespace cephes { - -/* polevl (modified for Eigen) - * - * Evaluate polynomial - * - * - * - * SYNOPSIS: - * - * int N; - * Scalar x, y, coef[N+1]; - * - * y = polevl<decltype(x), N>( x, coef); - * - * - * - * DESCRIPTION: - * - * Evaluates polynomial of degree N: - * - * 2 N - * y = C + C x + C x +...+ C x - * 0 1 2 N - * - * Coefficients are stored in reverse order: - * - * coef[0] = C , ..., coef[N] = C . - * N 0 - * - * The function p1evl() assumes that coef[N] = 1.0 and is - * omitted from the array. Its calling arguments are - * otherwise the same as polevl(). - * - * - * The Eigen implementation is templatized. For best speed, store - * coef as a const array (constexpr), e.g. - * - * const double coef[] = {1.0, 2.0, 3.0, ...}; - * - */ -template <typename Scalar, int N> -struct polevl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(const Scalar x, const Scalar coef[]) { - EIGEN_STATIC_ASSERT((N > 0), YOU_MADE_A_PROGRAMMING_MISTAKE); - - return polevl<Scalar, N - 1>::run(x, coef) * x + coef[N]; - } -}; - -template <typename Scalar> -struct polevl<Scalar, 0> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(const Scalar, const Scalar coef[]) { - return coef[0]; - } -}; - -} // end namespace cephes - -/**************************************************************************** - * Implementation of lgamma, requires C++11/C99 * - ****************************************************************************/ - -template <typename Scalar> -struct lgamma_impl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(const Scalar) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -template <typename Scalar> -struct lgamma_retval { - typedef Scalar type; -}; - -#if EIGEN_HAS_C99_MATH -template <> -struct lgamma_impl<float> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float run(float x) { -#if !defined(__CUDA_ARCH__) && (defined(_BSD_SOURCE) || defined(_SVID_SOURCE)) && !defined(__APPLE__) - int signgam; - return ::lgammaf_r(x, &signgam); -#else - return ::lgammaf(x); -#endif - } -}; - -template <> -struct lgamma_impl<double> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double run(double x) { -#if !defined(__CUDA_ARCH__) && (defined(_BSD_SOURCE) || defined(_SVID_SOURCE)) && !defined(__APPLE__) - int signgam; - return ::lgamma_r(x, &signgam); -#else - return ::lgamma(x); -#endif - } -}; -#endif - -/**************************************************************************** - * Implementation of digamma (psi), based on Cephes * - ****************************************************************************/ - -template <typename Scalar> -struct digamma_retval { - typedef Scalar type; -}; - -/* - * - * Polynomial evaluation helper for the Psi (digamma) function. - * - * digamma_impl_maybe_poly::run(s) evaluates the asymptotic Psi expansion for - * input Scalar s, assuming s is above 10.0. - * - * If s is above a certain threshold for the given Scalar type, zero - * is returned. Otherwise the polynomial is evaluated with enough - * coefficients for results matching Scalar machine precision. - * - * - */ -template <typename Scalar> -struct digamma_impl_maybe_poly { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(const Scalar) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - - -template <> -struct digamma_impl_maybe_poly<float> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float run(const float s) { - const float A[] = { - -4.16666666666666666667E-3f, - 3.96825396825396825397E-3f, - -8.33333333333333333333E-3f, - 8.33333333333333333333E-2f - }; - - float z; - if (s < 1.0e8f) { - z = 1.0f / (s * s); - return z * cephes::polevl<float, 3>::run(z, A); - } else return 0.0f; - } -}; - -template <> -struct digamma_impl_maybe_poly<double> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double run(const double s) { - const double A[] = { - 8.33333333333333333333E-2, - -2.10927960927960927961E-2, - 7.57575757575757575758E-3, - -4.16666666666666666667E-3, - 3.96825396825396825397E-3, - -8.33333333333333333333E-3, - 8.33333333333333333333E-2 - }; - - double z; - if (s < 1.0e17) { - z = 1.0 / (s * s); - return z * cephes::polevl<double, 6>::run(z, A); - } - else return 0.0; - } -}; - -template <typename Scalar> -struct digamma_impl { - EIGEN_DEVICE_FUNC - static Scalar run(Scalar x) { - /* - * - * Psi (digamma) function (modified for Eigen) - * - * - * SYNOPSIS: - * - * double x, y, psi(); - * - * y = psi( x ); - * - * - * DESCRIPTION: - * - * d - - * psi(x) = -- ln | (x) - * dx - * - * is the logarithmic derivative of the gamma function. - * For integer x, - * n-1 - * - - * psi(n) = -EUL + > 1/k. - * - - * k=1 - * - * If x is negative, it is transformed to a positive argument by the - * reflection formula psi(1-x) = psi(x) + pi cot(pi x). - * For general positive x, the argument is made greater than 10 - * using the recurrence psi(x+1) = psi(x) + 1/x. - * Then the following asymptotic expansion is applied: - * - * inf. B - * - 2k - * psi(x) = log(x) - 1/2x - > ------- - * - 2k - * k=1 2k x - * - * where the B2k are Bernoulli numbers. - * - * ACCURACY (float): - * Relative error (except absolute when |psi| < 1): - * arithmetic domain # trials peak rms - * IEEE 0,30 30000 1.3e-15 1.4e-16 - * IEEE -30,0 40000 1.5e-15 2.2e-16 - * - * ACCURACY (double): - * Absolute error, relative when |psi| > 1 : - * arithmetic domain # trials peak rms - * IEEE -33,0 30000 8.2e-7 1.2e-7 - * IEEE 0,33 100000 7.3e-7 7.7e-8 - * - * ERROR MESSAGES: - * message condition value returned - * psi singularity x integer <=0 INFINITY - */ - - Scalar p, q, nz, s, w, y; - bool negative = false; - - const Scalar maxnum = NumTraits<Scalar>::infinity(); - const Scalar m_pi = Scalar(EIGEN_PI); - - const Scalar zero = Scalar(0); - const Scalar one = Scalar(1); - const Scalar half = Scalar(0.5); - nz = zero; - - if (x <= zero) { - negative = true; - q = x; - p = numext::floor(q); - if (p == q) { - return maxnum; - } - /* Remove the zeros of tan(m_pi x) - * by subtracting the nearest integer from x - */ - nz = q - p; - if (nz != half) { - if (nz > half) { - p += one; - nz = q - p; - } - nz = m_pi / numext::tan(m_pi * nz); - } - else { - nz = zero; - } - x = one - x; - } - - /* use the recurrence psi(x+1) = psi(x) + 1/x. */ - s = x; - w = zero; - while (s < Scalar(10)) { - w += one / s; - s += one; - } - - y = digamma_impl_maybe_poly<Scalar>::run(s); - - y = numext::log(s) - (half / s) - y - w; - - return (negative) ? y - nz : y; - } -}; - -/**************************************************************************** - * Implementation of erf, requires C++11/C99 * - ****************************************************************************/ - -template <typename Scalar> -struct erf_impl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(const Scalar) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -template <typename Scalar> -struct erf_retval { - typedef Scalar type; -}; - -#if EIGEN_HAS_C99_MATH -template <> -struct erf_impl<float> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float run(float x) { return ::erff(x); } -}; - -template <> -struct erf_impl<double> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double run(double x) { return ::erf(x); } -}; -#endif // EIGEN_HAS_C99_MATH - -/*************************************************************************** -* Implementation of erfc, requires C++11/C99 * -****************************************************************************/ - -template <typename Scalar> -struct erfc_impl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(const Scalar) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -template <typename Scalar> -struct erfc_retval { - typedef Scalar type; -}; - -#if EIGEN_HAS_C99_MATH -template <> -struct erfc_impl<float> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float run(const float x) { return ::erfcf(x); } -}; - -template <> -struct erfc_impl<double> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double run(const double x) { return ::erfc(x); } -}; -#endif // EIGEN_HAS_C99_MATH - -/************************************************************************************************************** - * Implementation of igammac (complemented incomplete gamma integral), based on Cephes but requires C++11/C99 * - **************************************************************************************************************/ - -template <typename Scalar> -struct igammac_retval { - typedef Scalar type; -}; - -// NOTE: cephes_helper is also used to implement zeta -template <typename Scalar> -struct cephes_helper { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar machep() { assert(false && "machep not supported for this type"); return 0.0; } - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar big() { assert(false && "big not supported for this type"); return 0.0; } - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar biginv() { assert(false && "biginv not supported for this type"); return 0.0; } -}; - -template <> -struct cephes_helper<float> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float machep() { - return NumTraits<float>::epsilon() / 2; // 1.0 - machep == 1.0 - } - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float big() { - // use epsneg (1.0 - epsneg == 1.0) - return 1.0f / (NumTraits<float>::epsilon() / 2); - } - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float biginv() { - // epsneg - return machep(); - } -}; - -template <> -struct cephes_helper<double> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double machep() { - return NumTraits<double>::epsilon() / 2; // 1.0 - machep == 1.0 - } - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double big() { - return 1.0 / NumTraits<double>::epsilon(); - } - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double biginv() { - // inverse of eps - return NumTraits<double>::epsilon(); - } -}; - -#if !EIGEN_HAS_C99_MATH - -template <typename Scalar> -struct igammac_impl { - EIGEN_DEVICE_FUNC - static Scalar run(Scalar a, Scalar x) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -#else - -template <typename Scalar> struct igamma_impl; // predeclare igamma_impl - -template <typename Scalar> -struct igammac_impl { - EIGEN_DEVICE_FUNC - static Scalar run(Scalar a, Scalar x) { - /* igamc() - * - * Incomplete gamma integral (modified for Eigen) - * - * - * - * SYNOPSIS: - * - * double a, x, y, igamc(); - * - * y = igamc( a, x ); - * - * DESCRIPTION: - * - * The function is defined by - * - * - * igamc(a,x) = 1 - igam(a,x) - * - * inf. - * - - * 1 | | -t a-1 - * = ----- | e t dt. - * - | | - * | (a) - - * x - * - * - * In this implementation both arguments must be positive. - * The integral is evaluated by either a power series or - * continued fraction expansion, depending on the relative - * values of a and x. - * - * ACCURACY (float): - * - * Relative error: - * arithmetic domain # trials peak rms - * IEEE 0,30 30000 7.8e-6 5.9e-7 - * - * - * ACCURACY (double): - * - * Tested at random a, x. - * a x Relative error: - * arithmetic domain domain # trials peak rms - * IEEE 0.5,100 0,100 200000 1.9e-14 1.7e-15 - * IEEE 0.01,0.5 0,100 200000 1.4e-13 1.6e-15 - * - */ - /* - Cephes Math Library Release 2.2: June, 1992 - Copyright 1985, 1987, 1992 by Stephen L. Moshier - Direct inquiries to 30 Frost Street, Cambridge, MA 02140 - */ - const Scalar zero = 0; - const Scalar one = 1; - const Scalar nan = NumTraits<Scalar>::quiet_NaN(); - - if ((x < zero) || (a <= zero)) { - // domain error - return nan; - } - - if ((x < one) || (x < a)) { - /* The checks above ensure that we meet the preconditions for - * igamma_impl::Impl(), so call it, rather than igamma_impl::Run(). - * Calling Run() would also work, but in that case the compiler may not be - * able to prove that igammac_impl::Run and igamma_impl::Run are not - * mutually recursive. This leads to worse code, particularly on - * platforms like nvptx, where recursion is allowed only begrudgingly. - */ - return (one - igamma_impl<Scalar>::Impl(a, x)); - } - - return Impl(a, x); - } - - private: - /* igamma_impl calls igammac_impl::Impl. */ - friend struct igamma_impl<Scalar>; - - /* Actually computes igamc(a, x). - * - * Preconditions: - * a > 0 - * x >= 1 - * x >= a - */ - EIGEN_DEVICE_FUNC static Scalar Impl(Scalar a, Scalar x) { - const Scalar zero = 0; - const Scalar one = 1; - const Scalar two = 2; - const Scalar machep = cephes_helper<Scalar>::machep(); - const Scalar maxlog = numext::log(NumTraits<Scalar>::highest()); - const Scalar big = cephes_helper<Scalar>::big(); - const Scalar biginv = cephes_helper<Scalar>::biginv(); - const Scalar inf = NumTraits<Scalar>::infinity(); - - Scalar ans, ax, c, yc, r, t, y, z; - Scalar pk, pkm1, pkm2, qk, qkm1, qkm2; - - if (x == inf) return zero; // std::isinf crashes on CUDA - - /* Compute x**a * exp(-x) / gamma(a) */ - ax = a * numext::log(x) - x - lgamma_impl<Scalar>::run(a); - if (ax < -maxlog) { // underflow - return zero; - } - ax = numext::exp(ax); - - // continued fraction - y = one - a; - z = x + y + one; - c = zero; - pkm2 = one; - qkm2 = x; - pkm1 = x + one; - qkm1 = z * x; - ans = pkm1 / qkm1; - - while (true) { - c += one; - y += one; - z += two; - yc = y * c; - pk = pkm1 * z - pkm2 * yc; - qk = qkm1 * z - qkm2 * yc; - if (qk != zero) { - r = pk / qk; - t = numext::abs((ans - r) / r); - ans = r; - } else { - t = one; - } - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - if (numext::abs(pk) > big) { - pkm2 *= biginv; - pkm1 *= biginv; - qkm2 *= biginv; - qkm1 *= biginv; - } - if (t <= machep) { - break; - } - } - - return (ans * ax); - } -}; - -#endif // EIGEN_HAS_C99_MATH - -/************************************************************************************************ - * Implementation of igamma (incomplete gamma integral), based on Cephes but requires C++11/C99 * - ************************************************************************************************/ - -template <typename Scalar> -struct igamma_retval { - typedef Scalar type; -}; - -#if !EIGEN_HAS_C99_MATH - -template <typename Scalar> -struct igamma_impl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(Scalar a, Scalar x) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -#else - -template <typename Scalar> -struct igamma_impl { - EIGEN_DEVICE_FUNC - static Scalar run(Scalar a, Scalar x) { - /* igam() - * Incomplete gamma integral - * - * - * - * SYNOPSIS: - * - * double a, x, y, igam(); - * - * y = igam( a, x ); - * - * DESCRIPTION: - * - * The function is defined by - * - * x - * - - * 1 | | -t a-1 - * igam(a,x) = ----- | e t dt. - * - | | - * | (a) - - * 0 - * - * - * In this implementation both arguments must be positive. - * The integral is evaluated by either a power series or - * continued fraction expansion, depending on the relative - * values of a and x. - * - * ACCURACY (double): - * - * Relative error: - * arithmetic domain # trials peak rms - * IEEE 0,30 200000 3.6e-14 2.9e-15 - * IEEE 0,100 300000 9.9e-14 1.5e-14 - * - * - * ACCURACY (float): - * - * Relative error: - * arithmetic domain # trials peak rms - * IEEE 0,30 20000 7.8e-6 5.9e-7 - * - */ - /* - Cephes Math Library Release 2.2: June, 1992 - Copyright 1985, 1987, 1992 by Stephen L. Moshier - Direct inquiries to 30 Frost Street, Cambridge, MA 02140 - */ - - - /* left tail of incomplete gamma function: - * - * inf. k - * a -x - x - * x e > ---------- - * - - - * k=0 | (a+k+1) - * - */ - const Scalar zero = 0; - const Scalar one = 1; - const Scalar nan = NumTraits<Scalar>::quiet_NaN(); - - if (x == zero) return zero; - - if ((x < zero) || (a <= zero)) { // domain error - return nan; - } - - if ((x > one) && (x > a)) { - /* The checks above ensure that we meet the preconditions for - * igammac_impl::Impl(), so call it, rather than igammac_impl::Run(). - * Calling Run() would also work, but in that case the compiler may not be - * able to prove that igammac_impl::Run and igamma_impl::Run are not - * mutually recursive. This leads to worse code, particularly on - * platforms like nvptx, where recursion is allowed only begrudgingly. - */ - return (one - igammac_impl<Scalar>::Impl(a, x)); - } - - return Impl(a, x); - } - - private: - /* igammac_impl calls igamma_impl::Impl. */ - friend struct igammac_impl<Scalar>; - - /* Actually computes igam(a, x). - * - * Preconditions: - * x > 0 - * a > 0 - * !(x > 1 && x > a) - */ - EIGEN_DEVICE_FUNC static Scalar Impl(Scalar a, Scalar x) { - const Scalar zero = 0; - const Scalar one = 1; - const Scalar machep = cephes_helper<Scalar>::machep(); - const Scalar maxlog = numext::log(NumTraits<Scalar>::highest()); - - Scalar ans, ax, c, r; - - /* Compute x**a * exp(-x) / gamma(a) */ - ax = a * numext::log(x) - x - lgamma_impl<Scalar>::run(a); - if (ax < -maxlog) { - // underflow - return zero; - } - ax = numext::exp(ax); - - /* power series */ - r = a; - c = one; - ans = one; - - while (true) { - r += one; - c *= x/r; - ans += c; - if (c/ans <= machep) { - break; - } - } - - return (ans * ax / a); - } -}; - -#endif // EIGEN_HAS_C99_MATH - -/***************************************************************************** - * Implementation of Riemann zeta function of two arguments, based on Cephes * - *****************************************************************************/ - -template <typename Scalar> -struct zeta_retval { - typedef Scalar type; -}; - -template <typename Scalar> -struct zeta_impl_series { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(const Scalar) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -template <> -struct zeta_impl_series<float> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE bool run(float& a, float& b, float& s, const float x, const float machep) { - int i = 0; - while(i < 9) - { - i += 1; - a += 1.0f; - b = numext::pow( a, -x ); - s += b; - if( numext::abs(b/s) < machep ) - return true; - } - - //Return whether we are done - return false; - } -}; - -template <> -struct zeta_impl_series<double> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE bool run(double& a, double& b, double& s, const double x, const double machep) { - int i = 0; - while( (i < 9) || (a <= 9.0) ) - { - i += 1; - a += 1.0; - b = numext::pow( a, -x ); - s += b; - if( numext::abs(b/s) < machep ) - return true; - } - - //Return whether we are done - return false; - } -}; - -template <typename Scalar> -struct zeta_impl { - EIGEN_DEVICE_FUNC - static Scalar run(Scalar x, Scalar q) { - /* zeta.c - * - * Riemann zeta function of two arguments - * - * - * - * SYNOPSIS: - * - * double x, q, y, zeta(); - * - * y = zeta( x, q ); - * - * - * - * DESCRIPTION: - * - * - * - * inf. - * - -x - * zeta(x,q) = > (k+q) - * - - * k=0 - * - * where x > 1 and q is not a negative integer or zero. - * The Euler-Maclaurin summation formula is used to obtain - * the expansion - * - * n - * - -x - * zeta(x,q) = > (k+q) - * - - * k=1 - * - * 1-x inf. B x(x+1)...(x+2j) - * (n+q) 1 - 2j - * + --------- - ------- + > -------------------- - * x-1 x - x+2j+1 - * 2(n+q) j=1 (2j)! (n+q) - * - * where the B2j are Bernoulli numbers. Note that (see zetac.c) - * zeta(x,1) = zetac(x) + 1. - * - * - * - * ACCURACY: - * - * Relative error for single precision: - * arithmetic domain # trials peak rms - * IEEE 0,25 10000 6.9e-7 1.0e-7 - * - * Large arguments may produce underflow in powf(), in which - * case the results are inaccurate. - * - * REFERENCE: - * - * Gradshteyn, I. S., and I. M. Ryzhik, Tables of Integrals, - * Series, and Products, p. 1073; Academic Press, 1980. - * - */ - - int i; - Scalar p, r, a, b, k, s, t, w; - - const Scalar A[] = { - Scalar(12.0), - Scalar(-720.0), - Scalar(30240.0), - Scalar(-1209600.0), - Scalar(47900160.0), - Scalar(-1.8924375803183791606e9), /*1.307674368e12/691*/ - Scalar(7.47242496e10), - Scalar(-2.950130727918164224e12), /*1.067062284288e16/3617*/ - Scalar(1.1646782814350067249e14), /*5.109094217170944e18/43867*/ - Scalar(-4.5979787224074726105e15), /*8.028576626982912e20/174611*/ - Scalar(1.8152105401943546773e17), /*1.5511210043330985984e23/854513*/ - Scalar(-7.1661652561756670113e18) /*1.6938241367317436694528e27/236364091*/ - }; - - const Scalar maxnum = NumTraits<Scalar>::infinity(); - const Scalar zero = 0.0, half = 0.5, one = 1.0; - const Scalar machep = cephes_helper<Scalar>::machep(); - const Scalar nan = NumTraits<Scalar>::quiet_NaN(); - - if( x == one ) - return maxnum; - - if( x < one ) - { - return nan; - } - - if( q <= zero ) - { - if(q == numext::floor(q)) - { - return maxnum; - } - p = x; - r = numext::floor(p); - if (p != r) - return nan; - } - - /* Permit negative q but continue sum until n+q > +9 . - * This case should be handled by a reflection formula. - * If q<0 and x is an integer, there is a relation to - * the polygamma function. - */ - s = numext::pow( q, -x ); - a = q; - b = zero; - // Run the summation in a helper function that is specific to the floating precision - if (zeta_impl_series<Scalar>::run(a, b, s, x, machep)) { - return s; - } - - w = a; - s += b*w/(x-one); - s -= half * b; - a = one; - k = zero; - for( i=0; i<12; i++ ) - { - a *= x + k; - b /= w; - t = a*b/A[i]; - s = s + t; - t = numext::abs(t/s); - if( t < machep ) { - break; - } - k += one; - a *= x + k; - b /= w; - k += one; - } - return s; - } -}; - -/**************************************************************************** - * Implementation of polygamma function, requires C++11/C99 * - ****************************************************************************/ - -template <typename Scalar> -struct polygamma_retval { - typedef Scalar type; -}; - -#if !EIGEN_HAS_C99_MATH - -template <typename Scalar> -struct polygamma_impl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(Scalar n, Scalar x) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -#else - -template <typename Scalar> -struct polygamma_impl { - EIGEN_DEVICE_FUNC - static Scalar run(Scalar n, Scalar x) { - Scalar zero = 0.0, one = 1.0; - Scalar nplus = n + one; - const Scalar nan = NumTraits<Scalar>::quiet_NaN(); - - // Check that n is an integer - if (numext::floor(n) != n) { - return nan; - } - // Just return the digamma function for n = 1 - else if (n == zero) { - return digamma_impl<Scalar>::run(x); - } - // Use the same implementation as scipy - else { - Scalar factorial = numext::exp(lgamma_impl<Scalar>::run(nplus)); - return numext::pow(-one, nplus) * factorial * zeta_impl<Scalar>::run(nplus, x); - } - } -}; - -#endif // EIGEN_HAS_C99_MATH - -/************************************************************************************************ - * Implementation of betainc (incomplete beta integral), based on Cephes but requires C++11/C99 * - ************************************************************************************************/ - -template <typename Scalar> -struct betainc_retval { - typedef Scalar type; -}; - -#if !EIGEN_HAS_C99_MATH - -template <typename Scalar> -struct betainc_impl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(Scalar a, Scalar b, Scalar x) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -#else - -template <typename Scalar> -struct betainc_impl { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(Scalar, Scalar, Scalar) { - /* betaincf.c - * - * Incomplete beta integral - * - * - * SYNOPSIS: - * - * float a, b, x, y, betaincf(); - * - * y = betaincf( a, b, x ); - * - * - * DESCRIPTION: - * - * Returns incomplete beta integral of the arguments, evaluated - * from zero to x. The function is defined as - * - * x - * - - - * | (a+b) | | a-1 b-1 - * ----------- | t (1-t) dt. - * - - | | - * | (a) | (b) - - * 0 - * - * The domain of definition is 0 <= x <= 1. In this - * implementation a and b are restricted to positive values. - * The integral from x to 1 may be obtained by the symmetry - * relation - * - * 1 - betainc( a, b, x ) = betainc( b, a, 1-x ). - * - * The integral is evaluated by a continued fraction expansion. - * If a < 1, the function calls itself recursively after a - * transformation to increase a to a+1. - * - * ACCURACY (float): - * - * Tested at random points (a,b,x) with a and b in the indicated - * interval and x between 0 and 1. - * - * arithmetic domain # trials peak rms - * Relative error: - * IEEE 0,30 10000 3.7e-5 5.1e-6 - * IEEE 0,100 10000 1.7e-4 2.5e-5 - * The useful domain for relative error is limited by underflow - * of the single precision exponential function. - * Absolute error: - * IEEE 0,30 100000 2.2e-5 9.6e-7 - * IEEE 0,100 10000 6.5e-5 3.7e-6 - * - * Larger errors may occur for extreme ratios of a and b. - * - * ACCURACY (double): - * arithmetic domain # trials peak rms - * IEEE 0,5 10000 6.9e-15 4.5e-16 - * IEEE 0,85 250000 2.2e-13 1.7e-14 - * IEEE 0,1000 30000 5.3e-12 6.3e-13 - * IEEE 0,10000 250000 9.3e-11 7.1e-12 - * IEEE 0,100000 10000 8.7e-10 4.8e-11 - * Outputs smaller than the IEEE gradual underflow threshold - * were excluded from these statistics. - * - * ERROR MESSAGES: - * message condition value returned - * incbet domain x<0, x>1 nan - * incbet underflow nan - */ - - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, Scalar>::value == false), - THIS_TYPE_IS_NOT_SUPPORTED); - return Scalar(0); - } -}; - -/* Continued fraction expansion #1 for incomplete beta integral (small_branch = True) - * Continued fraction expansion #2 for incomplete beta integral (small_branch = False) - */ -template <typename Scalar> -struct incbeta_cfe { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE Scalar run(Scalar a, Scalar b, Scalar x, bool small_branch) { - EIGEN_STATIC_ASSERT((internal::is_same<Scalar, float>::value || - internal::is_same<Scalar, double>::value), - THIS_TYPE_IS_NOT_SUPPORTED); - const Scalar big = cephes_helper<Scalar>::big(); - const Scalar machep = cephes_helper<Scalar>::machep(); - const Scalar biginv = cephes_helper<Scalar>::biginv(); - - const Scalar zero = 0; - const Scalar one = 1; - const Scalar two = 2; - - Scalar xk, pk, pkm1, pkm2, qk, qkm1, qkm2; - Scalar k1, k2, k3, k4, k5, k6, k7, k8, k26update; - Scalar ans; - int n; - - const int num_iters = (internal::is_same<Scalar, float>::value) ? 100 : 300; - const Scalar thresh = - (internal::is_same<Scalar, float>::value) ? machep : Scalar(3) * machep; - Scalar r = (internal::is_same<Scalar, float>::value) ? zero : one; - - if (small_branch) { - k1 = a; - k2 = a + b; - k3 = a; - k4 = a + one; - k5 = one; - k6 = b - one; - k7 = k4; - k8 = a + two; - k26update = one; - } else { - k1 = a; - k2 = b - one; - k3 = a; - k4 = a + one; - k5 = one; - k6 = a + b; - k7 = a + one; - k8 = a + two; - k26update = -one; - x = x / (one - x); - } - - pkm2 = zero; - qkm2 = one; - pkm1 = one; - qkm1 = one; - ans = one; - n = 0; - - do { - xk = -(x * k1 * k2) / (k3 * k4); - pk = pkm1 + pkm2 * xk; - qk = qkm1 + qkm2 * xk; - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - - xk = (x * k5 * k6) / (k7 * k8); - pk = pkm1 + pkm2 * xk; - qk = qkm1 + qkm2 * xk; - pkm2 = pkm1; - pkm1 = pk; - qkm2 = qkm1; - qkm1 = qk; - - if (qk != zero) { - r = pk / qk; - if (numext::abs(ans - r) < numext::abs(r) * thresh) { - return r; - } - ans = r; - } - - k1 += one; - k2 += k26update; - k3 += two; - k4 += two; - k5 += one; - k6 -= k26update; - k7 += two; - k8 += two; - - if ((numext::abs(qk) + numext::abs(pk)) > big) { - pkm2 *= biginv; - pkm1 *= biginv; - qkm2 *= biginv; - qkm1 *= biginv; - } - if ((numext::abs(qk) < biginv) || (numext::abs(pk) < biginv)) { - pkm2 *= big; - pkm1 *= big; - qkm2 *= big; - qkm1 *= big; - } - } while (++n < num_iters); - - return ans; - } -}; - -/* Helper functions depending on the Scalar type */ -template <typename Scalar> -struct betainc_helper {}; - -template <> -struct betainc_helper<float> { - /* Core implementation, assumes a large (> 1.0) */ - EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE float incbsa(float aa, float bb, - float xx) { - float ans, a, b, t, x, onemx; - bool reversed_a_b = false; - - onemx = 1.0f - xx; - - /* see if x is greater than the mean */ - if (xx > (aa / (aa + bb))) { - reversed_a_b = true; - a = bb; - b = aa; - t = xx; - x = onemx; - } else { - a = aa; - b = bb; - t = onemx; - x = xx; - } - - /* Choose expansion for optimal convergence */ - if (b > 10.0f) { - if (numext::abs(b * x / a) < 0.3f) { - t = betainc_helper<float>::incbps(a, b, x); - if (reversed_a_b) t = 1.0f - t; - return t; - } - } - - ans = x * (a + b - 2.0f) / (a - 1.0f); - if (ans < 1.0f) { - ans = incbeta_cfe<float>::run(a, b, x, true /* small_branch */); - t = b * numext::log(t); - } else { - ans = incbeta_cfe<float>::run(a, b, x, false /* small_branch */); - t = (b - 1.0f) * numext::log(t); - } - - t += a * numext::log(x) + lgamma_impl<float>::run(a + b) - - lgamma_impl<float>::run(a) - lgamma_impl<float>::run(b); - t += numext::log(ans / a); - t = numext::exp(t); - - if (reversed_a_b) t = 1.0f - t; - return t; - } - - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE float incbps(float a, float b, float x) { - float t, u, y, s; - const float machep = cephes_helper<float>::machep(); - - y = a * numext::log(x) + (b - 1.0f) * numext::log1p(-x) - numext::log(a); - y -= lgamma_impl<float>::run(a) + lgamma_impl<float>::run(b); - y += lgamma_impl<float>::run(a + b); - - t = x / (1.0f - x); - s = 0.0f; - u = 1.0f; - do { - b -= 1.0f; - if (b == 0.0f) { - break; - } - a += 1.0f; - u *= t * b / a; - s += u; - } while (numext::abs(u) > machep); - - return numext::exp(y) * (1.0f + s); - } -}; - -template <> -struct betainc_impl<float> { - EIGEN_DEVICE_FUNC - static float run(float a, float b, float x) { - const float nan = NumTraits<float>::quiet_NaN(); - float ans, t; - - if (a <= 0.0f) return nan; - if (b <= 0.0f) return nan; - if ((x <= 0.0f) || (x >= 1.0f)) { - if (x == 0.0f) return 0.0f; - if (x == 1.0f) return 1.0f; - // mtherr("betaincf", DOMAIN); - return nan; - } - - /* transformation for small aa */ - if (a <= 1.0f) { - ans = betainc_helper<float>::incbsa(a + 1.0f, b, x); - t = a * numext::log(x) + b * numext::log1p(-x) + - lgamma_impl<float>::run(a + b) - lgamma_impl<float>::run(a + 1.0f) - - lgamma_impl<float>::run(b); - return (ans + numext::exp(t)); - } else { - return betainc_helper<float>::incbsa(a, b, x); - } - } -}; - -template <> -struct betainc_helper<double> { - EIGEN_DEVICE_FUNC - static EIGEN_STRONG_INLINE double incbps(double a, double b, double x) { - const double machep = cephes_helper<double>::machep(); - - double s, t, u, v, n, t1, z, ai; - - ai = 1.0 / a; - u = (1.0 - b) * x; - v = u / (a + 1.0); - t1 = v; - t = u; - n = 2.0; - s = 0.0; - z = machep * ai; - while (numext::abs(v) > z) { - u = (n - b) * x / n; - t *= u; - v = t / (a + n); - s += v; - n += 1.0; - } - s += t1; - s += ai; - - u = a * numext::log(x); - // TODO: gamma() is not directly implemented in Eigen. - /* - if ((a + b) < maxgam && numext::abs(u) < maxlog) { - t = gamma(a + b) / (gamma(a) * gamma(b)); - s = s * t * pow(x, a); - } else { - */ - t = lgamma_impl<double>::run(a + b) - lgamma_impl<double>::run(a) - - lgamma_impl<double>::run(b) + u + numext::log(s); - return s = numext::exp(t); - } -}; - -template <> -struct betainc_impl<double> { - EIGEN_DEVICE_FUNC - static double run(double aa, double bb, double xx) { - const double nan = NumTraits<double>::quiet_NaN(); - const double machep = cephes_helper<double>::machep(); - // const double maxgam = 171.624376956302725; - - double a, b, t, x, xc, w, y; - bool reversed_a_b = false; - - if (aa <= 0.0 || bb <= 0.0) { - return nan; // goto domerr; - } - - if ((xx <= 0.0) || (xx >= 1.0)) { - if (xx == 0.0) return (0.0); - if (xx == 1.0) return (1.0); - // mtherr("incbet", DOMAIN); - return nan; - } - - if ((bb * xx) <= 1.0 && xx <= 0.95) { - return betainc_helper<double>::incbps(aa, bb, xx); - } - - w = 1.0 - xx; - - /* Reverse a and b if x is greater than the mean. */ - if (xx > (aa / (aa + bb))) { - reversed_a_b = true; - a = bb; - b = aa; - xc = xx; - x = w; - } else { - a = aa; - b = bb; - xc = w; - x = xx; - } - - if (reversed_a_b && (b * x) <= 1.0 && x <= 0.95) { - t = betainc_helper<double>::incbps(a, b, x); - if (t <= machep) { - t = 1.0 - machep; - } else { - t = 1.0 - t; - } - return t; - } - - /* Choose expansion for better convergence. */ - y = x * (a + b - 2.0) - (a - 1.0); - if (y < 0.0) { - w = incbeta_cfe<double>::run(a, b, x, true /* small_branch */); - } else { - w = incbeta_cfe<double>::run(a, b, x, false /* small_branch */) / xc; - } - - /* Multiply w by the factor - a b _ _ _ - x (1-x) | (a+b) / ( a | (a) | (b) ) . */ - - y = a * numext::log(x); - t = b * numext::log(xc); - // TODO: gamma is not directly implemented in Eigen. - /* - if ((a + b) < maxgam && numext::abs(y) < maxlog && numext::abs(t) < maxlog) - { - t = pow(xc, b); - t *= pow(x, a); - t /= a; - t *= w; - t *= gamma(a + b) / (gamma(a) * gamma(b)); - } else { - */ - /* Resort to logarithms. */ - y += t + lgamma_impl<double>::run(a + b) - lgamma_impl<double>::run(a) - - lgamma_impl<double>::run(b); - y += numext::log(w / a); - t = numext::exp(y); - - /* } */ - // done: - - if (reversed_a_b) { - if (t <= machep) { - t = 1.0 - machep; - } else { - t = 1.0 - t; - } - } - return t; - } -}; - -#endif // EIGEN_HAS_C99_MATH - -} // end namespace internal - -namespace numext { - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(lgamma, Scalar) - lgamma(const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(lgamma, Scalar)::run(x); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(digamma, Scalar) - digamma(const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(digamma, Scalar)::run(x); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(zeta, Scalar) -zeta(const Scalar& x, const Scalar& q) { - return EIGEN_MATHFUNC_IMPL(zeta, Scalar)::run(x, q); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(polygamma, Scalar) -polygamma(const Scalar& n, const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(polygamma, Scalar)::run(n, x); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(erf, Scalar) - erf(const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(erf, Scalar)::run(x); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(erfc, Scalar) - erfc(const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(erfc, Scalar)::run(x); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(igamma, Scalar) - igamma(const Scalar& a, const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(igamma, Scalar)::run(a, x); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(igammac, Scalar) - igammac(const Scalar& a, const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(igammac, Scalar)::run(a, x); -} - -template <typename Scalar> -EIGEN_DEVICE_FUNC inline EIGEN_MATHFUNC_RETVAL(betainc, Scalar) - betainc(const Scalar& a, const Scalar& b, const Scalar& x) { - return EIGEN_MATHFUNC_IMPL(betainc, Scalar)::run(a, b, x); -} - -} // end namespace numext - - -} // end namespace Eigen - -#endif // EIGEN_SPECIAL_FUNCTIONS_H diff --git a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h b/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h deleted file mode 100644 index 46d60d3..0000000 --- a/eigen/unsupported/Eigen/src/SpecialFunctions/SpecialFunctionsPacketMath.h +++ /dev/null @@ -1,58 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2016 Gael Guennebaud <gael.guennebaud@inria.fr> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPECIALFUNCTIONS_PACKETMATH_H -#define EIGEN_SPECIALFUNCTIONS_PACKETMATH_H - -namespace Eigen { - -namespace internal { - -/** \internal \returns the ln(|gamma(\a a)|) (coeff-wise) */ -template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet plgamma(const Packet& a) { using numext::lgamma; return lgamma(a); } - -/** \internal \returns the derivative of lgamma, psi(\a a) (coeff-wise) */ -template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet pdigamma(const Packet& a) { using numext::digamma; return digamma(a); } - -/** \internal \returns the zeta function of two arguments (coeff-wise) */ -template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet pzeta(const Packet& x, const Packet& q) { using numext::zeta; return zeta(x, q); } - -/** \internal \returns the polygamma function (coeff-wise) */ -template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet ppolygamma(const Packet& n, const Packet& x) { using numext::polygamma; return polygamma(n, x); } - -/** \internal \returns the erf(\a a) (coeff-wise) */ -template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet perf(const Packet& a) { using numext::erf; return erf(a); } - -/** \internal \returns the erfc(\a a) (coeff-wise) */ -template<typename Packet> EIGEN_DECLARE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS -Packet perfc(const Packet& a) { using numext::erfc; return erfc(a); } - -/** \internal \returns the incomplete gamma function igamma(\a a, \a x) */ -template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -Packet pigamma(const Packet& a, const Packet& x) { using numext::igamma; return igamma(a, x); } - -/** \internal \returns the complementary incomplete gamma function igammac(\a a, \a x) */ -template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -Packet pigammac(const Packet& a, const Packet& x) { using numext::igammac; return igammac(a, x); } - -/** \internal \returns the complementary incomplete gamma function betainc(\a a, \a b, \a x) */ -template<typename Packet> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -Packet pbetainc(const Packet& a, const Packet& b,const Packet& x) { using numext::betainc; return betainc(a, b, x); } - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_SPECIALFUNCTIONS_PACKETMATH_H - diff --git a/eigen/unsupported/Eigen/src/SpecialFunctions/arch/CUDA/CudaSpecialFunctions.h b/eigen/unsupported/Eigen/src/SpecialFunctions/arch/CUDA/CudaSpecialFunctions.h deleted file mode 100644 index ec4fa84..0000000 --- a/eigen/unsupported/Eigen/src/SpecialFunctions/arch/CUDA/CudaSpecialFunctions.h +++ /dev/null @@ -1,165 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_CUDA_SPECIALFUNCTIONS_H -#define EIGEN_CUDA_SPECIALFUNCTIONS_H - -namespace Eigen { - -namespace internal { - -// Make sure this is only available when targeting a GPU: we don't want to -// introduce conflicts between these packet_traits definitions and the ones -// we'll use on the host side (SSE, AVX, ...) -#if defined(__CUDACC__) && defined(EIGEN_USE_GPU) - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 plgamma<float4>(const float4& a) -{ - return make_float4(lgammaf(a.x), lgammaf(a.y), lgammaf(a.z), lgammaf(a.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 plgamma<double2>(const double2& a) -{ - using numext::lgamma; - return make_double2(lgamma(a.x), lgamma(a.y)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 pdigamma<float4>(const float4& a) -{ - using numext::digamma; - return make_float4(digamma(a.x), digamma(a.y), digamma(a.z), digamma(a.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 pdigamma<double2>(const double2& a) -{ - using numext::digamma; - return make_double2(digamma(a.x), digamma(a.y)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 pzeta<float4>(const float4& x, const float4& q) -{ - using numext::zeta; - return make_float4(zeta(x.x, q.x), zeta(x.y, q.y), zeta(x.z, q.z), zeta(x.w, q.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 pzeta<double2>(const double2& x, const double2& q) -{ - using numext::zeta; - return make_double2(zeta(x.x, q.x), zeta(x.y, q.y)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 ppolygamma<float4>(const float4& n, const float4& x) -{ - using numext::polygamma; - return make_float4(polygamma(n.x, x.x), polygamma(n.y, x.y), polygamma(n.z, x.z), polygamma(n.w, x.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 ppolygamma<double2>(const double2& n, const double2& x) -{ - using numext::polygamma; - return make_double2(polygamma(n.x, x.x), polygamma(n.y, x.y)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 perf<float4>(const float4& a) -{ - return make_float4(erff(a.x), erff(a.y), erff(a.z), erff(a.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 perf<double2>(const double2& a) -{ - using numext::erf; - return make_double2(erf(a.x), erf(a.y)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 perfc<float4>(const float4& a) -{ - using numext::erfc; - return make_float4(erfc(a.x), erfc(a.y), erfc(a.z), erfc(a.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 perfc<double2>(const double2& a) -{ - using numext::erfc; - return make_double2(erfc(a.x), erfc(a.y)); -} - - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 pigamma<float4>(const float4& a, const float4& x) -{ - using numext::igamma; - return make_float4( - igamma(a.x, x.x), - igamma(a.y, x.y), - igamma(a.z, x.z), - igamma(a.w, x.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 pigamma<double2>(const double2& a, const double2& x) -{ - using numext::igamma; - return make_double2(igamma(a.x, x.x), igamma(a.y, x.y)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 pigammac<float4>(const float4& a, const float4& x) -{ - using numext::igammac; - return make_float4( - igammac(a.x, x.x), - igammac(a.y, x.y), - igammac(a.z, x.z), - igammac(a.w, x.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 pigammac<double2>(const double2& a, const double2& x) -{ - using numext::igammac; - return make_double2(igammac(a.x, x.x), igammac(a.y, x.y)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -float4 pbetainc<float4>(const float4& a, const float4& b, const float4& x) -{ - using numext::betainc; - return make_float4( - betainc(a.x, b.x, x.x), - betainc(a.y, b.y, x.y), - betainc(a.z, b.z, x.z), - betainc(a.w, b.w, x.w)); -} - -template<> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -double2 pbetainc<double2>(const double2& a, const double2& b, const double2& x) -{ - using numext::betainc; - return make_double2(betainc(a.x, b.x, x.x), betainc(a.y, b.y, x.y)); -} - -#endif - -} // end namespace internal - -} // end namespace Eigen - -#endif // EIGEN_CUDA_SPECIALFUNCTIONS_H diff --git a/eigen/unsupported/Eigen/src/Splines/Spline.h b/eigen/unsupported/Eigen/src/Splines/Spline.h deleted file mode 100644 index 57788c8..0000000 --- a/eigen/unsupported/Eigen/src/Splines/Spline.h +++ /dev/null @@ -1,507 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 20010-2011 Hauke Heibel <hauke.heibel@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPLINE_H -#define EIGEN_SPLINE_H - -#include "SplineFwd.h" - -namespace Eigen -{ - /** - * \ingroup Splines_Module - * \class Spline - * \brief A class representing multi-dimensional spline curves. - * - * The class represents B-splines with non-uniform knot vectors. Each control - * point of the B-spline is associated with a basis function - * \f{align*} - * C(u) & = \sum_{i=0}^{n}N_{i,p}(u)P_i - * \f} - * - * \tparam _Scalar The underlying data type (typically float or double) - * \tparam _Dim The curve dimension (e.g. 2 or 3) - * \tparam _Degree Per default set to Dynamic; could be set to the actual desired - * degree for optimization purposes (would result in stack allocation - * of several temporary variables). - **/ - template <typename _Scalar, int _Dim, int _Degree> - class Spline - { - public: - typedef _Scalar Scalar; /*!< The spline curve's scalar type. */ - enum { Dimension = _Dim /*!< The spline curve's dimension. */ }; - enum { Degree = _Degree /*!< The spline curve's degree. */ }; - - /** \brief The point type the spline is representing. */ - typedef typename SplineTraits<Spline>::PointType PointType; - - /** \brief The data type used to store knot vectors. */ - typedef typename SplineTraits<Spline>::KnotVectorType KnotVectorType; - - /** \brief The data type used to store parameter vectors. */ - typedef typename SplineTraits<Spline>::ParameterVectorType ParameterVectorType; - - /** \brief The data type used to store non-zero basis functions. */ - typedef typename SplineTraits<Spline>::BasisVectorType BasisVectorType; - - /** \brief The data type used to store the values of the basis function derivatives. */ - typedef typename SplineTraits<Spline>::BasisDerivativeType BasisDerivativeType; - - /** \brief The data type representing the spline's control points. */ - typedef typename SplineTraits<Spline>::ControlPointVectorType ControlPointVectorType; - - /** - * \brief Creates a (constant) zero spline. - * For Splines with dynamic degree, the resulting degree will be 0. - **/ - Spline() - : m_knots(1, (Degree==Dynamic ? 2 : 2*Degree+2)) - , m_ctrls(ControlPointVectorType::Zero(Dimension,(Degree==Dynamic ? 1 : Degree+1))) - { - // in theory this code can go to the initializer list but it will get pretty - // much unreadable ... - enum { MinDegree = (Degree==Dynamic ? 0 : Degree) }; - m_knots.template segment<MinDegree+1>(0) = Array<Scalar,1,MinDegree+1>::Zero(); - m_knots.template segment<MinDegree+1>(MinDegree+1) = Array<Scalar,1,MinDegree+1>::Ones(); - } - - /** - * \brief Creates a spline from a knot vector and control points. - * \param knots The spline's knot vector. - * \param ctrls The spline's control point vector. - **/ - template <typename OtherVectorType, typename OtherArrayType> - Spline(const OtherVectorType& knots, const OtherArrayType& ctrls) : m_knots(knots), m_ctrls(ctrls) {} - - /** - * \brief Copy constructor for splines. - * \param spline The input spline. - **/ - template <int OtherDegree> - Spline(const Spline<Scalar, Dimension, OtherDegree>& spline) : - m_knots(spline.knots()), m_ctrls(spline.ctrls()) {} - - /** - * \brief Returns the knots of the underlying spline. - **/ - const KnotVectorType& knots() const { return m_knots; } - - /** - * \brief Returns the ctrls of the underlying spline. - **/ - const ControlPointVectorType& ctrls() const { return m_ctrls; } - - /** - * \brief Returns the spline value at a given site \f$u\f$. - * - * The function returns - * \f{align*} - * C(u) & = \sum_{i=0}^{n}N_{i,p}P_i - * \f} - * - * \param u Parameter \f$u \in [0;1]\f$ at which the spline is evaluated. - * \return The spline value at the given location \f$u\f$. - **/ - PointType operator()(Scalar u) const; - - /** - * \brief Evaluation of spline derivatives of up-to given order. - * - * The function returns - * \f{align*} - * \frac{d^i}{du^i}C(u) & = \sum_{i=0}^{n} \frac{d^i}{du^i} N_{i,p}(u)P_i - * \f} - * for i ranging between 0 and order. - * - * \param u Parameter \f$u \in [0;1]\f$ at which the spline derivative is evaluated. - * \param order The order up to which the derivatives are computed. - **/ - typename SplineTraits<Spline>::DerivativeType - derivatives(Scalar u, DenseIndex order) const; - - /** - * \copydoc Spline::derivatives - * Using the template version of this function is more efficieent since - * temporary objects are allocated on the stack whenever this is possible. - **/ - template <int DerivativeOrder> - typename SplineTraits<Spline,DerivativeOrder>::DerivativeType - derivatives(Scalar u, DenseIndex order = DerivativeOrder) const; - - /** - * \brief Computes the non-zero basis functions at the given site. - * - * Splines have local support and a point from their image is defined - * by exactly \f$p+1\f$ control points \f$P_i\f$ where \f$p\f$ is the - * spline degree. - * - * This function computes the \f$p+1\f$ non-zero basis function values - * for a given parameter value \f$u\f$. It returns - * \f{align*}{ - * N_{i,p}(u), \hdots, N_{i+p+1,p}(u) - * \f} - * - * \param u Parameter \f$u \in [0;1]\f$ at which the non-zero basis functions - * are computed. - **/ - typename SplineTraits<Spline>::BasisVectorType - basisFunctions(Scalar u) const; - - /** - * \brief Computes the non-zero spline basis function derivatives up to given order. - * - * The function computes - * \f{align*}{ - * \frac{d^i}{du^i} N_{i,p}(u), \hdots, \frac{d^i}{du^i} N_{i+p+1,p}(u) - * \f} - * with i ranging from 0 up to the specified order. - * - * \param u Parameter \f$u \in [0;1]\f$ at which the non-zero basis function - * derivatives are computed. - * \param order The order up to which the basis function derivatives are computes. - **/ - typename SplineTraits<Spline>::BasisDerivativeType - basisFunctionDerivatives(Scalar u, DenseIndex order) const; - - /** - * \copydoc Spline::basisFunctionDerivatives - * Using the template version of this function is more efficieent since - * temporary objects are allocated on the stack whenever this is possible. - **/ - template <int DerivativeOrder> - typename SplineTraits<Spline,DerivativeOrder>::BasisDerivativeType - basisFunctionDerivatives(Scalar u, DenseIndex order = DerivativeOrder) const; - - /** - * \brief Returns the spline degree. - **/ - DenseIndex degree() const; - - /** - * \brief Returns the span within the knot vector in which u is falling. - * \param u The site for which the span is determined. - **/ - DenseIndex span(Scalar u) const; - - /** - * \brief Computes the spang within the provided knot vector in which u is falling. - **/ - static DenseIndex Span(typename SplineTraits<Spline>::Scalar u, DenseIndex degree, const typename SplineTraits<Spline>::KnotVectorType& knots); - - /** - * \brief Returns the spline's non-zero basis functions. - * - * The function computes and returns - * \f{align*}{ - * N_{i,p}(u), \hdots, N_{i+p+1,p}(u) - * \f} - * - * \param u The site at which the basis functions are computed. - * \param degree The degree of the underlying spline. - * \param knots The underlying spline's knot vector. - **/ - static BasisVectorType BasisFunctions(Scalar u, DenseIndex degree, const KnotVectorType& knots); - - /** - * \copydoc Spline::basisFunctionDerivatives - * \param degree The degree of the underlying spline - * \param knots The underlying spline's knot vector. - **/ - static BasisDerivativeType BasisFunctionDerivatives( - const Scalar u, const DenseIndex order, const DenseIndex degree, const KnotVectorType& knots); - - private: - KnotVectorType m_knots; /*!< Knot vector. */ - ControlPointVectorType m_ctrls; /*!< Control points. */ - - template <typename DerivativeType> - static void BasisFunctionDerivativesImpl( - const typename Spline<_Scalar, _Dim, _Degree>::Scalar u, - const DenseIndex order, - const DenseIndex p, - const typename Spline<_Scalar, _Dim, _Degree>::KnotVectorType& U, - DerivativeType& N_); - }; - - template <typename _Scalar, int _Dim, int _Degree> - DenseIndex Spline<_Scalar, _Dim, _Degree>::Span( - typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::Scalar u, - DenseIndex degree, - const typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::KnotVectorType& knots) - { - // Piegl & Tiller, "The NURBS Book", A2.1 (p. 68) - if (u <= knots(0)) return degree; - const Scalar* pos = std::upper_bound(knots.data()+degree-1, knots.data()+knots.size()-degree-1, u); - return static_cast<DenseIndex>( std::distance(knots.data(), pos) - 1 ); - } - - template <typename _Scalar, int _Dim, int _Degree> - typename Spline<_Scalar, _Dim, _Degree>::BasisVectorType - Spline<_Scalar, _Dim, _Degree>::BasisFunctions( - typename Spline<_Scalar, _Dim, _Degree>::Scalar u, - DenseIndex degree, - const typename Spline<_Scalar, _Dim, _Degree>::KnotVectorType& knots) - { - const DenseIndex p = degree; - const DenseIndex i = Spline::Span(u, degree, knots); - - const KnotVectorType& U = knots; - - BasisVectorType left(p+1); left(0) = Scalar(0); - BasisVectorType right(p+1); right(0) = Scalar(0); - - VectorBlock<BasisVectorType,Degree>(left,1,p) = u - VectorBlock<const KnotVectorType,Degree>(U,i+1-p,p).reverse(); - VectorBlock<BasisVectorType,Degree>(right,1,p) = VectorBlock<const KnotVectorType,Degree>(U,i+1,p) - u; - - BasisVectorType N(1,p+1); - N(0) = Scalar(1); - for (DenseIndex j=1; j<=p; ++j) - { - Scalar saved = Scalar(0); - for (DenseIndex r=0; r<j; r++) - { - const Scalar tmp = N(r)/(right(r+1)+left(j-r)); - N[r] = saved + right(r+1)*tmp; - saved = left(j-r)*tmp; - } - N(j) = saved; - } - return N; - } - - template <typename _Scalar, int _Dim, int _Degree> - DenseIndex Spline<_Scalar, _Dim, _Degree>::degree() const - { - if (_Degree == Dynamic) - return m_knots.size() - m_ctrls.cols() - 1; - else - return _Degree; - } - - template <typename _Scalar, int _Dim, int _Degree> - DenseIndex Spline<_Scalar, _Dim, _Degree>::span(Scalar u) const - { - return Spline::Span(u, degree(), knots()); - } - - template <typename _Scalar, int _Dim, int _Degree> - typename Spline<_Scalar, _Dim, _Degree>::PointType Spline<_Scalar, _Dim, _Degree>::operator()(Scalar u) const - { - enum { Order = SplineTraits<Spline>::OrderAtCompileTime }; - - const DenseIndex span = this->span(u); - const DenseIndex p = degree(); - const BasisVectorType basis_funcs = basisFunctions(u); - - const Replicate<BasisVectorType,Dimension,1> ctrl_weights(basis_funcs); - const Block<const ControlPointVectorType,Dimension,Order> ctrl_pts(ctrls(),0,span-p,Dimension,p+1); - return (ctrl_weights * ctrl_pts).rowwise().sum(); - } - - /* --------------------------------------------------------------------------------------------- */ - - template <typename SplineType, typename DerivativeType> - void derivativesImpl(const SplineType& spline, typename SplineType::Scalar u, DenseIndex order, DerivativeType& der) - { - enum { Dimension = SplineTraits<SplineType>::Dimension }; - enum { Order = SplineTraits<SplineType>::OrderAtCompileTime }; - enum { DerivativeOrder = DerivativeType::ColsAtCompileTime }; - - typedef typename SplineTraits<SplineType>::ControlPointVectorType ControlPointVectorType; - typedef typename SplineTraits<SplineType,DerivativeOrder>::BasisDerivativeType BasisDerivativeType; - typedef typename BasisDerivativeType::ConstRowXpr BasisDerivativeRowXpr; - - const DenseIndex p = spline.degree(); - const DenseIndex span = spline.span(u); - - const DenseIndex n = (std::min)(p, order); - - der.resize(Dimension,n+1); - - // Retrieve the basis function derivatives up to the desired order... - const BasisDerivativeType basis_func_ders = spline.template basisFunctionDerivatives<DerivativeOrder>(u, n+1); - - // ... and perform the linear combinations of the control points. - for (DenseIndex der_order=0; der_order<n+1; ++der_order) - { - const Replicate<BasisDerivativeRowXpr,Dimension,1> ctrl_weights( basis_func_ders.row(der_order) ); - const Block<const ControlPointVectorType,Dimension,Order> ctrl_pts(spline.ctrls(),0,span-p,Dimension,p+1); - der.col(der_order) = (ctrl_weights * ctrl_pts).rowwise().sum(); - } - } - - template <typename _Scalar, int _Dim, int _Degree> - typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::DerivativeType - Spline<_Scalar, _Dim, _Degree>::derivatives(Scalar u, DenseIndex order) const - { - typename SplineTraits< Spline >::DerivativeType res; - derivativesImpl(*this, u, order, res); - return res; - } - - template <typename _Scalar, int _Dim, int _Degree> - template <int DerivativeOrder> - typename SplineTraits< Spline<_Scalar, _Dim, _Degree>, DerivativeOrder >::DerivativeType - Spline<_Scalar, _Dim, _Degree>::derivatives(Scalar u, DenseIndex order) const - { - typename SplineTraits< Spline, DerivativeOrder >::DerivativeType res; - derivativesImpl(*this, u, order, res); - return res; - } - - template <typename _Scalar, int _Dim, int _Degree> - typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::BasisVectorType - Spline<_Scalar, _Dim, _Degree>::basisFunctions(Scalar u) const - { - return Spline::BasisFunctions(u, degree(), knots()); - } - - /* --------------------------------------------------------------------------------------------- */ - - - template <typename _Scalar, int _Dim, int _Degree> - template <typename DerivativeType> - void Spline<_Scalar, _Dim, _Degree>::BasisFunctionDerivativesImpl( - const typename Spline<_Scalar, _Dim, _Degree>::Scalar u, - const DenseIndex order, - const DenseIndex p, - const typename Spline<_Scalar, _Dim, _Degree>::KnotVectorType& U, - DerivativeType& N_) - { - typedef Spline<_Scalar, _Dim, _Degree> SplineType; - enum { Order = SplineTraits<SplineType>::OrderAtCompileTime }; - - const DenseIndex span = SplineType::Span(u, p, U); - - const DenseIndex n = (std::min)(p, order); - - N_.resize(n+1, p+1); - - BasisVectorType left = BasisVectorType::Zero(p+1); - BasisVectorType right = BasisVectorType::Zero(p+1); - - Matrix<Scalar,Order,Order> ndu(p+1,p+1); - - Scalar saved, temp; // FIXME These were double instead of Scalar. Was there a reason for that? - - ndu(0,0) = 1.0; - - DenseIndex j; - for (j=1; j<=p; ++j) - { - left[j] = u-U[span+1-j]; - right[j] = U[span+j]-u; - saved = 0.0; - - for (DenseIndex r=0; r<j; ++r) - { - /* Lower triangle */ - ndu(j,r) = right[r+1]+left[j-r]; - temp = ndu(r,j-1)/ndu(j,r); - /* Upper triangle */ - ndu(r,j) = static_cast<Scalar>(saved+right[r+1] * temp); - saved = left[j-r] * temp; - } - - ndu(j,j) = static_cast<Scalar>(saved); - } - - for (j = p; j>=0; --j) - N_(0,j) = ndu(j,p); - - // Compute the derivatives - DerivativeType a(n+1,p+1); - DenseIndex r=0; - for (; r<=p; ++r) - { - DenseIndex s1,s2; - s1 = 0; s2 = 1; // alternate rows in array a - a(0,0) = 1.0; - - // Compute the k-th derivative - for (DenseIndex k=1; k<=static_cast<DenseIndex>(n); ++k) - { - Scalar d = 0.0; - DenseIndex rk,pk,j1,j2; - rk = r-k; pk = p-k; - - if (r>=k) - { - a(s2,0) = a(s1,0)/ndu(pk+1,rk); - d = a(s2,0)*ndu(rk,pk); - } - - if (rk>=-1) j1 = 1; - else j1 = -rk; - - if (r-1 <= pk) j2 = k-1; - else j2 = p-r; - - for (j=j1; j<=j2; ++j) - { - a(s2,j) = (a(s1,j)-a(s1,j-1))/ndu(pk+1,rk+j); - d += a(s2,j)*ndu(rk+j,pk); - } - - if (r<=pk) - { - a(s2,k) = -a(s1,k-1)/ndu(pk+1,r); - d += a(s2,k)*ndu(r,pk); - } - - N_(k,r) = static_cast<Scalar>(d); - j = s1; s1 = s2; s2 = j; // Switch rows - } - } - - /* Multiply through by the correct factors */ - /* (Eq. [2.9]) */ - r = p; - for (DenseIndex k=1; k<=static_cast<DenseIndex>(n); ++k) - { - for (j=p; j>=0; --j) N_(k,j) *= r; - r *= p-k; - } - } - - template <typename _Scalar, int _Dim, int _Degree> - typename SplineTraits< Spline<_Scalar, _Dim, _Degree> >::BasisDerivativeType - Spline<_Scalar, _Dim, _Degree>::basisFunctionDerivatives(Scalar u, DenseIndex order) const - { - typename SplineTraits<Spline<_Scalar, _Dim, _Degree> >::BasisDerivativeType der; - BasisFunctionDerivativesImpl(u, order, degree(), knots(), der); - return der; - } - - template <typename _Scalar, int _Dim, int _Degree> - template <int DerivativeOrder> - typename SplineTraits< Spline<_Scalar, _Dim, _Degree>, DerivativeOrder >::BasisDerivativeType - Spline<_Scalar, _Dim, _Degree>::basisFunctionDerivatives(Scalar u, DenseIndex order) const - { - typename SplineTraits< Spline<_Scalar, _Dim, _Degree>, DerivativeOrder >::BasisDerivativeType der; - BasisFunctionDerivativesImpl(u, order, degree(), knots(), der); - return der; - } - - template <typename _Scalar, int _Dim, int _Degree> - typename SplineTraits<Spline<_Scalar, _Dim, _Degree> >::BasisDerivativeType - Spline<_Scalar, _Dim, _Degree>::BasisFunctionDerivatives( - const typename Spline<_Scalar, _Dim, _Degree>::Scalar u, - const DenseIndex order, - const DenseIndex degree, - const typename Spline<_Scalar, _Dim, _Degree>::KnotVectorType& knots) - { - typename SplineTraits<Spline>::BasisDerivativeType der; - BasisFunctionDerivativesImpl(u, order, degree, knots, der); - return der; - } -} - -#endif // EIGEN_SPLINE_H diff --git a/eigen/unsupported/Eigen/src/Splines/SplineFitting.h b/eigen/unsupported/Eigen/src/Splines/SplineFitting.h deleted file mode 100644 index c761a9b..0000000 --- a/eigen/unsupported/Eigen/src/Splines/SplineFitting.h +++ /dev/null @@ -1,430 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 20010-2011 Hauke Heibel <hauke.heibel@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPLINE_FITTING_H -#define EIGEN_SPLINE_FITTING_H - -#include <algorithm> -#include <functional> -#include <numeric> -#include <vector> - -#include "SplineFwd.h" - -#include <Eigen/LU> -#include <Eigen/QR> - -namespace Eigen -{ - /** - * \brief Computes knot averages. - * \ingroup Splines_Module - * - * The knots are computed as - * \f{align*} - * u_0 & = \hdots = u_p = 0 \\ - * u_{m-p} & = \hdots = u_{m} = 1 \\ - * u_{j+p} & = \frac{1}{p}\sum_{i=j}^{j+p-1}\bar{u}_i \quad\quad j=1,\hdots,n-p - * \f} - * where \f$p\f$ is the degree and \f$m+1\f$ the number knots - * of the desired interpolating spline. - * - * \param[in] parameters The input parameters. During interpolation one for each data point. - * \param[in] degree The spline degree which is used during the interpolation. - * \param[out] knots The output knot vector. - * - * \sa Les Piegl and Wayne Tiller, The NURBS book (2nd ed.), 1997, 9.2.1 Global Curve Interpolation to Point Data - **/ - template <typename KnotVectorType> - void KnotAveraging(const KnotVectorType& parameters, DenseIndex degree, KnotVectorType& knots) - { - knots.resize(parameters.size()+degree+1); - - for (DenseIndex j=1; j<parameters.size()-degree; ++j) - knots(j+degree) = parameters.segment(j,degree).mean(); - - knots.segment(0,degree+1) = KnotVectorType::Zero(degree+1); - knots.segment(knots.size()-degree-1,degree+1) = KnotVectorType::Ones(degree+1); - } - - /** - * \brief Computes knot averages when derivative constraints are present. - * Note that this is a technical interpretation of the referenced article - * since the algorithm contained therein is incorrect as written. - * \ingroup Splines_Module - * - * \param[in] parameters The parameters at which the interpolation B-Spline - * will intersect the given interpolation points. The parameters - * are assumed to be a non-decreasing sequence. - * \param[in] degree The degree of the interpolating B-Spline. This must be - * greater than zero. - * \param[in] derivativeIndices The indices corresponding to parameters at - * which there are derivative constraints. The indices are assumed - * to be a non-decreasing sequence. - * \param[out] knots The calculated knot vector. These will be returned as a - * non-decreasing sequence - * - * \sa Les A. Piegl, Khairan Rajab, Volha Smarodzinana. 2008. - * Curve interpolation with directional constraints for engineering design. - * Engineering with Computers - **/ - template <typename KnotVectorType, typename ParameterVectorType, typename IndexArray> - void KnotAveragingWithDerivatives(const ParameterVectorType& parameters, - const unsigned int degree, - const IndexArray& derivativeIndices, - KnotVectorType& knots) - { - typedef typename ParameterVectorType::Scalar Scalar; - - DenseIndex numParameters = parameters.size(); - DenseIndex numDerivatives = derivativeIndices.size(); - - if (numDerivatives < 1) - { - KnotAveraging(parameters, degree, knots); - return; - } - - DenseIndex startIndex; - DenseIndex endIndex; - - DenseIndex numInternalDerivatives = numDerivatives; - - if (derivativeIndices[0] == 0) - { - startIndex = 0; - --numInternalDerivatives; - } - else - { - startIndex = 1; - } - if (derivativeIndices[numDerivatives - 1] == numParameters - 1) - { - endIndex = numParameters - degree; - --numInternalDerivatives; - } - else - { - endIndex = numParameters - degree - 1; - } - - // There are (endIndex - startIndex + 1) knots obtained from the averaging - // and 2 for the first and last parameters. - DenseIndex numAverageKnots = endIndex - startIndex + 3; - KnotVectorType averageKnots(numAverageKnots); - averageKnots[0] = parameters[0]; - - int newKnotIndex = 0; - for (DenseIndex i = startIndex; i <= endIndex; ++i) - averageKnots[++newKnotIndex] = parameters.segment(i, degree).mean(); - averageKnots[++newKnotIndex] = parameters[numParameters - 1]; - - newKnotIndex = -1; - - ParameterVectorType temporaryParameters(numParameters + 1); - KnotVectorType derivativeKnots(numInternalDerivatives); - for (DenseIndex i = 0; i < numAverageKnots - 1; ++i) - { - temporaryParameters[0] = averageKnots[i]; - ParameterVectorType parameterIndices(numParameters); - int temporaryParameterIndex = 1; - for (DenseIndex j = 0; j < numParameters; ++j) - { - Scalar parameter = parameters[j]; - if (parameter >= averageKnots[i] && parameter < averageKnots[i + 1]) - { - parameterIndices[temporaryParameterIndex] = j; - temporaryParameters[temporaryParameterIndex++] = parameter; - } - } - temporaryParameters[temporaryParameterIndex] = averageKnots[i + 1]; - - for (int j = 0; j <= temporaryParameterIndex - 2; ++j) - { - for (DenseIndex k = 0; k < derivativeIndices.size(); ++k) - { - if (parameterIndices[j + 1] == derivativeIndices[k] - && parameterIndices[j + 1] != 0 - && parameterIndices[j + 1] != numParameters - 1) - { - derivativeKnots[++newKnotIndex] = temporaryParameters.segment(j, 3).mean(); - break; - } - } - } - } - - KnotVectorType temporaryKnots(averageKnots.size() + derivativeKnots.size()); - - std::merge(averageKnots.data(), averageKnots.data() + averageKnots.size(), - derivativeKnots.data(), derivativeKnots.data() + derivativeKnots.size(), - temporaryKnots.data()); - - // Number of knots (one for each point and derivative) plus spline order. - DenseIndex numKnots = numParameters + numDerivatives + degree + 1; - knots.resize(numKnots); - - knots.head(degree).fill(temporaryKnots[0]); - knots.tail(degree).fill(temporaryKnots.template tail<1>()[0]); - knots.segment(degree, temporaryKnots.size()) = temporaryKnots; - } - - /** - * \brief Computes chord length parameters which are required for spline interpolation. - * \ingroup Splines_Module - * - * \param[in] pts The data points to which a spline should be fit. - * \param[out] chord_lengths The resulting chord lenggth vector. - * - * \sa Les Piegl and Wayne Tiller, The NURBS book (2nd ed.), 1997, 9.2.1 Global Curve Interpolation to Point Data - **/ - template <typename PointArrayType, typename KnotVectorType> - void ChordLengths(const PointArrayType& pts, KnotVectorType& chord_lengths) - { - typedef typename KnotVectorType::Scalar Scalar; - - const DenseIndex n = pts.cols(); - - // 1. compute the column-wise norms - chord_lengths.resize(pts.cols()); - chord_lengths[0] = 0; - chord_lengths.rightCols(n-1) = (pts.array().leftCols(n-1) - pts.array().rightCols(n-1)).matrix().colwise().norm(); - - // 2. compute the partial sums - std::partial_sum(chord_lengths.data(), chord_lengths.data()+n, chord_lengths.data()); - - // 3. normalize the data - chord_lengths /= chord_lengths(n-1); - chord_lengths(n-1) = Scalar(1); - } - - /** - * \brief Spline fitting methods. - * \ingroup Splines_Module - **/ - template <typename SplineType> - struct SplineFitting - { - typedef typename SplineType::KnotVectorType KnotVectorType; - typedef typename SplineType::ParameterVectorType ParameterVectorType; - - /** - * \brief Fits an interpolating Spline to the given data points. - * - * \param pts The points for which an interpolating spline will be computed. - * \param degree The degree of the interpolating spline. - * - * \returns A spline interpolating the initially provided points. - **/ - template <typename PointArrayType> - static SplineType Interpolate(const PointArrayType& pts, DenseIndex degree); - - /** - * \brief Fits an interpolating Spline to the given data points. - * - * \param pts The points for which an interpolating spline will be computed. - * \param degree The degree of the interpolating spline. - * \param knot_parameters The knot parameters for the interpolation. - * - * \returns A spline interpolating the initially provided points. - **/ - template <typename PointArrayType> - static SplineType Interpolate(const PointArrayType& pts, DenseIndex degree, const KnotVectorType& knot_parameters); - - /** - * \brief Fits an interpolating spline to the given data points and - * derivatives. - * - * \param points The points for which an interpolating spline will be computed. - * \param derivatives The desired derivatives of the interpolating spline at interpolation - * points. - * \param derivativeIndices An array indicating which point each derivative belongs to. This - * must be the same size as @a derivatives. - * \param degree The degree of the interpolating spline. - * - * \returns A spline interpolating @a points with @a derivatives at those points. - * - * \sa Les A. Piegl, Khairan Rajab, Volha Smarodzinana. 2008. - * Curve interpolation with directional constraints for engineering design. - * Engineering with Computers - **/ - template <typename PointArrayType, typename IndexArray> - static SplineType InterpolateWithDerivatives(const PointArrayType& points, - const PointArrayType& derivatives, - const IndexArray& derivativeIndices, - const unsigned int degree); - - /** - * \brief Fits an interpolating spline to the given data points and derivatives. - * - * \param points The points for which an interpolating spline will be computed. - * \param derivatives The desired derivatives of the interpolating spline at interpolation points. - * \param derivativeIndices An array indicating which point each derivative belongs to. This - * must be the same size as @a derivatives. - * \param degree The degree of the interpolating spline. - * \param parameters The parameters corresponding to the interpolation points. - * - * \returns A spline interpolating @a points with @a derivatives at those points. - * - * \sa Les A. Piegl, Khairan Rajab, Volha Smarodzinana. 2008. - * Curve interpolation with directional constraints for engineering design. - * Engineering with Computers - */ - template <typename PointArrayType, typename IndexArray> - static SplineType InterpolateWithDerivatives(const PointArrayType& points, - const PointArrayType& derivatives, - const IndexArray& derivativeIndices, - const unsigned int degree, - const ParameterVectorType& parameters); - }; - - template <typename SplineType> - template <typename PointArrayType> - SplineType SplineFitting<SplineType>::Interpolate(const PointArrayType& pts, DenseIndex degree, const KnotVectorType& knot_parameters) - { - typedef typename SplineType::KnotVectorType::Scalar Scalar; - typedef typename SplineType::ControlPointVectorType ControlPointVectorType; - - typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType; - - KnotVectorType knots; - KnotAveraging(knot_parameters, degree, knots); - - DenseIndex n = pts.cols(); - MatrixType A = MatrixType::Zero(n,n); - for (DenseIndex i=1; i<n-1; ++i) - { - const DenseIndex span = SplineType::Span(knot_parameters[i], degree, knots); - - // The segment call should somehow be told the spline order at compile time. - A.row(i).segment(span-degree, degree+1) = SplineType::BasisFunctions(knot_parameters[i], degree, knots); - } - A(0,0) = 1.0; - A(n-1,n-1) = 1.0; - - HouseholderQR<MatrixType> qr(A); - - // Here, we are creating a temporary due to an Eigen issue. - ControlPointVectorType ctrls = qr.solve(MatrixType(pts.transpose())).transpose(); - - return SplineType(knots, ctrls); - } - - template <typename SplineType> - template <typename PointArrayType> - SplineType SplineFitting<SplineType>::Interpolate(const PointArrayType& pts, DenseIndex degree) - { - KnotVectorType chord_lengths; // knot parameters - ChordLengths(pts, chord_lengths); - return Interpolate(pts, degree, chord_lengths); - } - - template <typename SplineType> - template <typename PointArrayType, typename IndexArray> - SplineType - SplineFitting<SplineType>::InterpolateWithDerivatives(const PointArrayType& points, - const PointArrayType& derivatives, - const IndexArray& derivativeIndices, - const unsigned int degree, - const ParameterVectorType& parameters) - { - typedef typename SplineType::KnotVectorType::Scalar Scalar; - typedef typename SplineType::ControlPointVectorType ControlPointVectorType; - - typedef Matrix<Scalar, Dynamic, Dynamic> MatrixType; - - const DenseIndex n = points.cols() + derivatives.cols(); - - KnotVectorType knots; - - KnotAveragingWithDerivatives(parameters, degree, derivativeIndices, knots); - - // fill matrix - MatrixType A = MatrixType::Zero(n, n); - - // Use these dimensions for quicker populating, then transpose for solving. - MatrixType b(points.rows(), n); - - DenseIndex startRow; - DenseIndex derivativeStart; - - // End derivatives. - if (derivativeIndices[0] == 0) - { - A.template block<1, 2>(1, 0) << -1, 1; - - Scalar y = (knots(degree + 1) - knots(0)) / degree; - b.col(1) = y*derivatives.col(0); - - startRow = 2; - derivativeStart = 1; - } - else - { - startRow = 1; - derivativeStart = 0; - } - if (derivativeIndices[derivatives.cols() - 1] == points.cols() - 1) - { - A.template block<1, 2>(n - 2, n - 2) << -1, 1; - - Scalar y = (knots(knots.size() - 1) - knots(knots.size() - (degree + 2))) / degree; - b.col(b.cols() - 2) = y*derivatives.col(derivatives.cols() - 1); - } - - DenseIndex row = startRow; - DenseIndex derivativeIndex = derivativeStart; - for (DenseIndex i = 1; i < parameters.size() - 1; ++i) - { - const DenseIndex span = SplineType::Span(parameters[i], degree, knots); - - if (derivativeIndices[derivativeIndex] == i) - { - A.block(row, span - degree, 2, degree + 1) - = SplineType::BasisFunctionDerivatives(parameters[i], 1, degree, knots); - - b.col(row++) = points.col(i); - b.col(row++) = derivatives.col(derivativeIndex++); - } - else - { - A.row(row++).segment(span - degree, degree + 1) - = SplineType::BasisFunctions(parameters[i], degree, knots); - } - } - b.col(0) = points.col(0); - b.col(b.cols() - 1) = points.col(points.cols() - 1); - A(0,0) = 1; - A(n - 1, n - 1) = 1; - - // Solve - FullPivLU<MatrixType> lu(A); - ControlPointVectorType controlPoints = lu.solve(MatrixType(b.transpose())).transpose(); - - SplineType spline(knots, controlPoints); - - return spline; - } - - template <typename SplineType> - template <typename PointArrayType, typename IndexArray> - SplineType - SplineFitting<SplineType>::InterpolateWithDerivatives(const PointArrayType& points, - const PointArrayType& derivatives, - const IndexArray& derivativeIndices, - const unsigned int degree) - { - ParameterVectorType parameters; - ChordLengths(points, parameters); - return InterpolateWithDerivatives(points, derivatives, derivativeIndices, degree, parameters); - } -} - -#endif // EIGEN_SPLINE_FITTING_H diff --git a/eigen/unsupported/Eigen/src/Splines/SplineFwd.h b/eigen/unsupported/Eigen/src/Splines/SplineFwd.h deleted file mode 100644 index 0a95fbf..0000000 --- a/eigen/unsupported/Eigen/src/Splines/SplineFwd.h +++ /dev/null @@ -1,93 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 20010-2011 Hauke Heibel <hauke.heibel@gmail.com> -// -// This Source Code Form is subject to the terms of the Mozilla -// Public License v. 2.0. If a copy of the MPL was not distributed -// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef EIGEN_SPLINES_FWD_H -#define EIGEN_SPLINES_FWD_H - -#include <Eigen/Core> - -namespace Eigen -{ - template <typename Scalar, int Dim, int Degree = Dynamic> class Spline; - - template < typename SplineType, int DerivativeOrder = Dynamic > struct SplineTraits {}; - - /** - * \ingroup Splines_Module - * \brief Compile-time attributes of the Spline class for Dynamic degree. - **/ - template <typename _Scalar, int _Dim, int _Degree> - struct SplineTraits< Spline<_Scalar, _Dim, _Degree>, Dynamic > - { - typedef _Scalar Scalar; /*!< The spline curve's scalar type. */ - enum { Dimension = _Dim /*!< The spline curve's dimension. */ }; - enum { Degree = _Degree /*!< The spline curve's degree. */ }; - - enum { OrderAtCompileTime = _Degree==Dynamic ? Dynamic : _Degree+1 /*!< The spline curve's order at compile-time. */ }; - enum { NumOfDerivativesAtCompileTime = OrderAtCompileTime /*!< The number of derivatives defined for the current spline. */ }; - - enum { DerivativeMemoryLayout = Dimension==1 ? RowMajor : ColMajor /*!< The derivative type's memory layout. */ }; - - /** \brief The data type used to store non-zero basis functions. */ - typedef Array<Scalar,1,OrderAtCompileTime> BasisVectorType; - - /** \brief The data type used to store the values of the basis function derivatives. */ - typedef Array<Scalar,Dynamic,Dynamic,RowMajor,NumOfDerivativesAtCompileTime,OrderAtCompileTime> BasisDerivativeType; - - /** \brief The data type used to store the spline's derivative values. */ - typedef Array<Scalar,Dimension,Dynamic,DerivativeMemoryLayout,Dimension,NumOfDerivativesAtCompileTime> DerivativeType; - - /** \brief The point type the spline is representing. */ - typedef Array<Scalar,Dimension,1> PointType; - - /** \brief The data type used to store knot vectors. */ - typedef Array<Scalar,1,Dynamic> KnotVectorType; - - /** \brief The data type used to store parameter vectors. */ - typedef Array<Scalar,1,Dynamic> ParameterVectorType; - - /** \brief The data type representing the spline's control points. */ - typedef Array<Scalar,Dimension,Dynamic> ControlPointVectorType; - }; - - /** - * \ingroup Splines_Module - * \brief Compile-time attributes of the Spline class for fixed degree. - * - * The traits class inherits all attributes from the SplineTraits of Dynamic degree. - **/ - template < typename _Scalar, int _Dim, int _Degree, int _DerivativeOrder > - struct SplineTraits< Spline<_Scalar, _Dim, _Degree>, _DerivativeOrder > : public SplineTraits< Spline<_Scalar, _Dim, _Degree> > - { - enum { OrderAtCompileTime = _Degree==Dynamic ? Dynamic : _Degree+1 /*!< The spline curve's order at compile-time. */ }; - enum { NumOfDerivativesAtCompileTime = _DerivativeOrder==Dynamic ? Dynamic : _DerivativeOrder+1 /*!< The number of derivatives defined for the current spline. */ }; - - enum { DerivativeMemoryLayout = _Dim==1 ? RowMajor : ColMajor /*!< The derivative type's memory layout. */ }; - - /** \brief The data type used to store the values of the basis function derivatives. */ - typedef Array<_Scalar,Dynamic,Dynamic,RowMajor,NumOfDerivativesAtCompileTime,OrderAtCompileTime> BasisDerivativeType; - - /** \brief The data type used to store the spline's derivative values. */ - typedef Array<_Scalar,_Dim,Dynamic,DerivativeMemoryLayout,_Dim,NumOfDerivativesAtCompileTime> DerivativeType; - }; - - /** \brief 2D float B-spline with dynamic degree. */ - typedef Spline<float,2> Spline2f; - - /** \brief 3D float B-spline with dynamic degree. */ - typedef Spline<float,3> Spline3f; - - /** \brief 2D double B-spline with dynamic degree. */ - typedef Spline<double,2> Spline2d; - - /** \brief 3D double B-spline with dynamic degree. */ - typedef Spline<double,3> Spline3d; -} - -#endif // EIGEN_SPLINES_FWD_H |