// This may look like C code, but it is really -*- C++ -*-

#ifndef VECTOR_SEEN
#define VECTOR_SEEN
#include "matrix.h"

namespace SOPHYA {
  class GeneralFit;
  template <class T> class TVector;
}

// <summary> Vecteur colonne pour operations matricielles </summary>
// Vecteur colonne, en fait une matrice avec une seule colonne, pour faire
// des operations matricielles.
class OVector : public OMatrix {
  friend class TVector<r_8>;
public:
  // Constructeur, n = nombre d'elements.
  EXPLICIT OVector(int n=1);
  // Constructeur, a partir des valeurs. Pas d'allocation.
  OVector(int n, double* values);
  // Constructeur par copie
  OVector(const OVector& v);
  // Constructeur par "copie" a partir d'une matrice, qui doit avoir une colonne
  // <thrown> sizeMismatchErr </thrown>
  OVector(const OMatrix& a);
  // Constructeur par copie a partir d'un TVector<r_8>
  OVector(const TVector<r_8>& v);

  // Construction automatique pour PPF
  // <group>
  enum {classId = ClassId_Vector};
  int_4                 ClassId() const         { return classId; }
  static PPersist*      Create() {return new OVector(1);}
  // </group>
  
  // Change la taille du vecteur. Reallocation physique seulement si
  // pas assez de place, ou forcee si force=true
  void Realloc(int n, bool force=false);

  OVector& operator = (const OVector& v);
  OVector& operator = (double x);

  // Acces aux elements
  // <group>
  double& operator()(int n);
  double const& operator()(int n) const;
  // </group>

  // produit scalaire
  // <group>
  friend double operator* (const OVector& v1, const OVector& v2);
  friend OVector operator* (const OVector& v, double b)
  {return OVector(((OMatrix const&)v) * b);}
  // </group>
  // produit matrice*vecteur
  friend OVector operator* (const OMatrix& a, const OVector& b)
  {return OVector(a * ((OMatrix const&) (b)));}

  // Nombre de lignes du vecteur
  int NElts() const {return nr;}

  // Resolution du systeme A*C = B
  friend double LinSolve(const OMatrix& a, const OVector& b, OVector& c);
  
  // Resolution du systeme A*C = B, avec C retourne dans B
  friend double LinSolveInPlace(OMatrix& a, OVector& b);

  // Residus et fonction fittees.
  OVector FitResidus(GeneralFit& gfit,double xorg=0.,double dx=1.);
  OVector FitFunction(GeneralFit& gfit,double xorg=0.,double dx=1.);

};


inline OVector& OVector::operator = (const OVector& v)
{ OMatrix::operator =(v); return *this; }


inline double const& OVector::operator()(int n) const
{
#ifdef RGCHECK
  if (n<0 || n>=ndata) THROW(rangeCheckErr);
#endif
  return data[n];
}


inline double& OVector::operator()(int n)
{ 
#ifdef RGCHECK
  if (n<0 || n>=ndata) THROW(rangeCheckErr);
#endif
  return data[n];
}

inline void OVector::Realloc(int n, bool force)
{ OMatrix::Realloc(n,1,force);}


#endif /* VECTOR_SEEN */
