// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// 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_SPARSEVECTOR_H
#define EIGEN_SPARSEVECTOR_H

/** \class SparseVector
  *
  * \brief a sparse vector class
  *
  * \param _Scalar the scalar type, i.e. the type of the coefficients
  *
  * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme.
  *
  */
template<typename _Scalar, int _Options>
struct ei_traits<SparseVector<_Scalar, _Options> >
{
  typedef _Scalar Scalar;
  typedef Sparse StorageKind;
  typedef MatrixXpr XprKind;
  enum {
    IsColVector = _Options & RowMajorBit ? 0 : 1,

    RowsAtCompileTime = IsColVector ? Dynamic : 1,
    ColsAtCompileTime = IsColVector ? 1 : Dynamic,
    MaxRowsAtCompileTime = RowsAtCompileTime,
    MaxColsAtCompileTime = ColsAtCompileTime,
    Flags = _Options | NestByRefBit,
    CoeffReadCost = NumTraits<Scalar>::ReadCost,
    SupportedAccessPatterns = InnerRandomAccessPattern
  };
};

template<typename _Scalar, int _Options>
class SparseVector
  : public SparseMatrixBase<SparseVector<_Scalar, _Options> >
{
  public:
    EIGEN_SPARSE_GENERIC_PUBLIC_INTERFACE(SparseVector)
    EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=)
    EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=)
//     EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, =)

  protected:
  public:

    typedef SparseMatrixBase<SparseVector> SparseBase;
    enum { IsColVector = ei_traits<SparseVector>::IsColVector };

    CompressedStorage<Scalar> m_data;
    int m_size;

    CompressedStorage<Scalar>& _data() { return m_data; }
    CompressedStorage<Scalar>& _data() const { return m_data; }

  public:

    EIGEN_STRONG_INLINE int rows() const { return IsColVector ? m_size : 1; }
    EIGEN_STRONG_INLINE int cols() const { return IsColVector ? 1 : m_size; }
    EIGEN_STRONG_INLINE int innerSize() const { return m_size; }
    EIGEN_STRONG_INLINE int outerSize() const { return 1; }
    EIGEN_STRONG_INLINE int innerNonZeros(int j) const { ei_assert(j==0); return m_size; }

    EIGEN_STRONG_INLINE const Scalar* _valuePtr() const { return &m_data.value(0); }
    EIGEN_STRONG_INLINE Scalar* _valuePtr() { return &m_data.value(0); }

    EIGEN_STRONG_INLINE const int* _innerIndexPtr() const { return &m_data.index(0); }
    EIGEN_STRONG_INLINE int* _innerIndexPtr() { return &m_data.index(0); }

    inline Scalar coeff(int row, int col) const
    {
      ei_assert((IsColVector ? col : row)==0);
      return coeff(IsColVector ? row : col);
    }
    inline Scalar coeff(int i) const { return m_data.at(i); }

    inline Scalar& coeffRef(int row, int col)
    {
      ei_assert((IsColVector ? col : row)==0);
      return coeff(IsColVector ? row : col);
    }

    /** \returns a reference to the coefficient value at given index \a i
      * This operation involes a log(rho*size) binary search. If the coefficient does not
      * exist yet, then a sorted insertion into a sequential buffer is performed.
      *
      * This insertion might be very costly if the number of nonzeros above \a i is large.
      */
    inline Scalar& coeffRef(int i)
    {
      return m_data.atWithInsertion(i);
    }

  public:

    class InnerIterator;

    inline void setZero() { m_data.clear(); }

    /** \returns the number of non zero coefficients */
    inline int nonZeros() const  { return static_cast<int>(m_data.size()); }

    inline void startVec(int outer)
    {
      ei_assert(outer==0);
    }

    inline Scalar& insertBack(int outer, int inner)
    {
      ei_assert(outer==0);
      return insertBack(inner);
    }
    inline Scalar& insertBack(int i)
    {
      m_data.append(0, i);
      return m_data.value(m_data.size()-1);
    }

    inline Scalar& insert(int outer, int inner)
    {
      ei_assert(outer==0);
      return insert(inner);
    }
    Scalar& insert(int i)
    {
      int startId = 0;
      int id = m_data.size() - 1;
      // TODO smart realloc
      m_data.resize(id+2,1);

      while ( (id >= startId) && (m_data.index(id) > i) )
      {
        m_data.index(id+1) = m_data.index(id);
        m_data.value(id+1) = m_data.value(id);
        --id;
      }
      m_data.index(id+1) = i;
      m_data.value(id+1) = 0;
      return m_data.value(id+1);
    }

    /**
      */
    inline void reserve(int reserveSize) { m_data.reserve(reserveSize); }

    /** \deprecated use setZero() and reserve() */
    EIGEN_DEPRECATED void startFill(int reserve)
    {
      setZero();
      m_data.reserve(reserve);
    }

    /** \deprecated use insertBack(int,int) */
    EIGEN_DEPRECATED Scalar& fill(int r, int c)
    {
      ei_assert(r==0 || c==0);
      return fill(IsColVector ? r : c);
    }

    /** \deprecated use insertBack(int) */
    EIGEN_DEPRECATED Scalar& fill(int i)
    {
      m_data.append(0, i);
      return m_data.value(m_data.size()-1);
    }

    /** \deprecated use insert(int,int) */
    EIGEN_DEPRECATED Scalar& fillrand(int r, int c)
    {
      ei_assert(r==0 || c==0);
      return fillrand(IsColVector ? r : c);
    }

    /** \deprecated use insert(int) */
    EIGEN_DEPRECATED Scalar& fillrand(int i)
    {
      return insert(i);
    }

    /** \deprecated use finalize() */
    EIGEN_DEPRECATED void endFill() {}
    inline void finalize() {}

    void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
    {
      m_data.prune(reference,epsilon);
    }

    void resize(int rows, int cols)
    {
      ei_assert(rows==1 || cols==1);
      resize(IsColVector ? rows : cols);
    }

    void resize(int newSize)
    {
      m_size = newSize;
      m_data.clear();
    }

    void resizeNonZeros(int size) { m_data.resize(size); }

    inline SparseVector() : m_size(0) { resize(0); }

    inline SparseVector(int size) : m_size(0) { resize(size); }

    inline SparseVector(int rows, int cols) : m_size(0) { resize(rows,cols); }

    template<typename OtherDerived>
    inline SparseVector(const MatrixBase<OtherDerived>& other)
      : m_size(0)
    {
      *this = other.derived();
    }

    template<typename OtherDerived>
    inline SparseVector(const SparseMatrixBase<OtherDerived>& other)
      : m_size(0)
    {
      *this = other.derived();
    }

    inline SparseVector(const SparseVector& other)
      : m_size(0)
    {
      *this = other.derived();
    }

    inline void swap(SparseVector& other)
    {
      std::swap(m_size, other.m_size);
      m_data.swap(other.m_data);
    }

    inline SparseVector& operator=(const SparseVector& other)
    {
      if (other.isRValue())
      {
        swap(other.const_cast_derived());
      }
      else
      {
        resize(other.size());
        m_data = other.m_data;
      }
      return *this;
    }

    template<typename OtherDerived>
    inline SparseVector& operator=(const SparseMatrixBase<OtherDerived>& other)
    {
      if (int(RowsAtCompileTime)!=int(OtherDerived::RowsAtCompileTime))
        return Base::operator=(other.transpose());
      else
        return Base::operator=(other);
    }

