// 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;
  enum {
    IsColVector = _Options & RowMajorBit ? 0 : 1,

    RowsAtCompileTime = IsColVector ? Dynamic : 1,
    ColsAtCompileTime = IsColVector ? 1 : Dynamic,
    MaxRowsAtCompileTime = RowsAtCompileTime,
    MaxColsAtCompileTime = ColsAtCompileTime,
    Flags = SparseBit | _Options,
    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 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 = precision<RealScalar>())
    {
      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(m_data.size())
    {
      ei_assert(outer==0);
    }

    InnerIterator(const CompressedStorage<Scalar>& data)
      : m_data(data), m_id(0), m_end(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
