Rev 601 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/* ----------------------------------------------------------------------- *
* This file is part of GEL, http://www.imm.dtu.dk/GEL
* Copyright (C) the authors and DTU Informatics
* For license and list of authors, see ../../doc/intro.pdf
* ----------------------------------------------------------------------- */
/*!
\file Vector.h
\brief The Vector type
*/
#if !defined(VECTOR_H__HAA_AGUST_2001)
#define VECTOR_H__HAA_AGUST_2001
#include <cassert>
#include <iostream>
#include <cmath>
#include "../CGLA/Vec2f.h"
#include "../CGLA/Vec3f.h"
namespace LinAlg
{
template <class T> class CMatrixType;
/*!
\brief The Vector type.
This vector teplate is one of the basic linear algebra types. In
principle it an overloaded Array of type T. The typedef Vector with
T set to double
typedef CVectorType<double> CVector;
is the delclaration intended to be used as the matrix type outside
the this and related files. The reson for making a template is
twofold, first it allows for an esay change of precision in this
linear algebre package. Secondly it allows for other Vector types
in special cases.
The pointer to the data area can be obtained by operator [] (int i)
with i=0, e.g.
CVector A;
T* pData=A[0];
will make pData point to the data.
\see LapackFunc.h
\see CMatrixType
\see Additional vector operators (located in this file Vector.h)
\see CMatrix
\see CVector
\author Henrik Aanæs
\version Aug 2001
*/
template <class T>
class CVectorType
{
friend class CMatrixType<T>;
private:
///The number of elements in the vector
int nElems;
///The pointer to the vector data
T*Data;
///Sets all the elements in the vector to a scalar
void SetScalar(const T& Scalar)
{
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
*Itt=Scalar;
++Itt;
}
};
///Frees the used memory
void CleanUp(void) {if(Data!=NULL) delete [] Data;};
///Allocate the needed memory. Note that nElems should be initialized correctly first.
void Allocate(void) { Data= new T[nElems];};
public:
/// \name Constructurs and Destructors
//@{
///Creats a vector a size 0.
CVectorType<T>():nElems(0),Data(NULL) {};
///Creates a vector of the specified Length
explicit CVectorType<T>(const int Length): nElems(Length) {Allocate();}
///Creates a vector of the specified Length, and sets all the values to a scalar.
CVectorType<T>(const int Length,const T& Scalar): nElems(Length) {Allocate();SetScalar(Scalar);}
///Copy constructor
CVectorType<T>(const CVectorType<T>& Rhs): nElems(Rhs.nElems)
{
Allocate();
memcpy(Data,Rhs.Data,nElems*sizeof(T));
}
///Copy constructor from Vec2Type
template <class TT, class V, unsigned int N>
CVectorType<T>(const CGLA::ArithVec<TT,V,N>& Rhs):nElems(N)
{
Allocate();
for(int i=0;i<N;++i)
Data[i]=Rhs[i];
}
///
virtual ~CVectorType<T>(){ CleanUp();};
//@}
/*!\name Asignment operators.
Note that the vector is resized if it does not have the correct size.
*/
//@{
CVectorType<T>& operator=(const T& Rhs) {SetScalar(Rhs);return *this;}
template <class TT, class V, unsigned int N>
CVectorType<T>& operator=(const CGLA::ArithVec<TT,V,N>& Rhs)
{
Resize(N);
for(int i=0;i<N;++i)
Data[i]=Rhs[i];
}
CVectorType<T>& operator=(const CVectorType<T>& Rhs)
{
Resize(Rhs.nElems);
memcpy(Data,Rhs.Data,nElems*sizeof(T));
return *this;
}
//@}
/// \name Dimension functions
//@{
///Returns the length of the vector.
const int Length(void) const {return nElems;}
///Realocates memory IF the vector does not already hve the correct size.
void Resize(const int Length)
{
if(Length!=nElems)
{
CleanUp();
nElems=Length;
Data= new T[nElems];
}
}
//@}
/*!
\name Acces functions and operators.
The [] operators are the ones intaended for usual use. The get
and set functions are added to allow for genral vector function
templates.
*/
//@{
const T& get(const int i)const
{
assert(i>=0);
assert(i<nElems);
return Data[i];
}
void set(const int i,const T& val)
{
assert(i>=0);
assert(i<nElems);
Data[i]=val;
}
T& operator[](const int i)
{
assert(i>=0);
assert(i<nElems);
return Data[i];
}
const T& operator[](const int i) const
{
assert(i>=0);
assert(i<nElems);
return Data[i];
}
//@}
/// \name aritmethic operators
//@{
CVectorType<T> operator+(const CVectorType<T>& Rhs) const {CVectorType<T>Ret(*this); return Ret+=Rhs;};
CVectorType<T> operator-(const CVectorType<T>& Rhs) const {CVectorType<T>Ret(*this); return Ret-=Rhs;};
CVectorType<T> operator+(const T& Rhs) const {CVectorType<T>Ret(*this); return Ret+=Rhs;};
CVectorType<T> operator-(const T& Rhs) const {CVectorType<T>Ret(*this); return Ret-=Rhs;};
CVectorType<T> operator*(const T& Rhs) const {CVectorType<T>Ret(*this); return Ret*=Rhs;};
CVectorType<T> operator/(const T& Rhs) const {CVectorType<T>Ret(*this); return Ret/=Rhs;};
CVectorType<T>& operator+=(const CVectorType<T>& Rhs)
{
assert(nElems==Rhs.nElems);
T* IttRhs=Rhs.Data;
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
(*Itt)+=(*IttRhs);
++Itt;
++IttRhs;
}
return *this;
}
CVectorType<T>& operator-=(const CVectorType<T>& Rhs)
{
assert(nElems==Rhs.nElems);
T* IttRhs=Rhs.Data;
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
(*Itt)-=(*IttRhs);
++Itt;
++IttRhs;
}
return *this;
}
CVectorType<T>& operator+=(const T& Rhs)
{
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
(*Itt)+=Rhs;
++Itt;
}
return *this;
}
CVectorType<T>& operator-=(const T& Rhs)
{
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
(*Itt)-=Rhs;
++Itt;
}
return *this;
}
CVectorType<T>& operator*=(const T& Rhs)
{
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
(*Itt)*=Rhs;
++Itt;
}
return *this;
}
CVectorType<T>& operator/=(const T& Rhs)
{
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
(*Itt)/=Rhs;
++Itt;
}
return *this;
}
T operator*(const CVectorType<T>& Rhs) const
{
assert(nElems==Rhs.nElems);
T Ret=0;
T* IttRhs=Rhs.Data;
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
Ret+=(*Itt)*(*IttRhs);
++Itt;
++IttRhs;
}
return Ret;
}
CVectorType<T> operator*(const CMatrixType<T>& Rhs) const
{
assert(nElems==Rhs.Rows());
CVectorType<T> Ret(Rhs.Cols(),0);
T* ThisItt=Data;
const T* RhsItt=Rhs.Data;
const T* Stop=&(Rhs.Data[Rhs.nElems]);
T* RetItt;
while(RhsItt!=Stop)
{
RetItt=Ret.Data;
for(int cCol=Rhs.Cols()-1;cCol>=0;--cCol)
{
(*RetItt)+=(*ThisItt)*(*RhsItt);
++RetItt;
++RhsItt;
}
++ThisItt;
}
return Ret;
}
//@}
/// \name Norms
//@{
const T Norm(void) const {return sqrt((*this)*(*this));}
const T NormMax(void) const
{
T Ret=0;
T Abs;
const T* Itt=Data;
const T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
Abs=(*Itt)>0?(*Itt):-(*Itt);
if(Ret<Abs)
Ret=Abs;
++Itt;
}
return Ret;
}
//@}
/// Sum of all the elements in the vector
const T Sum(void) const
{
T Ret=0;
const T* Itt=Data;
const T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
Ret+=(*Itt);
++Itt;
}
}
/*!
\name Elementwise functions.
Functions the perform some elementary operation on each
of the elements of the vector.
*/
//@{
///The elements of the vector squared. Equvivalent to MatLAb's .^2
void ElemSqr(void)
{
T* Itt=Data;
T* Stop=&(Data[nElems]);
while(Itt!=Stop)
{
(*Itt)*=(*Itt);
++Itt;
}
}
};
/*!
\name Additional vector operators
These are operators heavily associated with CVectorType, but not included
in the class definition it self.
*/
//@{
template<class T>
inline CVectorType<T> operator+(const T& Lhs,const CVectorType<T>&Rhs )
{
return Rhs+Lhs;
}
template<class T>
inline CVectorType<T> operator*(const T& Lhs,const CVectorType<T>&Rhs )
{
return Rhs*Lhs;
}
template <class T>
std::ostream& operator<<(std::ostream &s, const CVectorType<T> &a)
{
int nElems=a.Length();
for (int cElem=0; cElem<nElems; cElem++)
{
s << a[cElem] << " ";
}
s << "\n";
return s;
}
template <class T>
std::istream& operator>>(std::istream &s, CVectorType<T> &a)
{
int nElems;
s >> nElems;
if ( nElems!=a.Length())
a.Resize(nElems);
for (int cElem=0; cElem<a.Length();cElem++)
{
s >> a[cElem];
}
return s;
}
//@}
/// The Vector annotation intended for use.
typedef CVectorType<double> CVector;
}
#endif // !defined(VECTOR_H__HAA_AGUST_2001)