//-*-c++-*- #ifndef ARRAY_H #define ARRAY_H /** * @file array.h * @brief Basic dynamic K-dimensional array of type T - COLUMNWISE ORDERING! * @author James R. Diebel, Stanford University * * - History: * - 3 March 2006 - Started */ #include #ifdef _DEBUG #define AR_CHECK_BOUNDS 1 #define AR_PO 1 #else #define AR_CHECK_BOUNDS 0 #define AR_PO 0 #endif /** * @namespace sla * @brief Simple Linear Algebra - library of matrix and vector classes * plus some random utility functions and other containers */ namespace sla { ///////////////////////////////////////////////////////////////////////////// // DECLARATIONS ///////////////////////////////////////////////////////////////////////////// // Forward declarations template class Array; // Arbitrary-dimensional array //////////////////// Array //////////////////// /** * A K-Dimensional Array of type T */ template class Array { public: // Constructors/Destructor Array(); Array(const Vec dim_); Array(const Array& a) { set(a); } ~Array(); // Mutators void deleteArray() { reset(); } void reset(); void setSize(const Vec dim_); void set(const T v); void set(const T* v, const int i0 = 0, const int vlen = -1); void set(const Array& a); void addTo(const T* v, const int i0 = 0, const int vlen = -1); T& operator () (const int i); T& operator () (const Vec ind); // Assignment operator Array& operator = (const Array& a) { set(a); return *this; } // Accessors Vec size() const; int size(const int i) const; int length() const; T& operator () (const int i) const; T& operator () (const Vec ind) const; T min() const; T max() const; // Serialization int writeTo(std::ostream& os) const; int readFrom(std::istream& is); // Helper functions int indexOf(Vec ind) const; Vec coordsOf(int ind) const; bool isInBounds(Vec ind) const; bool isInBounds(int ind) const; int find(const T element) const; bool contains(const T element) const; // Data T* x; ///< storage array protected: Vec dim; ///< array dimensions }; // ASCII stream IO template std::ostream& operator << (std::ostream& os, const Array& a); template std::istream& operator >> (std::istream& is, Array& a); //////////////////////////////////////////////////////////////////////////// // DEFINITIONS //////////////////////////////////////////////////////////////////////////// //////////////////// Array //////////////////// // Constructors/Destructor /** Ctor that does no initalization. */ template inline Array::Array() { x = NULL; dim.set((int)0); if (AR_PO>1) std::cout << "Created empty Array." << std::endl << std::flush; } /** Ctor that starts with given dimensions * @param Vec n_ are the sizes in the several dimension */ template inline Array::Array(const Vec dim_) : Array() { setSize(dim_); } /** Dtor. */ template inline Array::~Array() { reset(); } // Mutators /** Deletes contents of array and frees memory */ template inline void Array::reset() { dim.set(0); if (x) { delete [] x; if (AR_PO>1) std::cout << "Freed memory for array." << std::endl << std::flush; x = NULL; } } /** Set the size of the array * @param dim_ the sizes of the array in each dimension */ template inline void Array::setSize(const Vec dim_) { if (!dim_.equalTo(dim)) { if (x != NULL) reset(); for (int k=0;k1) { std::cout << dim_; std::cout << "Warning, negative or zero dimensions not allowed." << std::endl << std::flush; } } dim = dim_; int len = dim.prod(); if (len>0) { x = new T[len]; if (AR_PO>1) std::cout << "Created array of linear size " << len << "." << std::endl << std::flush; } } } /** Set the values of all the elements in the array to v * @param v is the value to set the array to */ template inline void Array::set(const T v) { int len = dim.prod(); for (int i=0;i3) std::cout << "Set array elements to passed value." << std::endl << std::flush; } /** Set the values of all the elements in the array to v * @param v is the value to set the array to */ /*template inline void Array<,K>::set(const T v) { int len = dim.prod(); if (v == T(0)) memset(x,0,len*sizeof(T)); for (int i=0;i3) std::cout << "Set array elements to passed value." << std::endl << std::flush; }*/ /** Set the values of all the elements in the array to v * @param v is the value to set the array to */ template inline void Array::set(const T* v, const int i0, const int vlen) { int len = dim.prod(); int i1 = (vlen == -1)? len:sla::clamp(i0+vlen,0,len); for (int i=i0,j=0;i3) std::cout << "Set array elements to passed values." << std::endl << std::flush; } /** Set this array to the passed array, value-wise * @param a is the array to duplicate */ template inline void Array::set(const Array& a) { Vec dim_ = a.Array::size(); Array::setSize(dim_); Array::set(a.x); } /** Add the values in array v to this array * @param v is the value to set the array to */ template inline void Array::addTo(const T* v, const int i0, const int vlen) { int len = dim.prod(); int i1 = (vlen == -1)? len:sla::clamp(i0+vlen,0,len); for (int i=i0,j=0;i3) std::cout << "Added passed values to array elements." << std::endl << std::flush; } /** Returns mutable reference to array element * @param ind is the index list * @return a reference to the array element */ template inline T& Array::operator () (const Vec ind) { return x[indexOf(ind)]; } /** Returns mutable reference to array element * @param i is the linear index * @return a reference to the array element */ template inline T& Array::operator () (const int i) { #if AR_CHECK_BOUNDS int len = dim.prod(); if (i<0 || i>=len) { std::cerr << "Array::operator (): Error. Index " << i << " exceeds bounds [0, " << len << "]." << std::endl << std::flush; exit(1); } #endif return x[i]; } // Accessors /** Returns vector of array dimensions @return Vec of array dimension lengths */ template inline Vec Array::size() const { return dim; } /** Returns vector of array dimensions @return Vec of array dimension lengths */ template inline int Array::size(const int i) const { return dim(i); } /** Returns linear length of data @return integer legth of data */ template inline int Array::length() const { return dim.prod(); } /** Returns inmutable reference to array element * @param ind is the index list * @return the value of the array element */ template inline T& Array::operator () (const Vec ind) const { return x[indexOf(ind)]; } /** Returns inmutable reference to array element * @param i is the linear index * @return the value of the array element */ template inline T& Array::operator () (const int i) const { #if AR_CHECK_BOUNDS int len = dim.prod(); if (i<0 || i>=len) { std::cerr << "Error. Index " << i << " exceeds bounds [0, " << len << "]." << std::endl << std::flush; exit(1); } #endif return x[i]; } /** Returns the minimum value in the array. */ template inline T Array::min() const { if (length() == 0) { std::cerr << "Array::min: Error, no elements in array. Exiting." << std::endl << std::flush; } int len = dim.prod(); T m = x[0]; for (int i=0;i inline T Array::max() const { if (length() == 0) { std::cerr << "Array::max: Error, no elements in array. Exiting." << std::endl << std::flush; } int len = dim.prod(); T m = x[0]; for (int i=0;i m) m = x[i]; } return m; } // Serialization routines /** Write state to a binary stream. */ template inline int Array::writeTo(std::ostream& os) const { char flag[6] = "Array"; os.write(flag,5*sizeof(char)); dim.writeTo(os); int len = dim.prod(); if (len>0) os.write((char *)(x),len*sizeof(T)); return 0; } /** Restore state from a binary stream. */ template inline int Array::readFrom(std::istream& is) { char flag[6]; is.read(flag,5*sizeof(char)); if (flag[0] != 'A' || flag[1] != 'r') { if (AR_PO>1) std::cout << "Expecting array flag, but got something else." << std::endl << std::flush; return 1; } Vec dim_; dim_.readFrom(is); if (!dim_.equalTo(Array::size())) Array::setSize(dim_); int len = dim.prod(); if (len>0) is.read((char *)(x),len*sizeof(T)); return 0; } /** Write state to stream as formated ASCII */ template inline std::ostream& operator << (std::ostream& os, const Array& a) { int minFieldWidth = os.precision()+5; Vec dim = a.size(); for (int i=0;i0 && i%dim(0) == 0) os << std::endl; if (K>2) if (i>0 && i%(dim(0)*dim(1)) == 0) os << std::endl; if (K>3) if (i>0 && i%(dim(0)*dim(1)*dim(2)) == 0) os << std::endl; os << std::setw(minFieldWidth) << a(i) << std::endl; } os << std::endl; return os; } /** Read state from stream of formated ASCII */ template inline std::istream& operator >> (std::istream& is, Array& a) { Vec dim; for (int i=0;i> dim(i); if (!dim.equalTo(a.template Array::size())) a.setSize(dim); for (int i=0;i> a(i); } return is; } // Helper functions (used internally only) /** Returns linear index of given array indices * @param ind is the vector of indices to be converted * @return the linear index in the data array x */ template inline int Array::indexOf(Vec ind) const { #if AR_CHECK_BOUNDS for (int k=0;k= dim(k)) { std::cerr << "Error. Index " << ind(k) << " exceeds bounds [0, " << dim(k) << "]" << std::endl << std::flush; exit(1); } #endif int k=ind(0); int mul = 1; for (int i=1;i inline Vec Array::coordsOf(int ind) const { #if AR_CHECK_BOUNDS if (ind<0 || ind>=length()) { std::cerr << "Error. Index " << ind << " exceeds bounds [0, " << length() << "]" << std::endl << std::flush; exit(1); } #endif Vec result; for (int id=0;id inline bool Array::isInBounds(Vec ind) const { for (int k=0;k= dim(k)) return false; return true; } /** Checks if the given index is within array bounds * @param ind is the index to check */ template inline bool Array::isInBounds(int ind) const { return (ind>=0 && ind inline int Array::find(const T element) const { for (int k=0,n=length();k inline bool Array::contains(const T element) const { return find(element) >= 0; } } // end namespace sla #endif