//       const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit);
//       if (needToTranspose)
//       {
//         // two passes algorithm:
//         //  1 - compute the number of coeffs per dest inner vector
//         //  2 - do the actual copy/eval
//         // Since each coeff of the rhs has to be evaluated twice, let's evauluate it if needed
//         typedef typename ei_nested<OtherDerived,2>::type OtherCopy;
//         OtherCopy otherCopy(other.derived());
//         typedef typename ei_cleantype<OtherCopy>::type _OtherCopy;
//
//         resize(other.rows(), other.cols());
//         Eigen::Map<VectorXi>(m_outerIndex,outerSize()).setZero();
//         // pass 1
//         // FIXME the above copy could be merged with that pass
//         for (int j=0; j<otherCopy.outerSize(); ++j)
//           for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
//             ++m_outerIndex[it.index()];
//
//         // prefix sum
//         int count = 0;
//         VectorXi positions(outerSize());
//         for (int j=0; j<outerSize(); ++j)
//         {
//           int tmp = m_outerIndex[j];
//           m_outerIndex[j] = count;
//           positions[j] = count;
//           count += tmp;
//         }
//         m_outerIndex[outerSize()] = count;
//         // alloc
//         m_data.resize(count);
//         // pass 2
//         for (int j=0; j<otherCopy.outerSize(); ++j)
//           for (typename _OtherCopy::InnerIterator it(otherCopy, j); it; ++it)
//           {
//             int pos = positions[it.index()]++;
//             m_data.index(pos) = j;
//             m_data.value(pos) = it.value();
//           }
//
//         return *this;
//       }
//       else
//       {
//         // there is no special optimization
//         return SparseMatrixBase<SparseMatrix>::operator=(other.derived());
//       }
//     }

    friend std::ostream & operator << (std::ostream & s, const SparseVector& m)
    {
      for (unsigned int i=0; i<m.nonZeros(); ++i)
        s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
      s << std::endl;
      return s;
    }

    // this specialized version does not seems to be faster
//     Scalar dot(const SparseVector& other) const
//     {
//       int i=0, j=0;
//       Scalar res = 0;
//       asm("#begindot");
//       while (i<nonZeros() && j<other.nonZeros())
//       {
//         if (m_data.index(i)==other.m_data.index(j))
//         {
//           res += m_data.value(i) * ei_conj(other.m_data.value(j));
//           ++i; ++j;
//         }
//         else if (m_data.index(i)<other.m_data.index(j))
//           ++i;
//         else
//           ++j;
//       }
//       asm("#enddot");
//       return res;
//     }

    /** Destructor */
    inline ~SparseVector() {}

    /** Overloaded for performance */
    Scalar sum() const;
};

template<typename Scalar, int _Options>
class SparseVector<Scalar,_Options>::InnerIterator
{
  public:
    InnerIterator(const SparseVector& vec, int outer=0)
      : m_data(vec.m_data), m_id(0), m_end(static_cast<int>(m_data.size()))
    {
      ei_assert(outer==0);
    }

    InnerIterator(const CompressedStorage<Scalar>& data)
      : m_data(data), m_id(0), m_end(static_cast<int>(m_data.size()))
    {}

    template<unsigned int Added, unsigned int Removed>
    InnerIterator(const Flagged<SparseVector,Added,Removed>& vec, int outer)
      : m_data(vec._expression().m_data), m_id(0), m_end(m_data.size())
    {}

    inline InnerIterator& operator++() { m_id++; return *this; }

    inline Scalar value() const { return m_data.value(m_id); }
    inline Scalar& valueRef() { return const_cast<Scalar&>(m_data.value(m_id)); }

    inline int index() const { return m_data.index(m_id); }
    inline int row() const { return IsColVector ? index() : 0; }
    inline int col() const { return IsColVector ? 0 : index(); }

    inline operator bool() const { return (m_id < m_end); }

  protected:
    const CompressedStorage<Scalar>& m_data;
    int m_id;
    const int m_end;
};

#endif // EIGEN_SPARSEVECTOR_H
