/*-------------------------------------------------------------------------- @COPYRIGHT : Copyright 1996, Alex P. Zijdenbos, McConnell Brain Imaging Centre, Montreal Neurological Institute, McGill University. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies. The author and McGill University make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ---------------------------------------------------------------------------- $RCSfile: SimpleArray.h,v $ $Revision: 1.5 $ $Author: bert $ $Date: 2004/12/08 17:05:18 $ $State: Exp $ --------------------------------------------------------------------------*/ #ifndef SIMPLE_ARRAY_H #define SIMPLE_ARRAY_H #include "trivials.h" #include "Array.h" /******************************************************************** * SimpleArray class * * This class is derived from Array. It extends the functionality of * Array with various mathematical operations; as a result, these * operations must be defined for the objects stored in the array. * SimpleArray is therefore most suitable for simple types. ********************************************************************/ class ValueMap; template class SimpleArray; typedef SimpleArray BoolArray; typedef SimpleArray IntArray; typedef SimpleArray UnsignedArray; typedef SimpleArray DblArray; template struct IndexStruct { Type element; unsigned index; static int compareAscending(const void *struct1, const void *struct2); static int compareDescending(const void *struct1, const void *struct2); }; template class SimpleArray : public Array { public: static int compareAscending(const void *, const void *); static int compareDescending(const void *, const void *); static unsigned _rangeErrorCount; // Manager functions SimpleArray(unsigned sz = DEFAULT_SIZE) : Array(sz) {} SimpleArray(Type value, unsigned sz) : Array(value, sz) {} SimpleArray(const Type *init, unsigned nElements) : Array(init, nElements) {} SimpleArray(const Array& array) : Array(array) {} SimpleArray(const SimpleArray& array) : Array(array) {} SimpleArray(Type minVal, double step, Type maxVal); virtual ~SimpleArray() {} // Binary I/O functions std::ostream& write(std::ostream& os) const { saveBinary(os); return os; } virtual std::ostream& saveBinary(std::ostream&, unsigned n = 0, unsigned start = 0) const; std::istream& read(std::istream& is) { loadBinary(is); return is; } virtual std::istream& loadBinary(std::istream&, unsigned n = 0, unsigned start = 0); // ASCII I/O functions std::ostream& print(std::ostream& os) const { saveAscii(os); return os; } virtual std::ostream& saveAscii(std::ostream&, unsigned n = 0, unsigned start = 0) const; std::istream& scan(std::istream& is) { loadAscii(is); return is; } virtual std::istream& loadAscii(std::istream&, unsigned n = 0, unsigned start = 0); // Matlab I/O functions #ifdef HAVE_MATLAB virtual Boolean saveMatlab(const char *fileName, const char *varName = "A", const char *option = "u") const; #endif // Get functions SimpleArray operator () (unsigned nElements) const; // Sub-array (first nElements) SimpleArray operator () (unsigned start, unsigned end) const; // Sub-array SimpleArray operator () (const BoolArray& boolArray) const; // Return an array containing only the elements for which boolArray is TRUE SimpleArray operator () (const UnsignedArray& indices) const; // Return an array containing only the elements with indices listed in Boolean contains(Type value) const; Boolean contains(Type value, unsigned start, unsigned end) const; Boolean containsOnly(Type value) const; Boolean containsOnly(Type value, unsigned start, unsigned end) const; // Total number of occurrences of object unsigned occurrencesOf(Type value) const { return occurrencesOf(value, 0, this->_size - 1); } // Total number of occurrences of object present in a range unsigned occurrencesOf(Type, unsigned start, unsigned end) const; // Index of first (dir > 0) or last (dir < 0) occurrence of value int indexOf(Type, int dir, unsigned start) const; int indexOf(Type value, int dir = 1) const { return indexOf(value, dir, (dir > 0) ? 0 : this->_size - 1); } int indexOf(Type value, unsigned start) const { return indexOf(value, 1, start); } void removeAll(Type value); // Remove all elements equal to void removeAllIn(Type floor, Type ceil, unsigned *N = 0); // Remove all elements in [floor, ceil] void removeAllNotIn(Type floor, Type ceil, unsigned *nBelow=0, unsigned *nAbove=0); // Remove all elements not in [floor, ceil] UnsignedArray indicesOf(Type value) const; // Return an array containing the (unique) elements common with SimpleArray common(const SimpleArray& array) const; // Removes all infinite and NaN values SimpleArray& prune(); // Fills array with uniformly distributed numbers SimpleArray& randuniform(double min = 0, double max = 1); // Fills array with normally distributed numbers SimpleArray& randnormal(double mean = 0, double std = 1); // Quicksort all elements virtual void qsort() { qsortAscending(); } virtual void qsort(int (*compare) (const void *, const void *)) { ::qsort(this->_contents, this->_size, sizeof(Type), compare); } virtual void qsortAscending() { ::qsort(this->_contents, this->_size, sizeof(Type), compareAscending); } virtual void qsortDescending() { ::qsort(this->_contents, this->_size, sizeof(Type), compareDescending); } virtual SimpleArray qsortIndexAscending() const; virtual SimpleArray qsortIndexDescending() const; Type min(unsigned *index = 0) const; Type max(unsigned *index = 0) const; void extrema(Type *min, Type *max) const; Type range(unsigned *minIndex = 0, unsigned *maxIndex = 0) const; double sum() const; double sum2() const; double mean() const { return sum()/double(this->_size); } double prod() const; double prod2() const; double var() const; double std() const { return ::sqrt(var()); } // Median functions. median() and medianVolatile() use the algorithm described // in Sections 8.1, 8.3, and 10.2 in Cormen, Leierson, and Rivest, // "Introduction to Algorithms" (aka the Big White Book). // The low median is returned in case the array has an even # elements. virtual Type median() const; virtual Type medianVolatile(); // Does not create a copy of the array, but changes it virtual Type mode(const Type binWidth) const; // Cumulative sum/prod2uct DblArray cumSum() const; DblArray cumProd() const; // Impose ceiling/floor to values void ceil(Type ceil); void floor(Type floor); // Boolean operations // Elementwise inequality/equality Boolean operator != (const SimpleArray&) const; Boolean operator == (const SimpleArray& array) const { return !((*this) != array); } BoolArray operator && (const SimpleArray& array) const; BoolArray operator || (const SimpleArray& array) const; BoolArray operator == (double value) const; BoolArray operator != (double value) const; BoolArray operator >= (double value) const; BoolArray operator > (double value) const; BoolArray operator <= (double value) const; BoolArray operator < (double value) const; BoolArray operator >= (const SimpleArray&) const; BoolArray operator > (const SimpleArray&) const; BoolArray operator <= (const SimpleArray&) const; BoolArray operator < (const SimpleArray&) const; // Arithmetic operations SimpleArray operator - () const { SimpleArray result(Type(0), this->_size); return result -= *this; } SimpleArray& operator += (Type); SimpleArray operator + (Type value) const { SimpleArray result(*this); return result += value; } SimpleArray& operator += (const SimpleArray&); SimpleArray operator + (const SimpleArray& array) const { SimpleArray result(*this); return result += array; } SimpleArray& operator -= (Type); SimpleArray operator - (Type value) const { SimpleArray result(*this); return result -= value; } SimpleArray& operator -= (const SimpleArray&); SimpleArray operator - (const SimpleArray& array) const { SimpleArray result(*this); return result -= array; } SimpleArray& operator *= (double); SimpleArray operator * (double value) const { SimpleArray result(*this); return result *= value; } SimpleArray& operator *= (const SimpleArray&); SimpleArray operator * (const SimpleArray& array) const { SimpleArray result(*this); return result *= array; } SimpleArray& operator /= (double value) { return (*this) *= 1.0/value; } SimpleArray operator / (double value) const { SimpleArray result(*this); return result /= value; } SimpleArray& operator /= (const SimpleArray&); SimpleArray operator / (const SimpleArray& array) const { SimpleArray result(*this); return result /= array; } SimpleArray abs() const; // Absolute value SimpleArray round(unsigned n = 0) const;// Round to n decimal places SimpleArray sqr() const; // Square of all elements SimpleArray sqrt() const; // Square root of all elements SimpleArray operator ^ (int power) const; // Raise all elements to // Note: all elements are cast to int first. Should be generalized!! SimpleArray ln() const; // Natural logarithm of all elements SimpleArray log() const; // Base-10 logarithm of all elements SimpleArray exp() const; // e^(all elements) SimpleArray exp10() const; // 10^(all elements) SimpleArray sample(unsigned maxN) const; SimpleArray applyElementWise(Type (*function) (Type)) const; SimpleArray map(const ValueMap& map) const; protected: // Median support functions Type _randomizedSelect(int p, int r, int i); int _randomizedPartition(int p, int r); int _partition(int p, int r); }; // Various non-member template functions // template unsigned size(const SimpleArray& array) { return array.size(); } template Type min(const SimpleArray& array) { return array.min(); } template Type max(const SimpleArray& array) { return array.max(); } template Type range(const SimpleArray& array, unsigned *minIndex = 0, unsigned *maxIndex = 0) { return array.range(minIndex, maxIndex); } template double sum(const SimpleArray& array) { return array.sum(); } template double sum2(const SimpleArray& array) { return array.sum2(); } template double mean(const SimpleArray& array) { return array.mean(); } template double prod(const SimpleArray& array) { return array.prod(); } template double prod2(const SimpleArray& array) { return array.prod2(); } template double var(const SimpleArray& array) { return array.var(); } template double stdev(const SimpleArray& array) { return array.std(); } template Type median(const SimpleArray& array) { return array.median(); } template Type medianVolatile(SimpleArray& array) { return array.medianVolatile(); } template Type mode(const SimpleArray& array, Type binWidth) { return array.mode(binWidth); } template SimpleArray abs(const SimpleArray& array) { return array.abs(); } template SimpleArray sqr(const SimpleArray& array) { return array.sqr(); } template SimpleArray sqrt(const SimpleArray& array) { return array.sqrt(); } template SimpleArray ln(const SimpleArray& array) { return array.ln(); } template SimpleArray log(const SimpleArray& array) { return array.log(); } template SimpleArray max(const SimpleArray& array1, const SimpleArray& array2); template SimpleArray min(const SimpleArray& array1, const SimpleArray& array2); template SimpleArray cumSum(const SimpleArray& array) { return array.cumSum(); } template SimpleArray cumProd(const SimpleArray& array) { return array.cumProd(); } template SimpleArray exp(const SimpleArray& array) { return ::exp(1.0) ^ array; } template SimpleArray exp10(const SimpleArray& array) { return 10^array; } template SimpleArray operator ^ (double base, const SimpleArray& array); // I/O template std::ostream& operator << (std::ostream& os, const SimpleArray& A) { return A.saveAscii(os); } template std::istream& operator >> (std::istream& is, SimpleArray& A) { return A.loadAscii(is); } // Type conversions template SimpleArray asIntArray(const SimpleArray&); template SimpleArray asFloatArray(const SimpleArray&); template SimpleArray asDblArray(const SimpleArray&); #ifdef USE_COMPMAT template <> SimpleArray SimpleArray::round(unsigned n) const; template <> SimpleArray& SimpleArray::prune(); template <> SimpleArray operator ^ (double, const SimpleArray&); #endif /* USE_COMPMAT */ #ifdef USE_FCOMPMAT template <> SimpleArray SimpleArray::round(unsigned n) const; template <> SimpleArray& SimpleArray::prune(); template <> SimpleArray operator ^ (double, const SimpleArray&); #endif /* USE_FCOMPMAT */ template SimpleArray round(const SimpleArray& array, unsigned n = 0) { return array.round(n); } template void prune(SimpleArray& array) { array.prune(); } #endif