// -*- C++ -*- // $RCSfile: vec.C,v $ // $Revision: 1.9 $ // $Author: langer $ // $Date: 2000/11/02 21:46:23 $ /* This software was produced by NIST, an agency of the U.S. government, * and by statute is not subject to copyright in the United States. * Recipients of this software assume all responsibilities associated * with its operation, modification and maintenance. However, to * facilitate maintenance we ask that before distributing modifed * versions of this software, you first contact the authors at * oof_manager@ctcms.nist.gov. */ // a simple vector template class // doesn't work unless TYPE has a null constructor and an operator=(). // doesn't work if TYPE requires a destructor #ifndef VEC_C #define VEC_C #include #include #include "fatalerror.h" #include "vec.h" // construct a null vector template Vec::Vec() : data(0), logicalsize(0), allocatedsize(0), blocksize(1) {} // construct a vector of length n template Vec::Vec(int n) : data(0), logicalsize(n), allocatedsize(n), blocksize(1) { if(n > 0) { data = new TYPE[n]; if(!data) { cerr << "Vec: failed to allocate vec of " << n << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception } } } // construct a vector of length n, blocksize b template Vec::Vec(int n, BlockSize b) : data(0), logicalsize(n), allocatedsize(n), blocksize(b) { if(n > 0) { data = new TYPE[n]; if(!data) { cerr << "Vec: failed to allocate vec of " << n << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception } } } // construct initialized vector of length n, all data = x, blocksize 1 template Vec::Vec(int n, TYPE x) : data(0), logicalsize(n), allocatedsize(n), blocksize(1) { if(n > 0) { data = new TYPE[n]; if(!data) { cerr << "Vec: failed to allocate vec of " << n << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception } for(int i=0; i Vec::Vec(int n, TYPE x, BlockSize b) : data(0), logicalsize(n), allocatedsize(n), blocksize(b) { if(n > 0) { data = new TYPE[n]; if(!data) { cerr << "Vec: failed to allocate vec of " << n << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception } for(int i=0; i Vec::~Vec() { delete [] data; } // copy constructor template Vec::Vec(const Vec &v) : data(new TYPE [v.logicalsize]), logicalsize(v.logicalsize), allocatedsize(v.logicalsize), blocksize(v.blocksize) { if(v.logicalsize > 0 && !data) { cerr << "Vec: failed to copy vec of " << v.logicalsize << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception } copydata(v.data); } // assignment operator template const Vec& Vec::operator=(const Vec &v) { if(&v != this) { delete [] data; logicalsize = allocatedsize = v.logicalsize; blocksize = v.blocksize; data = new TYPE [logicalsize]; if(logicalsize > 0 && !data) { cerr << "Vec: failed to allocate vec of " << logicalsize << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception } copydata(v.data); } return *this; } // access template TYPE& Vec::operator[](const int n) const { return data[n]; } /* inlined // get size template int Vec::capacity() { return logicalsize; } */ // change size #include // for ceil template void Vec::resize(const int newsize) { if(newsize == logicalsize) return; // no change if(newsize < logicalsize) { // shrinking logicalsize = newsize; // here is where extra elements should be destructed. See p 173 // R. Murray's "C++ Strategies and Tactics". The right thing to do // is to copy the first newsize elements of data and delete all of it. return; } if(newsize <= allocatedsize) { // growing into preallocated space logicalsize = newsize; return; } // growing beyond preallocated space int nblocks = (int) ceil(((double)(newsize - allocatedsize))/blocksize.bs); allocatedsize += nblocks*blocksize.bs; TYPE *newdata = new TYPE [allocatedsize]; if(allocatedsize > 0 && !newdata) { cerr << "Vec: failed to resize vec to " << allocatedsize << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception } for(int i=0; i void Vec::resize(const int newsize, const TYPE &x) { if(newsize == logicalsize) return; // no change if(newsize < logicalsize) { // shrinking logicalsize = newsize; // here is where extra elements should be destructed. See p 173 // R. Murray's "C++ Strategies and Tactics". The right thing to do // is to copy the first newsize elements of data and delete all of it. return; } if(newsize <= allocatedsize) { // growing into preallocated space // initialize "new" elements for(int i=logicalsize; i 0 && !newdata) { cerr << "Vec: failed to resize vec to " << allocatedsize << "objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); } // copy old data int i; for(i=0; i int Vec::grow(const int n) { int newspot = logicalsize; resize(logicalsize + n); return newspot; } template int Vec::grow(const int n, const TYPE &x) { int newspot = logicalsize; resize(logicalsize + n, x); return newspot; } template int Vec::remove(const TYPE &x) { for(int i=0; i int Vec::remove(const TYPE &x, int (*compare)(const TYPE&, const TYPE&)) { for(int i=0; i int Vec::remove_conditional(int (*f)(const TYPE&)) { int j=0; // next available spot int oldsize = logicalsize; for(int i=0; i int Vec::remove_conditional(int (*f)(TYPE&)) { int j=0; // next available spot int oldsize = logicalsize; for(int i=0; i int Vec::remove_conditional(const Vec &flag) { int j=0; int oldsize = logicalsize; for(int i=0; i void Vec::remove_all(const TYPE &x) { int j=0; for(int i=0; i void Vec::trim(const TYPE &x) { for(int i=logicalsize; i>=0; i--) { if(x == data[i]) { for(int j=i+1; j void Vec::replace(const TYPE &a, const TYPE &b) { for(int i=0; i void Vec::smash() { setphysicalsize(0); } template void Vec::setphysicalsize(int n) { allocatedsize = n; logicalsize = 0; delete [] data; data = new TYPE [allocatedsize]; if(allocatedsize > 0 && !data) { cerr << "Vec: Failed to allocate space for " << allocatedsize << " objects of size " << sizeof(TYPE) << "!" << endl; fatalerror(); // should throw an exception here? } } // private copying function template void Vec::copydata(TYPE *dd) { for(int i=0; i ostream& operator<<(ostream &s, const Vec &v) { for(int i=0; i