// ----------------------------------------------------------- // SPL (Solitonic POOMA-based Library). // Copyright (C) 2000 by Serge Mingaleev // Last modified: Sep 17, 2000. // ----------------------------------------------------------- #ifndef SPL_ENGINE_SPARSEENGINE_H #error "Should be included from SparseEngine.h only!" #endif #ifndef SPL_ENGINE_SPARSEENGINE4_H #define SPL_ENGINE_SPARSEENGINE4_H //============================================================= // Realization of the Engine<4,T,Sparse> //============================================================= #define Dim 4 template class Engine<4,T,Sparse> { public: //============================================================ // Exported typedefs and constants //============================================================ typedef Engine This_t; typedef Engine Engine_t; // typedef Pooma::SparseBase Base_t; // typedef typename Base_t::Domain_t Domain_t; typedef Interval Domain_t; typedef DomainLayout Layout_t; typedef T Element_t; typedef T& ElementRef_t; typedef Sparse Tag_t; enum { sparse = true }; enum { brick = false }; enum { dimensions = Dim }; enum { hasDataObject = false }; enum { dynamic = false }; enum { zeroBased = false }; enum { multiPatch = false }; //========================================================== // Constructors and Factory Methods //========================================================== // Default constructor. Creates a Brick-Engine with no data // and an "empty" domain. This is not really usable until it // has been initialized (via operator=) to a new engine with an // actual domain. Engine() { } // These constructors take an Interval and create a new // Brick-Engine with data of type T on this Domain. This is where // storage gets allocated. The second version uses a model data // element to initialize storage. Engine(const Domain_t& dom) { data_m.initialize(dom[0], dom[1]); for (int i=dom[0].first(); i<=dom[0].last(); i++) for (int j=dom[1].first(); j<=dom[1].last(); j++) data_m(i,j).initialize(dom[2], dom[3]); for (int d = 0; d < Dim; d++) { domain_m[d] = dom[d]; firsts_m[d] = dom[d].first(); } tol_m=data_m(firsts_m[0], firsts_m[1]).engine().tolerance(); size_m=dom[0].size()*dom[1].size() *data_m(firsts_m[0], firsts_m[1]).engine().size(); #ifdef SPL_DEBUG_SPARSE cerr << "Creating 4D Sparse Array (" << domain_m[0] << "x" << domain_m[1] << "x" << domain_m[2] << "x" << domain_m[3] << ") with size = " << size_m << endl; #endif } // Subsetting Constructors. // There are none - you cannot create a Brick-Engine by taking // a "view" of another Engine. Brick-Engines, by definition, // view all of the data. See Engine below. //============================================================ // Destructor //============================================================ ~Engine(){ #ifdef SPL_DEBUG_SPARSE cerr << "Deleting 4D Sparse Array (" << domain_m[0] << "x" << domain_m[1] << "x" << domain_m[2] << "x" << domain_m[3] << ") with size = " << size_m << endl; #endif }; //============================================================ // Assignment operators //============================================================ // Assigment is SHALLOW, to be consistent with copy. Engine_t &operator=(const Engine_t &model) { if (this == &model) return *this; tol_m = model.tol_m; size_m = model.size_m; for (int d = 0; d < Dim; ++d) { firsts_m[d] = model.firsts_m[d]; }; domain_m = model.domain_m; data_m.initialize(model.data_m); for (int i=domain_m[0].first(); i<=domain_m[0].last(); i++) for (int j=domain_m[1].first(); j<=domain_m[1].last(); j++) { data_m(i,j).initialize(model.data_m(i,j)); // data_m(i,j)=model.data_m(i,j); }; return *this; } //============================================================ // Accessor and Mutator functions: //============================================================ // Element access via Loc. Element_t read(const Loc &loc) const { Loc<2> L01(loc[0], loc[1]), L23(loc[2], loc[3]); return data_m(L01)(L23); } ElementRef_t operator()(const Loc &loc) const { Loc<2> L01(loc[0], loc[1]), L23(loc[2], loc[3]); return data_m(L01)(L23); } // Element access via ints for speed. Element_t read(int i1, int i2, int i3, int i4) const { return data_m(i1,i2)(i3,i4); } ElementRef_t operator()(int i1, int i2, int i3, int i4) const { return data_m(i1,i2)(i3,i4); } // Get a private copy of data viewed by this Engine. Engine_t &makeOwnCopy() { data_m.makeOwnCopy(); return *this; } //--------------------------------------------------------- // Return/set the domain. inline const Domain_t &domain() const { return domain_m; } //--------------------------------------------------------- // Return the first index value for the specified direction. inline int first(int i) const { PAssert(i >= 0 && i < Dim); return firsts_m[i]; } //--------------------------------------------------------- // Return the size inline int size() const { return size_m; } //--------------------------------------------------------- // Return number of free cells inline int free() const { int f=0; for (int i=domain_m[0].first(); i<=domain_m[0].last(); i++) for (int j=domain_m[1].first(); j<=domain_m[1].last(); j++) { f += data_m(i,j).engine().free(); }; return f; } //--------------------------------------------------------- // Return tolerance: // (see also realization of pack() !!!) inline T& tolerance() { return tol_m; } //--------------------------------------------------------- // Packing functions for the sparse array: void pack(void) const { for (int i=domain_m[0].first(); i<=domain_m[0].last(); i++) for (int j=domain_m[1].first(); j<=domain_m[1].last(); j++) { data_m(i,j).engine().tolerance()=tol_m; data_m(i,j).engine().pack(); }; } //--------------------------------------------------------- // Print sparse array: void print(void) const { // cout << endl << " Non-zero elements of 4D Sparse Array:" << endl; for (int i=domain_m[0].first(); i<=domain_m[0].last(); i++) for (int j=domain_m[1].first(); j<=domain_m[1].last(); j++) { cout << "(" << i << "," << j << "):" << endl; data_m(i,j).engine().print(); }; } //--------------------------------------------------------- // Write sparse array: template void write(Out& os) const { // Write the extent vector: this is separated by 'x's, e.g. // (1, 10) x (-4, 4) x (-5, 5) for (int i=0; i < Dim; ++i) { os << "("; os << domain_m[i].first(); os << ", "; os << domain_m[i].last(); os << ")"; if (i != Dim-1) os << " x "; } os << endl << "[ "; for (int i=domain_m[0].first(); i<=domain_m[0].last(); i++) for (int j=domain_m[1].first(); j<=domain_m[1].last(); j++) { data_m(i,j).engine().write(os); }; os << "]" << endl; } private: //========================================================== // Private data //========================================================== T tol_m; int size_m; int firsts_m[Dim]; Domain_t domain_m; Array<2, Array<2,T,Sparse> > data_m; }; #undef Dim #endif // SPL_ENGINE_SPARSEENGINE4_H