Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
447 lines (362 sloc) 10.8 KB
// ********************************
// Classes for vectors and matrices
//
// RDB 7/24/95
// ********************************
#pragma once
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstdarg>
using namespace std;
#define DEBUG 0
// *******
// TVector
// *******
// The TVector class declaration
template<class EltType>
class TVector {
public:
// Constructors
TVector(void);
TVector(int LowerBound, int UpperBound);
TVector(TVector<EltType> &v);
// The destructor
~TVector();
// Accessors
int Size(void) {return ub - lb + 1;};
void SetSize(int NewSize) {SetBounds(lb,NewSize+lb-1);};
int LowerBound(void) {return lb;};
void SetLowerBound(int NewLB) {SetBounds(NewLB,ub);};
int UpperBound(void) {return ub;};
void SetUpperBound(int NewUB) {SetBounds(lb,NewUB);};
void SetBounds(int NewLB, int NewUB);
// Other stuff
void FillContents(EltType value);
void InitializeContents(EltType v1,...);
// Vector i/o
void BinaryWriteVector(ofstream& bofs);
void BinaryReadVector(ifstream& binfs);
// Overloaded operators
EltType &operator[](int index)
{
#if !DEBUG
return Vector[index];
#else
return (*this)(index);
#endif
};
inline EltType &operator()(int index);
inline TVector<EltType> &operator=(TVector<EltType> &v);
protected:
int lb, ub;
EltType *Vector;
};
// The default constructor
template<class EltType>
TVector<EltType>::TVector(void)
{
lb = 1; ub = 0;
}
// The standard constructor
template<class EltType>
TVector<EltType>::TVector(int LB, int UB)
{
lb = 1; ub = 0;
SetBounds(LB,UB);
}
// The copy constructor
template<class EltType>
TVector<EltType>::TVector(TVector<EltType> &v)
{
lb = 1; ub = 0;
SetBounds(v.LowerBound(),v.UpperBound());
for (int i = lb; i <= ub; i++)
Vector[i] = v[i];
}
// The destructor
template<class EltType>
TVector<EltType>::~TVector(void)
{
//cout << "destroying " << (*this)(1) << endl;
SetSize(0);
}
// Set the bounds of a TVector, reallocating space as necessary and
// preserving as much of the previous contents as possible
template<class EltType>
void TVector<EltType>::SetBounds(int newlb, int newub)
{
// Only do it if we have to
if (lb == newlb && ub == newub) return;
// Save the old info and init the new
EltType *OldVector = Vector;
int oldlb = lb, oldub = ub, oldlen = ub - lb + 1, len = newub - newlb + 1;
lb = newlb; ub = newub;
// No negative length vectors allowed!
if (len < 0) {
cerr << "Attempt to allocate a negative length TVector\n";
exit(0);
}
// Allocate the new storage and copy as much of the old info as possible
if (len != 0) {
Vector = new EltType[len] - lb;
if (oldlen != 0)
for (int i = oldlb, j = lb; i <= oldub && j <= ub; i++,j++)
Vector[j] = OldVector[i];
}
// Recover the old storage
if (oldlen != 0) delete [] (OldVector + oldlb);
}
// Fill a TVector with the given value
template<class EltType>
void TVector<EltType>::FillContents(EltType value)
{
for (int i = lb; i <= ub; i++)
Vector[i] = value;
}
// Initialize a TVector with given contents
template<class EltType>
void TVector<EltType>::InitializeContents(EltType v1,...)
{
va_list ap;
if (Size() == 0) return;
Vector[lb] = v1;
va_start(ap,v1);
for (int i = lb+1; i <= ub; i++)
Vector[i] = va_arg(ap,EltType);
va_end(ap);
}
// Overload the () operator to provide safe indexing
template<class EltType>
inline EltType &TVector<EltType>::operator()(int index)
{
if (index < lb || index > ub)
{
cerr << "Vector index " << index << " out of bounds\n";
exit(0);
}
return Vector[index];
}
// Overload the = operator to copy one TVector to another
template<class EltType>
inline TVector<EltType> &TVector<EltType>::operator=(TVector<EltType> &v)
{
SetBounds(v.LowerBound(),v.UpperBound());
for (int i = lb; i <= ub; i++)
Vector[i] = v[i];
return *this;
}
// Overload the stream insertion operator to recognize a TVector
template<class EltType>
ostream& operator<<(ostream& os, TVector<EltType>& v)
{
for (int i = v.LowerBound(); i < v.UpperBound(); i++)
os << v[i] << " ";
if (v.Size() > 0) os << v[v.UpperBound()];
return os;
}
// Write and read a TVector in binary
// (Thanks to Chad Seys)
template<class EltType>
void TVector<EltType>::BinaryWriteVector(ofstream& bofs)
{
int thisSize = ub-lb+1;
bofs.write((const char*) &(lb), sizeof(lb));
bofs.write((const char*) &(ub), sizeof(ub));
for (int i = lb; i < ub; i++) {
bofs.write((const char *) &(Vector[i]), sizeof(Vector[i]));
}
if (thisSize > 0) {
bofs.write((const char *) &(Vector[ub]), sizeof(Vector[ub]));
}
}
template<class EltType>
void TVector<EltType>::BinaryReadVector(ifstream& bifs)
{
int LB;
int UB;
bifs.read((char *) &(LB), sizeof(LB));
bifs.read((char *) &(UB), sizeof(UB));
SetLowerBound(LB);
SetUpperBound(UB);
for (int i = LB; i <= UB; ++i) {
bifs.read((char *) &(Vector[i]),sizeof(Vector[i]));
}
}
// *******
// TMatrix
// *******
// The TMatrix class declaration
template<class EltType>
class TMatrix {
public:
// Constructors
TMatrix(void);
TMatrix(int RowLowerBound, int RowUpperBound, int ColumnLowerBound, int ColumnUpperBound);
TMatrix(TMatrix<EltType> &m);
// The destructor
~TMatrix();
// Accessors
int RowSize(void) {return rowlen;};
void SetRowSize(int NewSize) {SetBounds(lb1,lb1+NewSize-1,lb2,ub2);};
int ColumnSize(void) {return collen;};
void SetColumnSize(int NewSize) {SetBounds(lb1,ub1,lb2,lb2+NewSize-1);};
void SetSize(int NewRowSize,int NewColSize)
{SetBounds(lb1,lb1+NewRowSize-1,lb2,lb2+NewColSize-1);};
int RowLowerBound(void) {return lb1;};
void SetRowLowerBound(int newlb1) {SetBounds(newlb1,ub1,lb2,ub2);};
int RowUpperBound(void) {return ub1;};
void SetRowUpperBound(int newub1) {SetBounds(lb1,newub1,lb2,ub2);};
int ColumnLowerBound(void) {return lb2;};
void SetColumnLowerBound(int newlb2) {SetBounds(lb1,ub1,newlb2,ub2);};
int ColumnUpperBound(void) {return ub2;};
void SetColumnUpperBound(int newub2) {SetBounds(lb1,ub1,lb2,newub2);};
void SetBounds(int newlb1, int newub1, int newlb2, int newub2);
// Overloaded operators
EltType* operator[](int index)
{
#if !DEBUG
return Matrix[index];
#else
if (index < lb1 || index > ub1)
{
cerr << "Matrix index " << index << " out of bounds\n";
exit(0);
}
return Matrix[index];
#endif
};
inline EltType &operator()(int i,int j);
inline TMatrix<EltType> &operator=(TMatrix<EltType> &m);
// Other stuff
void FillContents(EltType x);
void InitializeContents(EltType v1,...);
protected:
int lb1, ub1, lb2, ub2, collen, rowlen;
EltType **Matrix;
};
// The default constructor
template<class EltType>
TMatrix<EltType>::TMatrix(void)
{
lb1 = lb2 = 1; ub1 = ub2 = 0; collen = 0; rowlen = 0;
}
// The standard constructor
template<class EltType>
TMatrix<EltType>::TMatrix(int RowLowerBound, int RowUpperBound,
int ColumnLowerBound, int ColumnUpperBound)
{
lb1 = lb2 = 1; ub1 = ub2 = 0; collen = 0; rowlen = 0;
SetBounds(RowLowerBound,RowUpperBound,ColumnLowerBound,ColumnUpperBound);
}
// The copy constructor
template<class EltType>
TMatrix<EltType>::TMatrix(TMatrix<EltType> &m)
{
lb1 = lb2 = 1; ub1 = ub2 = 0; collen = 0; rowlen = 0;
SetBounds(m.RowLowerBound(),m.RowUpperBound(),m.ColumnLowerBound(),m.ColumnUpperBound());
for (int i = lb1; i <= ub1; i++)
for (int j = lb2; j <= ub2; j++)
Matrix[i][j] = m[i][j];
}
// The destructor
template<class EltType>
TMatrix<EltType>::~TMatrix()
{
SetSize(0,0);
//cout << "destroying " << this << endl;
}
// Set the bounds of a TMatrix to the given values, reallocating space as necessary.
// Note that, unlike for TVectors, we do not try to preserve the previous contents.
template<class EltType>
void TMatrix<EltType>::SetBounds(int newlb1, int newub1, int newlb2, int newub2)
{
// Only do it if we have to
if (newlb1 == lb1 && newub1 == ub1 && newlb2 == lb2 && newub2 == ub2) return;
// If storage is currently allocated, reclaim it
if (collen != 0) {
if (rowlen != 0)
for (int i = lb1; i <= ub1; i++)
delete (Matrix[i] + lb2);
delete [] (Matrix + lb1);
}
// Save the new bounds info
lb1 = newlb1; ub1 = newub1; lb2 = newlb2; ub2 = newub2;
collen = ub1 - lb1 + 1; rowlen = ub2 - lb2 + 1;
// No negative sizes allowed!
if (collen < 0 || rowlen < 0) {
cerr << "Attempt to allocate a negative sized TMatrix\n";
exit(0);
}
// If new storage is needed, allocate it
if (collen != 0) {
Matrix = new EltType*[collen] - lb1;
if (rowlen != 0)
for (int i = lb1; i <= ub1; i++)
Matrix[i] = new EltType[rowlen] - lb2;
else
for (int i = lb1; i <= ub1; i++)
Matrix[i] = NULL;
}
}
// Fill a TMatrix with the given value
template<class EltType>
void TMatrix<EltType>::FillContents(EltType x)
{
for (int i = lb1; i <= ub1; i++)
for (int j = lb2; j <= ub2; j++)
Matrix[i][j] = x;
}
// Initialize a TMatrix with given contents
template<class EltType>
void TMatrix<EltType>::InitializeContents(EltType v1,...)
{
va_list ap;
if (rowlen == 0 || collen == 0) return;
Matrix[lb1][lb2] = v1;
va_start(ap,v1);
for (int j = lb2+1; j <= ub2; j++)
Matrix[lb1][j] = va_arg(ap,EltType);
for (int i = lb1+1; i <= ub1; i++)
for (int j = lb2; j <= ub2; j++)
Matrix[i][j] = va_arg(ap,EltType);
va_end(ap);
}
// Overload the () operator to provide safe indexing
template<class EltType>
inline EltType &TMatrix<EltType>::operator()(int i,int j)
{
if (i < lb1 || i > ub1 || j < lb2 || j > ub2)
{
cerr << "Matrix indices (" << i << "," << j << ") out of bounds\n";
exit(0);
}
return Matrix[i][j];
}
// Overload the = operator to copy one TMatrix to another
template<class EltType>
inline TMatrix<EltType> &TMatrix<EltType>::operator=(TMatrix<EltType> &m)
{
SetBounds(m.RowLowerBound(),m.RowUpperBound(),m.ColumnLowerBound(),m.ColumnUpperBound());
for (int i = lb1; i <= ub1; i++)
for (int j = lb2; j <= ub2; j++)
Matrix[i][j] = m[i][j];
return *this;
}
// Overload the stream insertion operator to recognize a TMatrix
template<class EltType>
ostream& operator<<(ostream& os, TMatrix<EltType> &m)
{
int i,j;
for (i = m.RowLowerBound(); i < m.RowUpperBound(); i++) {
for (j = m.ColumnLowerBound(); j < m.ColumnUpperBound(); j++)
os << m[i][j] << " ";
if (m.ColumnSize() > 0) os << m[i][m.ColumnUpperBound()] << endl;
}
if (m.RowSize() > 0) {
for (j = m.ColumnLowerBound(); j < m.ColumnUpperBound(); j++)
os << m[m.RowUpperBound()][j] << " ";
if (m.ColumnSize() > 0) os << m[m.RowUpperBound()][m.ColumnUpperBound()];
}
return os;
}
You can’t perform that action at this time.