// Copyright 2009 Hans Pirnay
// All Rights Reserved.
// This code is published under the Common Public License.
//
// Date   : 2009-05-08

#ifndef __ASINDEXSCHURDATA_HPP__
#define __ASINDEXSCHURDATA_HPP__

#include "AsSchurData.hpp"

namespace Ipopt
{

  class IndexSchurData : public SchurData
  {
    /** This class is the implementation aimed at applications where
     *  only SchurData matrices with entries 1 or -1 appear. */

  public:

    IndexSchurData();

    IndexSchurData(const std::vector<Index> idx, const std::vector<Index> val);
    
    virtual ~IndexSchurData();

    virtual SmartPtr<SchurData> MakeNewSchurDataCopy() const;

    virtual Index GetNRowsAdded() const;

    virtual void SetData_Flag(Index dim, const Index* flags, Number v=1.0);

    virtual void SetData_Flag(Index dim, const Index* flags, const Number* values);

    virtual Index SetData_Index(Index dim, const Index* index, Number v=1.0);
    
    virtual void SetData_List(const std::vector<Index>& list, Number v=1.0);

    virtual void GetRow(Index i, IteratesVector& v) const;

    virtual void GetMultiplyingVectors(Index i, std::vector<Index>& indices, std::vector<Number>& factors) const;

    virtual void Multiply(const IteratesVector& v, Vector& u) const;

    virtual void TransMultiply(const Vector& u, IteratesVector& v) const;

    virtual void PrintImpl(const Journalist& jnlst,
			   EJournalLevel level,
			   EJournalCategory category,
			   const std::string& name,
			   Index indent,
			   const std::string& prefix) const;

    /** Functions specific to IndexSchurData */

    /** This function is for adding data to a SchurData object. It takes a set of column-indices
     *  a value v and adds indices accordingly. If the column is already set in the data,
     *  it stays at the same place, otherwise the new indices are added at the bottom,
     *  in the order specified by the indices. The vector delta_u_sort returns the actual
     *  sorting so that the user knows how to place the new values inside the elongated 
     *  delta_u vector. These places are in C++ index style, so they correspond exactly
     *  to the indices used for the C++-array of the delta_u DenseVector*/
    void AddData_Flag(Index dim, Index* flags, std::vector<Index>& delta_u_sort, Index v);

    void AddData_List(std::vector<Index> cols, std::vector<Index>& delta_u_sort, Index& new_du_size, Index v);

    const std::vector<Index>* GetColIndices() const;

  private:

    /** returns a vector that holds the accumulated length of each vector component:
     *  v_len[0] = v.GetComp(0)->Dim()
     *  v_len[i] = sum(k=0..i, v.GetComp(k)->Dim()) */
    Index* GetVectorLengths(const IteratesVector& v) const;

    std::vector<Index> idx_;
    std::vector<Index> val_;
  };

}

#endif
