MFEM v2.0
|
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 ©) 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 ©) 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