/*************************************************************************** This is part of the evolver toolkit for exploring genetic progamming. Copyright (C) 1996 Benjamin Bennett and Yeasah G. Pell This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Contact information: Benjamin Bennett and Yeasah G. Pell *************************************************************************/ #include "generic.H" // constructor GIntArray::GIntArray() { num_arrays++; // start with nothing vsize = 0; size = 0; array = NULL; } // destructor GIntArray::~GIntArray() { num_arrays--; // free the array SetSize(0); } // sets the size of the array to 'asize' elements int GIntArray::SetSize(int asize) { int chunks, retval; // make sure they didn't slip us a bogus value if(asize >= 0) { // set the new size size = asize; // calculate the new size in chunks chunks = asize / ARRAY_CHUNK + (asize % ARRAY_CHUNK ? 1 : 0); // change the array by the difference in sizes retval = ChangeSize(chunks-vsize); if(asize == 0 && array != NULL) cerr << "SetSize(0): Didn't free array" << endl; return retval; } else return -1; } // retrieves the current size of the array, in elements int GIntArray::GetSize() { return size; } // appends a value to the end of the array, returns index int GIntArray::Append(int t) { (*this)[size] = t; return size-1; } // return the last value in the array int &GIntArray::Last() { int index = size; // make sure there are elements in the list if(index > 0) index--; else cerr << "GArray::Last: array is empty" << endl; return array[index]; } // shrink the array by one int GIntArray::Pop() { int temp = -1; // make sure there are elements in the list if(size > 0) { temp = array[size-1]; SetSize(size-1); } else cerr << "GArray::Pop: array is empty" << endl; return temp; } // array operator -- hole-proof int &GIntArray::operator[](int index) { // array references must be non-negative if (index < 0) { cerr << "GArray::operator[]: Bad Array Index:" << index << endl; exit(-1); } // if index is past end of array, grow array to fit if (index == size) SetSize(size + 1); else if(index > size) { cerr << "GArray::operator[]: Attempt to create hole" << endl; exit(-1); } // return the actual value return array[index]; } // overloaded assignment operator for array (copy) GIntArray &GIntArray::operator=(GIntArray &input) { // free the array this->SetSize(0); this->vsize = input.vsize; this->size = input.size; this->array = (int *)debug_malloc(this->vsize * ARRAY_CHUNK * sizeof(int)); if(this->array == NULL) if (array == NULL) { cerr << "Array creation failed\n"; exit(1); } memcpy(this->array, input.array, this->size * sizeof(int)); return *this; } // private member function to change array size // this is where most of the work gets done // change gives +/- array size change in chunks of ARRAY_CHUNK elements // NOTE: This member function doesn't update size, only vsize. int GIntArray::ChangeSize(int change) { int *temp = NULL; // set the new vsize vsize += change; // if change is positive, we should grow the array by 'change' chunks if(change > 0) { // if we already have an array, change it's size if(array != NULL) { // change the size of the array array = (int *) realloc((void *) array, vsize * ARRAY_CHUNK * sizeof(int)); if (array == NULL) { perror("GArray::ChangeSize"); exit(-1); } } // starting from scratch, just allocate an array else { array = (int *) debug_malloc(vsize * ARRAY_CHUNK * sizeof(int)); if (array == NULL) { perror("GArray::GArray"); exit(-1); } } } // if change is negative, we should shrink the array by 'change' chunks else if(change < 0) { // resize the array only if there is anything left if(vsize > 0) { // allocate a new, smaller array temp = (int *) debug_malloc(vsize * ARRAY_CHUNK * sizeof(int)); if (temp == NULL) { perror("GArray::ChangeSize"); exit(-1); } // copy some of the old array into the new memcpy((void *) temp, (void *) array, size * sizeof(int)); } // free the old array, and replace with new debug_free((void *)array); array = temp; } #ifdef DEBUG cerr << "(Array changed size by " << change * ARRAY_CHUNK << " entries, new vsize " << vsize << ")" << endl; #endif // DEBUG return 0; } // sort the array // compar is the function to use to perform the comparison void GIntArray::Sort(int (*compar)(const void *, const void *)) { qsort(array, size, sizeof(int), compar); }