/***************************************************************************
                          Vector.cpp  -  description
                             -------------------
    begin                : Don Feb 10 2005
    copyright            : (C) 2005 by klaus frieler
    email                : kgf@omniversum.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "Vector.h"

Vector& Vector::operator =(const Vector& vector)
{
   if(this==&vector){
      return *this;
   }
   clear();
   for(uint i = 0; i<vector.size(); ++i){
      push_back(vector[i]);
   }
   return *this;
}
Vector& Vector::operator =(const dData& vector)
{
   clear();
   for(uint i = 0; i<vector.size(); ++i){
      push_back(vector[i]);
   }
   return *this;
}
Vector& Vector::operator =(const iData& vector)
{
   clear();
   for(uint i = 0; i<vector.size(); ++i){
      push_back((double)vector[i]);
   }
   return *this;
}

void Vector::operator+=(const Vector& vector)
{
   if(empty()){
      *this = vector;
      return;
   }
   if(size()!=vector.size()) return;

   for(uint i = 0; i<size(); ++i){
      at(i) += vector[i];
   }
}
void Vector::operator-=(const Vector& vector)
{
   if(empty()){
      *this = vector;
      return;
   }
   if(size()!=vector.size()) return;

   for(uint i = 0; i<size(); ++i){
      at(i) -= vector[i];
   }
}
double Vector::operator*=(const Vector& vector)
{
   double sum = 0;
   if(size()!=vector.size()) return 0.0;

   for(uint i = 0; i<size(); ++i){
      sum += at(i) * vector[i];
   }
   return sum;
}
void Vector::operator *=(const double lambda)
{
   for(uint i = 0; i<size(); ++i){
      at(i) *= lambda;
   }
}
void Vector::operator /=(const double lambda)
{
   for(uint i = 0; i<size(); ++i){
      at(i) /= lambda;
   }
}
Vector Vector::operator+(const Vector& vector)const
{
   Vector tmp; 
   if(size()!=vector.size()) return tmp;
   for(uint i = 0; i<size(); ++i){
      tmp.push_back(at(i) + vector[i]);
   }
   return tmp;
}
Vector Vector::operator-(const Vector& vector)const
{
   Vector tmp; 
   if(size()!=vector.size()) return tmp;

   for(uint i = 0; i<size(); ++i){
      tmp.push_back(at(i) - vector[i]);
   }
   return tmp;
}
Vector Vector::operator*(const double lambda)const
{   
   Vector tmp;
   for(uint i = 0; i<size(); ++i){
      tmp.push_back( at(i) * lambda);
   }
   return *this;
}
Vector Vector::operator/(const double lambda)const
{   
   Vector tmp;
   for(uint i = 0; i<size(); ++i){
      tmp.push_back( at(i) / lambda);
   }
   return *this;
}

double Vector::operator*(const Vector& vector)const
{
   double sum = 0; 
   if(size()!=vector.size()) return 0.0;
   for(uint i = 0; i<size(); ++i){
      sum += at(i) * vector[i];
   }
   return sum;
}

bool Vector::operator==(const Vector& vector)const
{
   if(vector.size() != size()) return false;
   for(uint i = 0; i<size(); ++i){
      if(at(i) != vector[i]) return false;
   }
   return true;
}

void  Vector::remove(const uint idx)
{
   if(idx>size()-1) return;
   dData::iterator it = begin();
   for(uint i = 0; i<size(); ++i, ++it){
      if(i == idx){
         m_data.erase(it, it+1);
         return;
      }
   }
}

Vector  Vector::getLocalMaxima(iData& positions, bool bStrict ) const
{
   Vector ret;
   positions.clear();
   if(empty() || size()<2) return ret;

   if(bStrict){
      if(at(1)<at(0)){
         positions.push_back(0);
         ret.push_back(at(0));
      }  
   }
   else{
      if(at(1)<=at(0)){
         positions.push_back(0);
         ret.push_back(at(0));
      }
   }

   for(uint i = 1; i<size()-1; ++i){
      if(bStrict){
         if(at(i-1)<at(i) && at(i+1)<at(i)){
         positions.push_back(i);
         ret.push_back(at(i));
         }  
      }
      else{
         if(at(i-1)<=at(i) && at(i+1)<=at(i)){
         positions.push_back(i);
         ret.push_back(at(i));
         }
      }
   }
   if(bStrict){
      if(at(size()-2)<at(size()-1)){
         positions.push_back(size()-1);
         ret.push_back(at(size()-1));
      }  
   }
   else{
      if(at(size()-2)<=at(size()-1)){
         positions.push_back(size()-1);
         ret.push_back(at(size()-1));
      }
   }
   return ret;
}

Vector  Vector::getLocalMinima(iData& positions, bool bStrict ) const
{
   Vector tmp = this->operator*(-1.0);
   return tmp.getLocalMaxima(positions, bStrict);
}

Vector  Vector::normalize() const
{
   Vector ret(*this);
   double sum = 0;
   for(uint i = 0; i<ret.size(); ++i){
      sum += at(i)*at(i);
   }
   sum = sqrt(sum);
   if(sum == 0.0) return ret;
   for(uint i = 0; i<ret.size(); ++i){
      ret[i] /= sum;
   }
   return ret;
}

double  Vector::getMax() const
{
   double max = 0;
   for(uint i = 0; i<size(); ++i){
      if(at(i)>max){
         max = at(i);
      }
   }
   return max;
}

void  Vector::dump(const char* text)const
{  
   if(strlen(text)) cout<<text<<" ";
   if(empty()){
      cout<<"()"<<endl;
      return;
   }
   cout<<setprecision(3)<<"(";
   for(uint i = 0; i<size()-1; ++i){
      cout<<at(i)<<" ";
   }
   cout<<at(size()-1)<<")"<<endl;
}
