// Copyright (C) 2003, International Business Machines
// Corporation and others.  All Rights Resized.
#if defined(_MSC_VER)
// Turn off compiler warning about long names
#  pragma warning(disable:4786)
#endif

#include <cassert>
#include "CoinDenseVector.hpp"
#include "CoinHelperFunctions.hpp"

//#############################################################################

template <typename T> void
CoinDenseVector<T>::clear()
{
   memset(elements_, 0, nElements_*sizeof(T));
}

//#############################################################################

template <typename T> CoinDenseVector<T> &
CoinDenseVector<T>::operator=(const CoinDenseVector<T> & rhs)
{
   if (this != &rhs) {
     setVector(rhs.getNumElements(), rhs.getElements());
   }
   return *this;
}

//#############################################################################

template <typename T> void
CoinDenseVector<T>::setVector(int size, const T * elems)
{
   resize(size);
   CoinMemcpyN( elems,size,elements_);
}

//#############################################################################

template <typename T> void
CoinDenseVector<T>::setConstant(int size, T value)
{
   resize(size);
   for(int i=0; i<size; i++)
     elements_[i] = value;
}

//#############################################################################

template <typename T> void
CoinDenseVector<T>::resize(int newsize, T value)
{
  if (newsize != nElements_){
    assert(newsize > 0);
    T *newarray = new T[newsize];
    int cpysize = CoinMin(newsize, nElements_);
    CoinMemcpyN( elements_,cpysize,newarray);
    delete[] elements_;
    elements_ = newarray;
    nElements_ = newsize;
    for(int i=cpysize; i<newsize; i++)
      elements_[i] = value;
  }
}

//#############################################################################

template <typename T> void
CoinDenseVector<T>::setElement(int index, T element)
{
  assert(index >= 0 && index < nElements_);
   elements_[index] = element;
}

//#############################################################################

template <typename T> void
CoinDenseVector<T>::append(const CoinDenseVector<T> & caboose)
{
   const int s = nElements_;
   const int cs = caboose.getNumElements();
   int newsize = s + cs;
   resize(newsize);
   const T * celem = caboose.getElements();
   CoinDisjointCopyN(celem, cs, elements_ + s);
}

//#############################################################################

template <typename T> void
CoinDenseVector<T>::operator+=(T value) 
{
  for(int i=0; i<nElements_; i++)
    elements_[i] += value;
}

//-----------------------------------------------------------------------------

template <typename T> void
CoinDenseVector<T>::operator-=(T value) 
{
  for(int i=0; i<nElements_; i++)
    elements_[i] -= value;
}

//-----------------------------------------------------------------------------

template <typename T> void
CoinDenseVector<T>::operator*=(T value) 
{
  for(int i=0; i<nElements_; i++)
    elements_[i] *= value;
}

//-----------------------------------------------------------------------------

template <typename T> void
CoinDenseVector<T>::operator/=(T value) 
{
  for(int i=0; i<nElements_; i++)
    elements_[i] /= value;
}

//#############################################################################

template <typename T> CoinDenseVector<T>::CoinDenseVector():
   nElements_(0),
   elements_(NULL)
{}
  
//#############################################################################

template <typename T> 
CoinDenseVector<T>::CoinDenseVector(int size, const T * elems):
   nElements_(0),
   elements_(NULL)
{
  gutsOfSetVector(size, elems);
}

//-----------------------------------------------------------------------------

template <typename T> CoinDenseVector<T>::CoinDenseVector(int size, T value):
   nElements_(0),
   elements_(NULL)
{
  gutsOfSetConstant(size, value);
}

//-----------------------------------------------------------------------------

template <typename T> 
CoinDenseVector<T>::CoinDenseVector(const CoinDenseVector<T> & rhs):
   nElements_(0),
   elements_(NULL)
{
     setVector(rhs.getNumElements(), rhs.getElements());
}

//-----------------------------------------------------------------------------

template <typename T> CoinDenseVector<T>::~CoinDenseVector ()
{
   delete [] elements_;
}

//#############################################################################

template <typename T> void
CoinDenseVector<T>::gutsOfSetVector(int size, const T * elems)
{
   if ( size != 0 ) {
      resize(size);
      nElements_ = size;
      CoinDisjointCopyN(elems, size, elements_);
   }
}

//-----------------------------------------------------------------------------

template <typename T> void
CoinDenseVector<T>::gutsOfSetConstant(int size, T value)
{
   if ( size != 0 ) {
      resize(size);
      nElements_ = size;
      CoinFillN(elements_, size, value);
   }
}

//#############################################################################
/** Access the i'th element of the dense vector.  */
template <typename T> T &
CoinDenseVector<T>::operator[](int index) const
{
  assert(index >= 0 && index < nElements_);
  T *where = elements_ + index;
  return *where;
}
//#############################################################################

// template class CoinDenseVector<int>; This works but causes warning messages
template class CoinDenseVector<float>;
template class CoinDenseVector<double>;
