// -*- 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 <stdlib.h>
#include <iostream.h>
#include "fatalerror.h"
#include "vec.h"
// construct a null vector
template <class TYPE>
Vec<TYPE>::Vec() : data(0), logicalsize(0), allocatedsize(0), blocksize(1) {}
// construct a vector of length n
template <class TYPE>
Vec<TYPE>::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 <class TYPE>
Vec<TYPE>::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 <class TYPE>
Vec<TYPE>::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<logicalsize; i++)
data[i] = x;
}
}
// construct initialized vector of length n, all data = x, blocksize b
template <class TYPE>
Vec<TYPE>::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<logicalsize; i++)
data[i] = x;
}
}
// destruct a vector
template <class TYPE>
Vec<TYPE>::~Vec() {
delete [] data;
}
// copy constructor
template <class TYPE>
Vec<TYPE>::Vec(const Vec<TYPE> &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 <class TYPE>
const Vec<TYPE>& Vec<TYPE>::operator=(const Vec<TYPE> &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 <class TYPE>
TYPE& Vec<TYPE>::operator[](const int n) const {
return data[n];
}
/* inlined
// get size
template <class TYPE>
int Vec<TYPE>::capacity() {
return logicalsize;
}
*/
// change size
#include <math.h> // for ceil
template <class TYPE>
void Vec<TYPE>::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<logicalsize; i++)
newdata[i] = data[i];
logicalsize = newsize;
delete [] data;
data = newdata;
}
template <class TYPE>
void Vec<TYPE>::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<newsize; i++)
data[i] = x;
// change size
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();
}
// copy old data
int i;
for(i=0; i<logicalsize; i++)
newdata[i] = data[i];
// initialize new data
for(i=logicalsize; i<newsize; i++)
newdata[i] = x;
logicalsize = newsize;
delete [] data;
data = newdata;
}
template <class TYPE>
int Vec<TYPE>::grow(const int n) {
int newspot = logicalsize;
resize(logicalsize + n);
return newspot;
}
template <class TYPE>
int Vec<TYPE>::grow(const int n, const TYPE &x) {
int newspot = logicalsize;
resize(logicalsize + n, x);
return newspot;
}
template <class TYPE>
int Vec<TYPE>::remove(const TYPE &x) {
for(int i=0; i<logicalsize; i++) {
if(x == data[i]) {
for(int j=i+1; j<logicalsize; j++)
data[j-1] = data[j];
logicalsize--;
return 1;
}
}
return 0;
}
template <class TYPE>
int Vec<TYPE>::remove(const TYPE &x, int (*compare)(const TYPE&, const TYPE&)) {
for(int i=0; i<logicalsize; i++) {
if(compare(data[i], x)) {
for(int j=i+1; j<logicalsize; j++)
data[j-1] = data[j];
logicalsize--;
return 1;
}
}
return 0;
}
// remove *all* members for which f(data[i]) == 1
template <class TYPE>
int Vec<TYPE>::remove_conditional(int (*f)(const TYPE&)) {
int j=0; // next available spot
int oldsize = logicalsize;
for(int i=0; i<logicalsize; i++) {
if(!f(data[i])) {
data[j] = data[i];
j++;
}
}
logicalsize = j;
return oldsize - logicalsize;
}
template <class TYPE>
int Vec<TYPE>::remove_conditional(int (*f)(TYPE&)) {
int j=0; // next available spot
int oldsize = logicalsize;
for(int i=0; i<logicalsize; i++) {
if(!f(data[i])) {
data[j] = data[i];
j++;
}
}
logicalsize = j;
return oldsize - logicalsize;
}
// remove all members for which flag==1
template <class TYPE>
int Vec<TYPE>::remove_conditional(const Vec<int> &flag) {
int j=0;
int oldsize = logicalsize;
for(int i=0; i<logicalsize; i++) {
if(!flag[i]) {
data[j] = data[i];
j++;
}
}
logicalsize = j;
return oldsize - logicalsize;
}
template <class TYPE>
void Vec<TYPE>::remove_all(const TYPE &x) {
int j=0;
for(int i=0; i<logicalsize; i++) {
if(!(data[i] == x)) { // don't use !=, since TYPE might not have it
data[j] = data[i];
j++;
}
}
logicalsize = j;
}
template <class TYPE>
void Vec<TYPE>::trim(const TYPE &x) {
for(int i=logicalsize; i>=0; i--) {
if(x == data[i]) {
for(int j=i+1; j<logicalsize; j++)
data[j-1] = data[j];
logicalsize--;
return;
}
}
}
template <class TYPE>
void Vec<TYPE>::replace(const TYPE &a, const TYPE &b) {
for(int i=0; i<logicalsize; i++)
if(data[i] == a) {
data[i] = b;
return;
}
}
// free space without deleting Vec
template <class TYPE>
void Vec<TYPE>::smash() {
setphysicalsize(0);
}
template <class TYPE>
void Vec<TYPE>::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 <class TYPE>
void Vec<TYPE>::copydata(TYPE *dd) {
for(int i=0; i<logicalsize; i++)
data[i] = dd[i];
}
// for printing
template <class TYPE>
ostream& operator<<(ostream &s, const Vec<TYPE> &v) {
for(int i=0; i<v.logicalsize; i++)
s << v[i] << " ";
return s;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1