// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2015 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_SOLVERBASE_H
#define EIGEN_SOLVERBASE_H

namespace Eigen {

namespace internal {

template<typename Derived>
struct solve_assertion {
    template<bool Transpose_, typename Rhs>
    static void run(const Derived& solver, const Rhs& b) { solver.template _check_solve_assertion<Transpose_>(b); }
};

template<typename Derived>
struct solve_assertion<Transpose<Derived> >
{
    typedef Transpose<Derived> type;

    template<bool Transpose_, typename Rhs>
    static void run(const type& transpose, const Rhs& b)
    {
        internal::solve_assertion<typename internal::remove_all<Derived>::type>::template run<true>(transpose.nestedExpression(), b);
    }
};

template<typename Scalar, typename Derived>
struct solve_assertion<CwiseUnaryOp<Eigen::internal::scalar_conjugate_op<Scalar>, const Transpose<Derived> > >
{
    typedef CwiseUnaryOp<Eigen::internal::scalar_conjugate_op<Scalar>, const Transpose<Derived> > type;

    template<bool Transpose_, typename Rhs>
    static void run(const type& adjoint, const Rhs& b)
    {
        internal::solve_assertion<typename internal::remove_all<Transpose<Derived> >::type>::template run<true>(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<typename Derived>
class SolverBase : public EigenBase<Derived>
{
  public:

    typedef EigenBase<Derived> Base;
    typedef typename internal::traits<Derived>::Scalar Scalar;
    typedef Scalar CoeffReturnType;

    template<typename Derived_>
    friend struct internal::solve_assertion;

    enum {
      RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
      ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
      SizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::RowsAtCompileTime,
                                                          internal::traits<Derived>::ColsAtCompileTime>::ret),
      MaxRowsAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime,
      MaxColsAtCompileTime = internal::traits<Derived>::MaxColsAtCompileTime,
      MaxSizeAtCompileTime = (internal::size_at_compile_time<internal::traits<Derived>::MaxRowsAtCompileTime,
                                                             internal::traits<Derived>::MaxColsAtCompileTime>::ret),
      IsVectorAtCompileTime = internal::traits<Derived>::MaxRowsAtCompileTime == 1
                           || internal::traits<Derived>::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<typename Rhs>
    inline const Solve<Derived, Rhs>
    solve(const MatrixBase<Rhs>& b) const
    {
      internal::solve_assertion<typename internal::remove_all<Derived>::type>::template run<false>(derived(), b);
      return Solve<Derived, Rhs>(derived(), b.derived());
    }

    /** \internal the return type of transpose() */
    typedef typename internal::add_const<Transpose<const Derived> >::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<NumTraits<Scalar>::IsComplex,
                        CwiseUnaryOp<internal::scalar_conjugate_op<Scalar>, 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<bool Transpose_, typename Rhs>
    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<typename Derived>
struct generic_xpr_base<Derived, MatrixXpr, SolverStorage>
{
  typedef SolverBase<Derived> type;

};

} // end namespace internal

} // end namespace Eigen

#endif // EIGEN_SOLVERBASE_H
