// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2015 Gael Guennebaud // // 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_SOLVERBASE_H #define EIGEN_SOLVERBASE_H namespace Eigen { namespace internal { template struct solve_assertion { template static void run(const Derived& solver, const Rhs& b) { solver.template _check_solve_assertion(b); } }; template struct solve_assertion > { typedef Transpose type; template static void run(const type& transpose, const Rhs& b) { internal::solve_assertion::type>::template run(transpose.nestedExpression(), b); } }; template struct solve_assertion, const Transpose > > { typedef CwiseUnaryOp, const Transpose > type; template static void run(const type& adjoint, const Rhs& b) { internal::solve_assertion >::type>::template run(adjoint.nestedExpression(), b); } }; } // end namespace internal /** \class SolverBase * \brief A base class for matrix decomposition and solvers * * \tparam Derived the actual type of the decomposition/solver. * * Any matrix decomposition inheriting this base class provide the following API: * * \code * MatrixType A, b, x; * DecompositionType dec(A); * x = dec.solve(b); // solve A * x = b * x = dec.transpose().solve(b); // solve A^T * x = b * x = dec.adjoint().solve(b); // solve A' * x = b * \endcode * * \warning Currently, any other usage of transpose() and adjoint() are not supported and will produce compilation errors. * * \sa class PartialPivLU, class FullPivLU, class HouseholderQR, class ColPivHouseholderQR, class FullPivHouseholderQR, class CompleteOrthogonalDecomposition, class LLT, class LDLT, class SVDBase */ template class SolverBase : public EigenBase { public: typedef EigenBase Base; typedef typename internal::traits::Scalar Scalar; typedef Scalar CoeffReturnType; template friend struct internal::solve_assertion; enum { RowsAtCompileTime = internal::traits::RowsAtCompileTime, ColsAtCompileTime = internal::traits::ColsAtCompileTime, SizeAtCompileTime = (internal::size_at_compile_time::RowsAtCompileTime, internal::traits::ColsAtCompileTime>::ret), MaxRowsAtCompileTime = internal::traits::MaxRowsAtCompileTime, MaxColsAtCompileTime = internal::traits::MaxColsAtCompileTime, MaxSizeAtCompileTime = (internal::size_at_compile_time::MaxRowsAtCompileTime, internal::traits::MaxColsAtCompileTime>::ret), IsVectorAtCompileTime = internal::traits::MaxRowsAtCompileTime == 1 || internal::traits::MaxColsAtCompileTime == 1, NumDimensions = int(MaxSizeAtCompileTime) == 1 ? 0 : bool(IsVectorAtCompileTime) ? 1 : 2 }; /** Default constructor */ SolverBase() {} ~SolverBase() {} using Base::derived; /** \returns an expression of the solution x of \f$ A x = b \f$ using the current decomposition of A. */ template inline const Solve solve(const MatrixBase& b) const { internal::solve_assertion::type>::template run(derived(), b); return Solve(derived(), b.derived()); } /** \internal the return type of transpose() */ typedef typename internal::add_const >::type ConstTransposeReturnType; /** \returns an expression of the transposed of the factored matrix. * * A typical usage is to solve for the transposed problem A^T x = b: * \code x = dec.transpose().solve(b); \endcode * * \sa adjoint(), solve() */ inline ConstTransposeReturnType transpose() const { return ConstTransposeReturnType(derived()); } /** \internal the return type of adjoint() */ typedef typename internal::conditional::IsComplex, CwiseUnaryOp, ConstTransposeReturnType>, ConstTransposeReturnType >::type AdjointReturnType; /** \returns an expression of the adjoint of the factored matrix * * A typical usage is to solve for the adjoint problem A' x = b: * \code x = dec.adjoint().solve(b); \endcode * * For real scalar types, this function is equivalent to transpose(). * * \sa transpose(), solve() */ inline AdjointReturnType adjoint() const { return AdjointReturnType(derived().transpose()); } protected: template void _check_solve_assertion(const Rhs& b) const { EIGEN_ONLY_USED_FOR_DEBUG(b); eigen_assert(derived().m_isInitialized && "Solver is not initialized."); eigen_assert((Transpose_?derived().cols():derived().rows())==b.rows() && "SolverBase::solve(): invalid number of rows of the right hand side matrix b"); } }; namespace internal { template struct generic_xpr_base { typedef SolverBase type; }; } // end namespace internal } // end namespace Eigen #endif // EIGEN_SOLVERBASE_H