// 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"

#include "./InternalHeaderCheck.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, internal::max_size_prefer_dynamic(RowsAtCompileTime, ColsAtCompileTime),
                           internal::max_size_prefer_dynamic(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 EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT {
        return derived().rows();
    }

    /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/
    inline EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT {
        return derived().cols();
    }

    /** \returns the number of coefficients, which is \a rows()*cols().
     * \sa rows(), cols(), SizeAtCompileTime. */
    inline EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT {
        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
