MFEM v2.0
array.hpp
Go to the documentation of this file.
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
00003 // reserved. See file COPYRIGHT for details.
00004 //
00005 // This file is part of the MFEM library. For more information and source code
00006 // availability see http://mfem.googlecode.com.
00007 //
00008 // MFEM is free software; you can redistribute it and/or modify it under the
00009 // terms of the GNU Lesser General Public License (as published by the Free
00010 // Software Foundation) version 2.1 dated February 1999.
00011 
00012 #ifndef MFEM_ARRAY
00013 #define MFEM_ARRAY
00014 
00015 #include <iostream>
00016 #include <cstdlib>
00017 #include <cstring>
00018 
00019 #include "error.hpp"
00020 
00021 using namespace std;
00022 
00024 class BaseArray
00025 {
00026 protected:
00028    void *data;
00030    int size;
00032    int allocsize;
00035    int inc;
00036 
00037    BaseArray() { }
00039    BaseArray(int asize, int ainc, int elmentsize);
00041    ~BaseArray();
00045    void GrowSize(int minsize, int elementsize);
00046 };
00047 
00048 template <class T>
00049 class Array;
00050 
00051 template <class T>
00052 void Swap(Array<T> &, Array<T> &);
00053 
00062 template <class T>
00063 class Array : public BaseArray
00064 {
00065 public:
00066    friend void Swap<T>(Array<T> &, Array<T> &);
00067 
00069    explicit inline Array(int asize = 0, int ainc = 0)
00070       : BaseArray(asize, ainc, sizeof (T)) { }
00071 
00075    inline Array(T *_data, int asize, int ainc = 0)
00076    { data = _data; size = asize; allocsize = -asize; inc = ainc; }
00077 
00079    inline ~Array() { }
00080 
00082    inline operator T *() { return (T *)data; }
00083 
00085    inline operator const T *() const { return (const T *)data; }
00086 
00088    inline T *GetData() { return (T *)data; }
00089 
00091    inline void StealData(T **p)
00092    { *p = (T*)data; data = 0; size = allocsize = 0; }
00093 
00095    inline void LoseData() { data = 0; size = allocsize = 0; }
00096 
00098    void MakeDataOwner() { allocsize = abs(allocsize); }
00099 
00101    inline int Size() const { return size; };
00102 
00104    inline void SetSize(int nsize);
00105 
00107    inline T & operator[](int i);
00108 
00110    inline const T &operator[](int i) const;
00111 
00113    inline int Append(const T & el);
00114 
00116    inline int Append(const Array<T> &els);
00117 
00119    inline int Prepend(const T &el);
00120 
00122    inline T &Last();
00123 
00125    inline int Union(const T & el);
00126 
00128    inline int Find(const T &el) const;
00129 
00131    inline void DeleteLast() { size--; }
00132 
00134    inline void DeleteFirst(const T &el);
00135 
00137    inline void DeleteAll();
00138 
00140    inline void Copy(Array &copy) const
00141    {
00142       copy.SetSize(Size());
00143       memcpy(copy.GetData(), data, Size()*sizeof(T));
00144    }
00145 
00147    inline void MakeRef(const Array &master);
00148 
00149    inline void GetSubArray(int offset, int sa_size, Array<T> &sa);
00150 
00152    void Print(ostream &out, int width);
00153 
00155    void Save(ostream &out);
00156 
00159    T Max() const;
00160 
00162    void Sort();
00163 
00164    inline void operator=(const T &a);
00165 
00166 private:
00168    Array<T> &operator=(Array<T> &);
00170    Array(const Array<T> &);
00171 };
00172 
00173 template <class T>
00174 class Array2D;
00175 
00176 template <class T>
00177 void Swap(Array2D<T> &, Array2D<T> &);
00178 
00179 template <class T>
00180 class Array2D
00181 {
00182 private:
00183    friend void Swap<T>(Array2D<T> &, Array2D<T> &);
00184 
00185    Array<T> array1d;
00186    int N;
00187 
00188 public:
00189    Array2D() { N = 0; }
00190    Array2D(int m, int n) : array1d(m*n) { N = n; }
00191 
00192    void SetSize(int m, int n) { array1d.SetSize(m*n); N = n; }
00193 
00194    int NumRows() const { return array1d.Size()/N; }
00195    int NumCols() const { return N; }
00196 
00197    inline const T &operator()(int i, int j) const;
00198    inline       T &operator()(int i, int j);
00199 
00200    inline const T *operator[](int i) const;
00201    inline T       *operator[](int i);
00202 
00203    const T *operator()(int i) const { return (*this)[i]; }
00204    T       *operator()(int i)       { return (*this)[i]; }
00205 
00206    const T *GetRow(int i) const { return (*this)[i]; }
00207    T       *GetRow(int i)       { return (*this)[i]; }
00208 
00209    void Copy(Array2D &copy) const
00210    { copy.N = N; array1d.Copy(copy.array1d); }
00211 };
00212 
00213 
00214 template <class T>
00215 class Array3D
00216 {
00217 private:
00218    Array<T> array1d;
00219    int N2, N3;
00220 
00221 public:
00222    Array3D() { N2 = N3 = 0; }
00223    Array3D(int n1, int n2, int n3)
00224       : array1d(n1*n2*n3) { N2 = n2; N3 = n3; }
00225 
00226    void SetSize(int n1, int n2, int n3)
00227    { array1d.SetSize(n1*n2*n3); N2 = n2; N3 = n3; }
00228 
00229    inline const T &operator()(int i, int j, int k) const;
00230    inline       T &operator()(int i, int j, int k);
00231 };
00232 
00233 
00234 template <class T>
00235 inline void Swap(T &a, T &b)
00236 {
00237    T c = a;
00238    a = b;
00239    b = c;
00240 }
00241 
00242 template <class T>
00243 inline void Swap(Array<T> &a, Array<T> &b)
00244 {
00245    int   s;
00246    void *data;
00247 
00248    data = a.data;   a.data = b.data;           b.data = data;
00249    s = a.size;      a.size = b.size;           b.size = s;
00250    s = a.allocsize; a.allocsize = b.allocsize; b.allocsize = s;
00251    s = a.inc;       a.inc = b.inc;             b.inc = s;
00252 }
00253 
00254 template <class T>
00255 inline void Array<T>::SetSize(int nsize)
00256 {
00257 #ifdef MFEM_DEBUG
00258    if (nsize < 0)
00259       mfem_error("Array::SetSize : negative size!");
00260 #endif
00261    if (nsize > abs(allocsize))
00262       GrowSize(nsize, sizeof(T));
00263    size = nsize;
00264 }
00265 
00266 template <class T>
00267 inline T &Array<T>::operator[](int i)
00268 {
00269 #ifdef MFEM_DEBUG
00270    if (i < 0 || i >= size)
00271    {
00272       cerr << "Access element " << i << " of array, size = " << size << endl;
00273       mfem_error();
00274    }
00275 #endif
00276    return ((T*)data)[i];
00277 }
00278 
00279 template <class T>
00280 inline const T &Array<T>::operator[](int i) const
00281 {
00282 #ifdef MFEM_DEBUG
00283    if (i < 0 || i >= size)
00284    {
00285       cerr << "Access element " << i << " of array, size = " << size << endl;
00286       mfem_error();
00287    }
00288 #endif
00289    return ((T*)data)[i];
00290 }
00291 
00292 template <class T>
00293 inline int Array<T>::Append(const T &el)
00294 {
00295    SetSize(size+1);
00296    ((T*)data)[size-1] = el;
00297    return size;
00298 }
00299 
00300 template <class T>
00301 inline int Array<T>::Append(const Array<T> & els)
00302 {
00303    int old_size = size;
00304 
00305    SetSize(size + els.Size());
00306    for (int i = 0; i < els.Size(); i++)
00307       ((T*)data)[old_size+i] = els[i];
00308    return size;
00309 }
00310 
00311 
00312 template <class T>
00313 inline int Array<T>::Prepend(const T &el)
00314 {
00315    SetSize(size+1);
00316    for (int i = size-1; i > 0; i--)
00317       ((T*)data)[i] = ((T*)data)[i-1];
00318    ((T*)data)[0] = el;
00319    return size;
00320 }
00321 
00322 
00323 template <class T>
00324 inline T &Array<T>::Last()
00325 {
00326 #ifdef MFEM_DEBUG
00327    if (size < 1)
00328       mfem_error("Array<T>::Last()");
00329 #endif
00330    return ((T*)data)[size-1];
00331 }
00332 
00333 template <class T>
00334 inline int Array<T>::Union(const T &el)
00335 {
00336    int i = 0;
00337    while ((i < size) && (((T*)data)[i] != el)) i++;
00338    if (i == size)
00339       Append(el);
00340    return i;
00341 }
00342 
00343 template <class T>
00344 inline int Array<T>::Find(const T &el) const
00345 {
00346    for (int i = 0; i < size; i++)
00347       if (((T*)data)[i] == el)
00348          return i;
00349    return -1;
00350 }
00351 
00352 template <class T>
00353 inline void Array<T>::DeleteFirst(const T &el)
00354 {
00355    for (int i = 0; i < size; i++)
00356       if (((T*)data)[i] == el)
00357       {
00358          for (i++; i < size; i++)
00359             ((T*)data)[i-1] = ((T*)data)[i];
00360          size--;
00361          return;
00362       }
00363 }
00364 
00365 template <class T>
00366 inline void Array<T>::DeleteAll()
00367 {
00368    if (allocsize > 0)
00369       delete [] (char*)data;
00370    data = NULL;
00371    size = allocsize = 0;
00372 }
00373 
00374 template <class T>
00375 inline void Array<T>::MakeRef(const Array &master)
00376 {
00377    if (allocsize > 0)
00378       delete [] (char*)data;
00379    data = master.data;
00380    size = master.size;
00381    allocsize = -abs(master.allocsize);
00382    inc = master.inc;
00383 }
00384 
00385 template <class T>
00386 inline void Array<T>::GetSubArray(int offset, int sa_size, Array<T> &sa)
00387 {
00388    sa.SetSize(sa_size);
00389    for (int i = 0; i < sa_size; i++)
00390       sa[i] = (*this)[offset+i];
00391 }
00392 
00393 template <class T>
00394 inline void Array<T>::operator=(const T &a)
00395 {
00396    for (int i = 0; i < size; i++)
00397       ((T*)data)[i] = a;
00398 }
00399 
00400 
00401 template <class T>
00402 inline const T &Array2D<T>::operator()(int i, int j) const
00403 {
00404 #ifdef MFEM_DEBUG
00405    if (i < 0 || i >= array1d.Size()/N || j < 0 || j >= N)
00406    {
00407       cerr << "Array2D: invalid access of element (" << i << ',' << j
00408            << ") in array of size (" << array1d.Size()/N << ',' << N
00409            << ")." << endl;
00410       mfem_error();
00411    }
00412 #endif
00413    return array1d[i*N+j];
00414 }
00415 
00416 template <class T>
00417 inline T &Array2D<T>::operator()(int i, int j)
00418 {
00419 #ifdef MFEM_DEBUG
00420    if (i < 0 || i >= array1d.Size()/N || j < 0 || j >= N)
00421    {
00422       cerr << "Array2D: invalid access of element (" << i << ',' << j
00423            << ") in array of size (" << array1d.Size()/N << ',' << N
00424            << ")." << endl;
00425       mfem_error();
00426    }
00427 #endif
00428    return array1d[i*N+j];
00429 }
00430 
00431 template <class T>
00432 inline const T *Array2D<T>::operator[](int i) const
00433 {
00434 #ifdef MFEM_DEBUG
00435    if (i < 0 || i >= array1d.Size()/N)
00436    {
00437       cerr << "Array2D: invalid access of row " << i << " in array with "
00438            << array1d.Size()/N << " rows." << endl;
00439       mfem_error();
00440    }
00441 #endif
00442    return &array1d[i*N];
00443 }
00444 
00445 template <class T>
00446 inline T *Array2D<T>::operator[](int i)
00447 {
00448 #ifdef MFEM_DEBUG
00449    if (i < 0 || i >= array1d.Size()/N)
00450    {
00451       cerr << "Array2D: invalid access of row " << i << " in array with "
00452            << array1d.Size()/N << " rows." << endl;
00453       mfem_error();
00454    }
00455 #endif
00456    return &array1d[i*N];
00457 }
00458 
00459 
00460 template <class T>
00461 inline void Swap(Array2D<T> &a, Array2D<T> &b)
00462 {
00463    int s;
00464    Swap(a.array1d, b.array1d);
00465    s = a.N;  a.N = b.N;  b.N = s;
00466 }
00467 
00468 
00469 template <class T>
00470 inline const T &Array3D<T>::operator()(int i, int j, int k) const
00471 {
00472 #ifdef MFEM_DEBUG
00473    int N1 = array1d.Size()/N2/N3;
00474    if (i < 0 || i >= N1 || j < 0 || j >= N2 || k < 0 || k >= N3)
00475    {
00476       cerr << "Array3D: invalid access of element ("
00477            << i << ',' << j << ',' << k << ") in array of size ("
00478            << N1 << ',' << N2 << ',' << N3 << ")." << endl;
00479       mfem_error();
00480    }
00481 #endif
00482    return array1d[(i*N2+j)*N3+k];
00483 }
00484 
00485 template <class T>
00486 inline T &Array3D<T>::operator()(int i, int j, int k)
00487 {
00488 #ifdef MFEM_DEBUG
00489    int N1 = array1d.Size()/N2/N3;
00490    if (i < 0 || i >= N1 || j < 0 || j >= N2 || k < 0 || k >= N3)
00491    {
00492       cerr << "Array3D: invalid access of element ("
00493            << i << ',' << j << ',' << k << ") in array of size ("
00494            << N1 << ',' << N2 << ',' << N3 << ")." << endl;
00495       mfem_error();
00496    }
00497 #endif
00498    return array1d[(i*N2+j)*N3+k];
00499 }
00500 
00501 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines