// ----------------------------------------------------------- // 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_SPARSEENGINE2_H #define SPL_ENGINE_SPARSEENGINE2_H //============================================================= // Realization of the Engine<2,T,Sparse> //============================================================= #define Dim 2 template class Engine<2,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 Interval<1> Domain1D_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) { tol_m=SPARSE_TOLERANCE; size_m=int(SPARSITY_LEVEL*dom[0].size()*dom[1].size()); domain1D_m=Domain1D_t(-1, size_m-1); for (int d = 0; d < Dim; d++) { domain_m[d] = dom[d]; firsts_m[d] = dom[d].first(); } data_m.initialize(domain1D_m); cols_m.initialize(domain1D_m); next_m.initialize(domain1D_m); addr_m.initialize(domain_m[0]); addr_m=-1; // no elements are stored data_m(-1)=0.0; // unstored elements are zero // the first free cell has zero index: free_m=0; // all other free cells form a chain: for (int k=0; k below. //============================================================ // Destructor //============================================================ ~Engine(){ #ifdef SPL_DEBUG_SPARSE cerr << "Deleting Sparse Matrix (" << domain_m[0] << "x" << domain_m[1] << ") with size = " << size_m << " in (" << domain1D_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; free_m = model.free_m; for (int d = 0; d < Dim; ++d) { firsts_m[d] = model.firsts_m[d]; } domain_m = model.domain_m; domain1D_m = model.domain1D_m; data_m.initialize(model.data_m); cols_m.initialize(model.cols_m); next_m.initialize(model.next_m); addr_m.initialize(model.addr_m); data_m = model.data_m; cols_m = model.cols_m; next_m = model.next_m; addr_m = model.addr_m; return *this; } //============================================================ // Accessor and Mutator functions: //============================================================ // Element access via Loc. Element_t read(const Loc &loc) const { return data_m(index(loc)); } ElementRef_t operator()(const Loc &loc) const { return data_m(set_index(loc)); } // Element access via ints for speed. Element_t read(int i1, int i2) const { return data_m(index(i1,i2)); } ElementRef_t operator()(int i1, int i2) const { return data_m(set_index(i1,i2)); } // Get a private copy of data viewed by this Engine. Engine_t &makeOwnCopy() { // mutable int free_m; // T tol_m; // int size_m; // int firsts_m[Dim]; // Domain_t domain_m; // Domain1D_t domain1D_m; data_m.makeOwnCopy(); cols_m.makeOwnCopy(); next_m.makeOwnCopy(); addr_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, k=free_m; while (k != -1) { f++; k=next_m(k); } return f; } //--------------------------------------------------------- // Return/set tolerance inline T& tolerance() { return tol_m; } //--------------------------------------------------------- // Return index of element (i,j) or -1 if it is not stored inline int index(int i, int j) const { int k=addr_m(i); while (k != -1) { int m=cols_m(k); if (m == j) return k; if (m > j) break; k=next_m(k); } return (-1); } inline int index(const Domain_t &dom) const { return index(dom[0].first(),dom[1].first()); } //--------------------------------------------------------- // Packing functions for the sparse array: void pack(void) const { int i_min=domain_m[0].first(), i_max=i_min+domain_m[0].size(); for (int i=i_min; i diagVector(void) const { if (domain_m[0] != domain_m[1]) PError ("Not a square matrix - has no diagonal"); Array<1,T> B(domain_m[0]); int i_min=domain_m[0].first(), i_max=i_min+domain_m[0].size(); for (int i=i_min; i inline Array<1,TV,ETV> dot(Array<1,TV,ETV> X) const { if (X.domain() != domain_m[1]) PError ("Mismatched matrix and input vector"); Array<1,TV,ETV> B(domain_m[0]); int i_min=domain_m[0].first(), i_max=i_min+domain_m[0].size(); B=0.0; for (int i=i_min; i inline Array<1,TV,ETV> dot_T(Array<1,TV,ETV> X) const { if (X.domain() != domain_m[0]) PError ("Mismatched matrix and input vector"); Array<1,TV,ETV> B(domain_m[1]); int i_min=domain_m[0].first(), i_max=i_min+domain_m[0].size(); B=0.0; for (int i=i_min; i j) break; k0=k; k=next_m(k); } int q=get_free(); if (k == addr_m(i)) addr_m(i)=q; else next_m(k0)=q; next_m(q)=k; cols_m(q)=j; data_m(q)=0.0; return q; } inline int set_index(const Domain_t &dom) const { return set_index(dom[0].first(),dom[1].first()); } private: //========================================================== // Private data //========================================================== mutable int free_m; T tol_m; int size_m; int firsts_m[Dim]; Domain_t domain_m; Domain1D_t domain1D_m; Array<1,T> data_m; Array<1,int> cols_m; Array<1,int> next_m; Array<1,int> addr_m; }; #undef Dim #endif // SPL_ENGINE_SPARSEENGINE2_H