626 lines
20 KiB
C++
626 lines
20 KiB
C++
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
/* */
|
|
/* */
|
|
/* MV++ Numerical Matrix/Vector C++ Library */
|
|
/* MV++ Version 1.5 */
|
|
/* */
|
|
/* R. Pozo */
|
|
/* National Institute of Standards and Technology */
|
|
/* */
|
|
/* NOTICE */
|
|
/* */
|
|
/* Permission to use, copy, modify, and distribute this software and */
|
|
/* its documentation for any purpose and without fee is hereby granted */
|
|
/* provided that this permission notice appear in all copies and */
|
|
/* supporting documentation. */
|
|
/* */
|
|
/* Neither the Institution (National Institute of Standards and Technology) */
|
|
/* nor the author makes any representations about the suitability of this */
|
|
/* software for any purpose. This software is provided ``as is''without */
|
|
/* expressed or implied warranty. */
|
|
/* */
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
|
|
//
|
|
// mvvtp.h Basic templated vector class
|
|
//
|
|
|
|
// modif gérard Rio :
|
|
// - introduction de la surcharge d'écriture dans la classe MVvecteur
|
|
// - modification de l'indice du type unsigned int au type int et vérification
|
|
// du nombre négatif
|
|
// - modification de la surcharge d'écriture (ajout de l'écriture de la taille)
|
|
// et ajout de la surcharge de lecture en cohérence avec l'écriture déjà existante
|
|
// - introduction de la possibilité de créer un vecteur à la place d'un autre
|
|
// en donnant la référence à l'autre vecteur et un indicateur de non construction
|
|
// - dans le cas ou les tailles à alouer sont nulles, on met en place une procédure spé
|
|
|
|
|
|
#ifndef _MV_VECTOR_TPL_H_
|
|
#define _MV_VECTOR_TPL_H_
|
|
|
|
#include <iostream> // for formatted printing of vecteur : GR
|
|
|
|
#include <stdlib.h>
|
|
#ifdef MV_VECTOR_BOUNDS_CHECK
|
|
# include <assert.h>
|
|
#endif
|
|
#include "Sortie.h"
|
|
//#ifdef SYSTEM_MAC_OS_X
|
|
// #include <stringfwd.h> // a priori ce n'est pas portable
|
|
//#el
|
|
#if defined SYSTEM_MAC_OS_CARBON
|
|
#include <stringfwd.h> // a priori ce n'est pas portable
|
|
#else
|
|
#include <string.h> // pour le flot en memoire centrale
|
|
#endif
|
|
#include <string>
|
|
|
|
#include "mvvind_GR.h"
|
|
#include "mvvrf_GR.h"
|
|
using namespace std;
|
|
template <class TYPE>
|
|
class MV_Vector
|
|
{
|
|
protected:
|
|
TYPE *p_;
|
|
// unsigned int dim_;
|
|
int dim_; // modif GR
|
|
int ref_; // 0 or 1; does this own its own memory space?
|
|
public:
|
|
|
|
// les informations sont le type puis la taille puis les datas
|
|
friend istream & operator >> (istream & entree, MV_Vector<TYPE>& vec)
|
|
{ // vérification du type
|
|
string type;
|
|
entree >> type;
|
|
if (type != "MV_Vector<>")
|
|
{Sortie (1);
|
|
return entree;
|
|
}
|
|
// passage de la chaine donnant la taille puis lecture de la taille
|
|
int taille;
|
|
entree >> type >> taille;
|
|
// vérification de la taille sinon changement
|
|
if (vec.size() != taille) vec.newsize(taille);
|
|
// lecture des données
|
|
for (int i = 0; i< taille; i++)
|
|
entree >> vec.p_[i];
|
|
return entree;
|
|
};
|
|
// surcharge de l'operator d'ecriture non formatée
|
|
// les informations sont le type puis la taille puis les datas séparées par
|
|
// un espace
|
|
friend ostream& operator<<(ostream& s, const MV_Vector<TYPE>& V)
|
|
{
|
|
int N = V.size();
|
|
s << "\n MV_Vector<> taille= " << V.size();
|
|
for (int j=0; j<N; j++)
|
|
s << V(j) << " " ;
|
|
s << endl;
|
|
return s;
|
|
}
|
|
|
|
/*::::::::::::::::::::::::::*/
|
|
/* Constructors/Destructors */
|
|
/*::::::::::::::::::::::::::*/
|
|
|
|
MV_Vector();
|
|
// MV_Vector(unsigned int);
|
|
// MV_Vector(unsigned int, const TYPE&);
|
|
// MV_Vector(TYPE*, unsigned int);
|
|
// MV_Vector(const TYPE*, unsigned int);
|
|
|
|
MV_Vector( int); // modif GR
|
|
MV_Vector( int, const TYPE&); // modif GR
|
|
|
|
MV_Vector(TYPE*, int); // modif GR
|
|
MV_Vector(const TYPE*, int); // modif GR
|
|
|
|
// reference of an exisiting data structure
|
|
//
|
|
// MV_Vector(TYPE*, unsigned int, MV_Vector_::ref_type i);
|
|
MV_Vector(TYPE*, int, MV_Vector_::ref_type i); // modif GR
|
|
// construction ici réelle
|
|
MV_Vector(const MV_Vector<TYPE>&);
|
|
// construction conditionnelle en fonction de l'indicateur
|
|
// cette construction est moins rapide que la précédente s'il y a vraiment
|
|
// définition d'un nouveau tableau de data (appel de new moin bon)
|
|
MV_Vector(MV_Vector<TYPE>&,MV_Vector_::ref_type i);
|
|
// destructeur
|
|
~MV_Vector();
|
|
|
|
/*::::::::::::::::::::::::::::::::*/
|
|
/* Indices and access operations */
|
|
/*::::::::::::::::::::::::::::::::*/
|
|
|
|
|
|
// inline TYPE& operator()(unsigned int i)
|
|
inline TYPE& operator()(int i) // modif GR
|
|
{
|
|
# ifdef MV_VECTOR_BOUNDS_CHECK
|
|
// assert(i < dim_);
|
|
assert((i < dim_)||(i>=0)); // modif GR
|
|
# endif
|
|
return p_[i];
|
|
}
|
|
// inline const TYPE& operator()(unsigned int i) const
|
|
inline const TYPE& operator()( int i) const // modif GR
|
|
{
|
|
# ifdef MV_VECTOR_BOUNDS_CHECK
|
|
// assert(i < dim_);
|
|
assert((i < dim_)||(i>=0)); // modif GR
|
|
# endif
|
|
return p_[i];
|
|
}
|
|
|
|
// inline TYPE& operator[](unsigned int i)
|
|
inline TYPE& operator[](int i) // modif GR
|
|
{
|
|
# ifdef MV_VECTOR_BOUNDS_CHECK
|
|
// assert(i < dim_);
|
|
assert((i < dim_)||(i>=0)); // modif GR
|
|
# endif
|
|
return p_[i];
|
|
}
|
|
// inline const TYPE& operator[](unsigned int i) const
|
|
inline const TYPE& operator[]( int i) const // modif GR
|
|
{
|
|
# ifdef MV_VECTOR_BOUNDS_CHECK
|
|
// assert(i < dim_);
|
|
assert((i < dim_)||(i>=0)); // modif GR
|
|
# endif
|
|
return p_[i];
|
|
}
|
|
|
|
|
|
|
|
inline MV_Vector<TYPE> operator()(const MV_VecIndex &I) ;
|
|
inline MV_Vector<TYPE> operator()(void);
|
|
inline const MV_Vector<TYPE> operator()(void) const;
|
|
inline const MV_Vector<TYPE> operator()(const MV_VecIndex &I) const;
|
|
|
|
// inline unsigned int size() const { return dim_;}
|
|
inline int size() const { return dim_;} // modif GR
|
|
inline int ref() const { return ref_;}
|
|
inline int null() const {return dim_== 0;}
|
|
//
|
|
// Create a new *uninitalized* vector of size N
|
|
MV_Vector<TYPE> & newsize( int );
|
|
|
|
/*::::::::::::::*/
|
|
/* Assignment */
|
|
/*::::::::::::::*/
|
|
|
|
MV_Vector<TYPE> & operator=(const MV_Vector<TYPE>&);
|
|
MV_Vector<TYPE> & operator=(const TYPE&);
|
|
|
|
|
|
|
|
};
|
|
|
|
template <class TYPE>
|
|
ostream& operator<<(ostream& s, const MV_Vector<TYPE>& V)
|
|
{
|
|
int N = V.size();
|
|
|
|
s << "\n MV_Vector<> taille= " << V.size();
|
|
for (int j=0; j<N; j++)
|
|
s << V(j) << " " ;
|
|
s << endl;
|
|
|
|
return s;
|
|
}
|
|
|
|
// surcharge de l'operateur de lecture
|
|
// cohérente avec l'écriture déjà existante
|
|
template <class TYPE>
|
|
istream & operator >> (istream & entree, MV_Vector<TYPE>& vec)
|
|
{ // vérification du type
|
|
string type;
|
|
entree >> type;
|
|
if (type != "MV_Vector<>")
|
|
{Sortie (1);
|
|
return entree;
|
|
}
|
|
// passage de la chaine donnant la taille puis lecture de la taille
|
|
int taille;
|
|
entree >> type >> taille;
|
|
// vérification de la taille sinon changement
|
|
if (vec.size() != taille) vec.newsize(taille);
|
|
// lecture des données
|
|
for (int i = 0; i< vec.taille; i++)
|
|
entree >> vec.p_[i];
|
|
return entree;
|
|
};
|
|
|
|
template <class TYPE>
|
|
MV_Vector<TYPE>::MV_Vector() : p_(NULL), dim_(0) , ref_(0){}
|
|
|
|
template <class TYPE>
|
|
//MV_Vector<TYPE>::MV_Vector(unsigned int n) : p_(new TYPE[n]), dim_(n),
|
|
// a priori si n est négatif new ramènera une erreur
|
|
//MV_Vector<TYPE>::MV_Vector( int n) : p_(new TYPE[n]), dim_(n), // modif 1 GR
|
|
MV_Vector<TYPE>::MV_Vector( int n) : dim_(n), // modif 2 GR
|
|
ref_(0)
|
|
{ if (n!= 0)
|
|
{p_ = new TYPE[n];
|
|
if (p_ == NULL)
|
|
{
|
|
cerr << "Error: NULL pointer in MV_Vector(int) constructor " << endl;
|
|
cerr << " Most likely out of memory... " << endl;
|
|
Sortie(1);
|
|
}
|
|
}
|
|
else
|
|
p_=NULL; // ajout car new ne fait pas bien son boulot !!
|
|
}
|
|
|
|
template <class TYPE>
|
|
//MV_Vector<TYPE>::MV_Vector(unsigned int n, const TYPE& v) :
|
|
MV_Vector<TYPE>::MV_Vector( int n, const TYPE& v) : // modif 1 GR
|
|
// p_(new TYPE[n]), dim_(n), ref_(0)
|
|
dim_(n), ref_(0) // modif 2 GR
|
|
{
|
|
if (n!= 0)
|
|
{ p_ = new TYPE[n];
|
|
if (p_ == NULL)
|
|
{
|
|
cerr << "Error: NULL pointer in MV_Vector(int) constructor " << endl;
|
|
cerr << " Most likely out of memory... " << endl;
|
|
Sortie(1);
|
|
}
|
|
for (int i=0; i<n; i++)
|
|
p_[i] = v;
|
|
}
|
|
else
|
|
p_=NULL; // ajout car new ne fait pas bien son boulot !!
|
|
|
|
}
|
|
|
|
// operators and member functions
|
|
//
|
|
|
|
|
|
|
|
|
|
template <class TYPE>
|
|
MV_Vector<TYPE>& MV_Vector<TYPE>::operator=(const TYPE & m)
|
|
{
|
|
#ifdef TRACE_VEC
|
|
cout << "> MV_Vector<TYPE>::operator=(const TYPE & m) " << endl;
|
|
#endif
|
|
|
|
// unroll loops to depth of length 4
|
|
|
|
int N = this->size();
|
|
|
|
int Nminus4 = N-4;
|
|
int i;
|
|
|
|
for (i=0; i<Nminus4; )
|
|
{
|
|
p_[i++] = m;
|
|
p_[i++] = m;
|
|
p_[i++] = m;
|
|
p_[i++] = m;
|
|
}
|
|
|
|
for (; i<N; p_[i++] = m) ; // finish off last piece...
|
|
|
|
#ifdef TRACE_VEC
|
|
cout << "< MV_Vector<TYPE>::operator=(const TYPE & m) " << endl;
|
|
#endif
|
|
return *this;
|
|
}
|
|
|
|
template <class TYPE>
|
|
//MV_Vector<TYPE>& MV_Vector<TYPE>::newsize(unsigned int n)
|
|
MV_Vector<TYPE>& MV_Vector<TYPE>::newsize( int n) // modif GR
|
|
{
|
|
#ifdef TRACE_VEC
|
|
// cout << "> MV_Vector<TYPE>::newsize(unsigned int n) " << endl;
|
|
cout << "> MV_Vector<TYPE>::newsize( int n) " << endl;
|
|
#endif
|
|
if (ref_ ) // is this structure just a pointer?
|
|
{
|
|
{
|
|
cerr << "MV_Vector::newsize can't operator on references.\n";
|
|
Sortie(1);
|
|
}
|
|
}
|
|
else
|
|
if (dim_ != n ) // only delete and new if
|
|
{ // the size of memory is really
|
|
if (p_) delete [] p_; // changing, otherwise just
|
|
p_ = new TYPE[n]; // copy in place.
|
|
if (p_ == NULL)
|
|
{
|
|
cerr << "Error : NULL pointer in operator= " << endl;
|
|
Sortie(1);
|
|
}
|
|
dim_ = n;
|
|
}
|
|
|
|
#ifdef TRACE_VEC
|
|
// cout << "< MV_Vector<TYPE>::newsize(unsigned int n) " << endl;
|
|
cout << "< MV_Vector<TYPE>::newsize( int n) " << endl;
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
|
|
template <class TYPE>
|
|
MV_Vector<TYPE>& MV_Vector<TYPE>::operator=(const MV_Vector<TYPE> & m)
|
|
{
|
|
|
|
int N = m.dim_;
|
|
int i;
|
|
|
|
if (ref_ ) // is this structure just a pointer?
|
|
{
|
|
if (dim_ != m.dim_) // check conformance,
|
|
{
|
|
cerr << "MV_VectorRef::operator= non-conformant assignment.\n";
|
|
Sortie(1);
|
|
}
|
|
|
|
// handle overlapping matrix references
|
|
if ((m.p_ + m.dim_) >= p_)
|
|
{
|
|
// overlap case, copy backwards to avoid overwriting results
|
|
for (i= N-1; i>=0; i--)
|
|
p_[i] = m.p_[i];
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i<N; i++)
|
|
p_[i] = m.p_[i];
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
newsize(N);
|
|
|
|
// no need to test for overlap, since this region is new
|
|
for (i =0; i< N; i++) // careful not to use bcopy()
|
|
p_[i] = m.p_[i]; // here, but TYPE::operator= TYPE.
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template <class TYPE>
|
|
//MV_Vector<TYPE>::MV_Vector(const MV_Vector<TYPE> & m) : p_(new TYPE[m.dim_]),
|
|
MV_Vector<TYPE>::MV_Vector(const MV_Vector<TYPE> & m) : // modif 2 GR
|
|
dim_(m.dim_) , ref_(0) , p_(NULL) // gerard: ajout de p_(NULL)
|
|
{ if (m.dim_ != 0)
|
|
{p_ = new TYPE[m.dim_];
|
|
if (p_ == NULL)
|
|
{
|
|
cerr << "Error: Null pointer in MV_Vector(const MV_Vector&); " << endl;
|
|
Sortie(1);
|
|
}
|
|
|
|
int N = m.dim_;
|
|
|
|
for (int i=0; i<N; i++)
|
|
p_[i] = m.p_[i];
|
|
};
|
|
}
|
|
|
|
|
|
// note that ref() is initalized with i rather than 1.
|
|
// this is so compilers will not generate a warning that i was
|
|
// not used in the construction. (MV_Vector::ref_type is an enum that
|
|
// can *only* have the value of 1.
|
|
//
|
|
template <class TYPE>
|
|
//MV_Vector<TYPE>::MV_Vector(TYPE* d, unsigned int n, MV_Vector_::ref_type i) :
|
|
MV_Vector<TYPE>::MV_Vector(TYPE* d, int n, MV_Vector_::ref_type i) : // modif GR
|
|
p_(d), dim_(n) , ref_(i)
|
|
{
|
|
# ifdef MV_VECTOR_BOUNDS_CHECK
|
|
assert(n < 0); // modif GR
|
|
# endif
|
|
}
|
|
|
|
template <class TYPE>
|
|
//MV_Vector<TYPE>::MV_Vector(TYPE* d, unsigned int n) : p_(new TYPE[n]),
|
|
//MV_Vector<TYPE>::MV_Vector(TYPE* d, int n) : p_(new TYPE[n]), // modif 1 GR
|
|
MV_Vector<TYPE>::MV_Vector(TYPE* d, int n) : // modif 2 GR
|
|
// a priori si n est négatif l'opérateur new renvera une erreur
|
|
dim_(n) , ref_(0)
|
|
{ if (n != 0)
|
|
{p_ = new TYPE[n];
|
|
if (p_ == NULL)
|
|
{
|
|
cerr << "Error: Null pointer in MV_Vector(TYPE*, int) " << endl;
|
|
Sortie(1);
|
|
}
|
|
for (int i=0; i<n; i++)
|
|
p_[i] = d[i];
|
|
}
|
|
else
|
|
p_=NULL; // ajout car new ne fait pas bien son boulot !!
|
|
|
|
}
|
|
|
|
// construction conditionnelle en fonction de l'indicateur
|
|
// cette construction est moins rapide que la précédente s'il y a vraiment
|
|
// définition d'un nouveau tableau de data (appel de new moin bon)
|
|
template <class TYPE>
|
|
MV_Vector<TYPE>::MV_Vector(MV_Vector<TYPE>& B ,MV_Vector_::ref_type i) :
|
|
p_(B.p_),dim_(B.dim_) , ref_(i)
|
|
{ // le vecteur est construit en fonction du cas donné par ref_
|
|
if (ref_ != 1)
|
|
// cas avec construction
|
|
{ p_ = new TYPE[dim_];
|
|
for (int i=0; i<dim_; i++)
|
|
p_[i] = B.p_[i];
|
|
}
|
|
// sinon le pointeur p_ est déjà bien positionné
|
|
|
|
# ifdef MV_VECTOR_BOUNDS_CHECK
|
|
assert(n < 0); // modif GR
|
|
# endif
|
|
}
|
|
|
|
template <class TYPE>
|
|
//MV_Vector<TYPE>::MV_Vector(const TYPE* d, unsigned int n) : p_(new TYPE[n]),
|
|
//MV_Vector<TYPE>::MV_Vector(const TYPE* d, int n) : p_(new TYPE[n]), // modif 1 GR
|
|
MV_Vector<TYPE>::MV_Vector(const TYPE* d, int n) : // modif 2 GR
|
|
// a priori si n est négatif l'opérateur new renvera une erreur
|
|
dim_(n) , ref_(0)
|
|
{if (n != 0)
|
|
{p_=new TYPE[n];
|
|
if (p_ == NULL)
|
|
{
|
|
cerr << "Error: Null pointer in MV_Vector(TYPE*, int) " << endl;
|
|
Sortie(1);
|
|
}
|
|
for (int i=0; i<n; i++)
|
|
p_[i] = d[i];
|
|
}
|
|
else
|
|
p_=NULL; // ajout car new ne fait pas bien son boulot !!
|
|
|
|
}
|
|
|
|
template <class TYPE>
|
|
MV_Vector<TYPE> MV_Vector<TYPE>::operator()(void)
|
|
{
|
|
return MV_Vector<TYPE>(p_, dim_, MV_Vector_::ref);
|
|
}
|
|
|
|
template <class TYPE>
|
|
const MV_Vector<TYPE> MV_Vector<TYPE>::operator()(void) const
|
|
{
|
|
return MV_Vector<TYPE>(p_, dim_, MV_Vector_::ref);
|
|
}
|
|
|
|
template <class TYPE>
|
|
MV_Vector<TYPE> MV_Vector<TYPE>::operator()(const MV_VecIndex &I)
|
|
{
|
|
// default parameters
|
|
if (I.all())
|
|
return MV_Vector<TYPE>(p_, dim_, MV_Vector_::ref);
|
|
else
|
|
{
|
|
// check that index is not out of bounds
|
|
//
|
|
if ( I.end() >= dim_)
|
|
{
|
|
cerr << "MV_VecIndex: (" << I.start() << ":" << I.end() <<
|
|
") too big for matrix (0:" << dim_ - 1 << ") " << endl;
|
|
Sortie(1);
|
|
}
|
|
return MV_Vector<TYPE>(p_+ I.start(), I.end() - I.start() + 1,
|
|
MV_Vector_::ref);
|
|
}
|
|
}
|
|
|
|
template <class TYPE>
|
|
const MV_Vector<TYPE> MV_Vector<TYPE>::operator()(const MV_VecIndex &I) const
|
|
{
|
|
// check that index is not out of bounds
|
|
//
|
|
if ( I.end() >= dim_)
|
|
{
|
|
cerr << "MV_VecIndex: (" << I.start() << ":" << I.end() <<
|
|
") too big for matrix (0:" << dim_ - 1 << ") " << endl;
|
|
Sortie(1);
|
|
}
|
|
return MV_Vector<TYPE>(p_+ I.start(), I.end() - I.start() + 1,
|
|
MV_Vector_::ref);
|
|
}
|
|
|
|
template <class TYPE>
|
|
MV_Vector<TYPE>::~MV_Vector()
|
|
{
|
|
if (p_ && !ref_ ) delete [] p_;
|
|
}
|
|
|
|
|
|
template <class TYPE>
|
|
class FMV_Vector : public MV_Vector<TYPE>
|
|
{
|
|
public:
|
|
// FMV_Vector(unsigned int n) : MV_Vector<TYPE>(n) {}
|
|
FMV_Vector( int n) : MV_Vector<TYPE>(n) {}
|
|
FMV_Vector<TYPE>& operator=(const FMV_Vector<TYPE>& m);
|
|
FMV_Vector<TYPE>& operator=(const TYPE& m);
|
|
};
|
|
|
|
template <class TYPE>
|
|
FMV_Vector<TYPE>& FMV_Vector<TYPE>::operator=( const FMV_Vector<TYPE>& m)
|
|
{
|
|
|
|
#ifdef TRACE_VEC
|
|
cout << "> FMV_Vector<TYPE>::operator=( const FMV_Vector<TYPE>& m)" << endl;
|
|
#endif
|
|
|
|
int N = m.dim_;
|
|
|
|
|
|
|
|
if (this->ref_ ) // is this structure just a pointer?
|
|
{
|
|
if (this->dim_ != m.dim_) // check conformance,
|
|
{
|
|
cerr << "MV_VectorRef::operator= non-conformant assignment.\n";
|
|
Sortie(1);
|
|
}
|
|
}
|
|
else if ( this->dim_ != m.dim_ ) // resize only if necessary
|
|
this->newsize(N);
|
|
|
|
memmove(this->p_, m.p_, N * sizeof(TYPE));
|
|
|
|
#ifdef TRACE_VEC
|
|
cout << "< FMV_Vector<TYPE>::operator=( const FMV_Vector<TYPE>& m)" << endl;
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class TYPE>
|
|
FMV_Vector<TYPE>& FMV_Vector<TYPE>::operator=(const TYPE & m)
|
|
{
|
|
#ifdef TRACE_VEC
|
|
cout << "> FMV_Vector<TYPE>::operator=(const TYPE & m) " << endl;
|
|
#endif
|
|
|
|
// unroll loops to depth of length 4
|
|
|
|
int N = this->size();
|
|
|
|
int Nminus4 = N-4;
|
|
int i;
|
|
|
|
for (i=0; i<Nminus4; )
|
|
{
|
|
this->p_[i++] = m;
|
|
this->p_[i++] = m;
|
|
this->p_[i++] = m;
|
|
this->p_[i++] = m;
|
|
}
|
|
|
|
for (; i<N; this->p_[i++] = m); // finish off last piece...
|
|
|
|
#ifdef TRACE_VEC
|
|
cout << "< FMV_Vector<TYPE>::operator=(const TYPE & m) " << endl;
|
|
#endif
|
|
return *this;
|
|
}
|
|
|
|
|
|
#include "mvblas_GR.h"
|
|
|
|
#endif
|
|
// _MV_VECTOR_TPL_H_
|
|
|