src/Index/SIndex.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  *
00022  * Visit http://people.web.psi.ch/adelmann/ for more details
00023  *
00024  ***************************************************************************/
00025 
00026 // include files
00027 #include "Index/SIndex.h"
00028 #include "Index/IndexedSIndex.h"
00029 #include "FieldLayout/FieldLayout.h"
00030 #include "Utility/PAssert.h"
00031 #include "Profile/Profiler.h"
00032 
00033 
00034 
00036 // default constructor: this requires the user to call 'initialize'
00037 // before any other actions are carried out with this SIndex
00038 template<unsigned int Dim>
00039 SIndex<Dim>::SIndex() : Layout(0) {
00040   TAU_PROFILE("SIndex::SIndex()", typeid(*this).name(), TAU_SPARSE);
00041 }
00042 
00043 
00045 // constructor: requires a FieldLayout, and optionally an offset amount
00046 template<unsigned int Dim>
00047 SIndex<Dim>::SIndex(FieldLayout<Dim>& fl) : Layout(&fl) {
00048   TAU_TYPE_STRING(taustr, "void (" + CT(fl) + " )");
00049   TAU_PROFILE("SIndex::SIndex()", taustr, TAU_SPARSE);
00050 
00051   setup();
00052 }
00053 
00054 
00056 // copy constructor
00057 template<unsigned int Dim>
00058 SIndex<Dim>::SIndex(const SIndex<Dim>& si)
00059   : Layout(si.Layout), Offset(si.Offset), IndexList(si.IndexList),
00060     BoundingBox(si.BoundingBox)
00061 {
00062   TAU_TYPE_STRING(taustr, "void (" + CT(si) + " )");
00063   TAU_PROFILE("SIndex::SIndex()", taustr, TAU_SPARSE);
00064 
00065   // check in as a user of this Layout
00066   Layout->checkin(*this);
00067 }
00068 
00069 
00071 // a special constructor, taking another SIndex and an Offset.  This
00072 // version is almost like a copy constructor, except that the given Offset
00073 // is added to our own offset.
00074 template<unsigned int Dim>
00075 SIndex<Dim>::SIndex(const SIndex<Dim>& si, const SOffset<Dim>& so)
00076   : Layout(si.Layout), Offset(si.Offset), IndexList(si.IndexList),
00077     BoundingBox(si.BoundingBox)
00078 {
00079   TAU_TYPE_STRING(taustr, "void (" + CT(si) + ", " + CT(so) + " )");
00080   TAU_PROFILE("SIndex::SIndex()", taustr, TAU_SPARSE);
00081 
00082   // add in the extra offset amount
00083   Offset += so;
00084 
00085   // check in as a user of this Layout
00086   Layout->checkin(*this);
00087 }
00088 
00089 
00091 // a special constructor, taking another SIndex and an int * offset.  This
00092 // version is almost like a copy constructor, except that the given Offset
00093 // is added to our own offset.
00094 template<unsigned int Dim>
00095 SIndex<Dim>::SIndex(const SIndex<Dim>& si, const int *so)
00096   : Layout(si.Layout), Offset(si.Offset), IndexList(si.IndexList),
00097     BoundingBox(si.BoundingBox)
00098 {
00099   TAU_TYPE_STRING(taustr, "void (" + CT(si) + ", " + CT(so) + " )");
00100   TAU_PROFILE("SIndex::SIndex()", taustr, TAU_SPARSE);
00101 
00102   // add in the extra offset amount
00103   Offset += so;
00104 
00105   // check in as a user of this Layout
00106   Layout->checkin(*this);
00107 }
00108 
00109 
00111 // destructor: frees memory used to store indices, and check out from Layout
00112 template<unsigned int Dim>
00113 SIndex<Dim>::~SIndex() {
00114   TAU_PROFILE("SIndex::~SIndex()", typeid(*this).name(), TAU_SPARSE);
00115   if (Layout != 0)
00116     Layout->checkout(*this);
00117 }
00118 
00119 
00121 // initialize the object, if we were constructed with the default
00122 // constructor
00123 template<unsigned int Dim>
00124 void SIndex<Dim>::initialize(FieldLayout<Dim>& fl) {
00125   TAU_TYPE_STRING(taustr, "void (" + CT(fl) + " )"); 
00126   TAU_PROFILE("SIndex::initialize()", taustr, TAU_SPARSE);
00127 
00128   Layout = &fl;
00129   setup();
00130 }
00131 
00132 
00134 // set up our internal data structures from the constructor.  Assumes
00135 // the Layout and Offset have been set.
00136 template<unsigned int Dim>
00137 void SIndex<Dim>::setup() {
00138   TAU_PROFILE("SIndex::setup()", typeid(*this).name(), TAU_SPARSE);
00139 
00140   // check in as a user of the FieldLayout
00141   Layout->checkin(*this);
00142 
00143   // get the number of vnodes, and make sure we have storage for them
00144   IndexList.reserve(Layout->size_iv());
00145 
00146   // create new LSIndex objects for the local vnodes
00147   typename FieldLayout<Dim>::iterator_iv locvn = Layout->begin_iv();
00148   for ( ; locvn != Layout->end_iv(); ++locvn)
00149     IndexList.push_back(new LSIndex<Dim>((*locvn).second.get()));
00150 
00151   // save our bounding box information
00152   BoundingBox = Layout->getDomain();
00153 }
00154 
00155 
00157 // add a new index point, specified as an Offset or as a single-point NDIndex.
00158 // return success (this can fail if the point is outsize the field's domain)
00159 template<unsigned int Dim>
00160 bool SIndex<Dim>::addIndex(const SOffset<Dim>& so) {
00161   TAU_TYPE_STRING(taustr, "bool (" + CT(so) + " )"); 
00162   TAU_PROFILE("SIndex::addIndex()", taustr, TAU_SPARSE);
00163 
00164   // right now, this is straightforward: try to add to each LSIndex in
00165   // succession until one actually works
00166   for (iterator_iv curr = begin_iv(); curr != end_iv(); ++curr) {
00167     if (addIndex(curr, so)) {
00168       return true;
00169     }
00170   }
00171 
00172   // if we're here, we could not find a vnode to take this point
00173   return false;
00174 }
00175 
00176 
00178 // add a new index point, specified as an Offset or as a single-point NDIndex.
00179 // This version specifically tells which LField to use.
00180 // return success (this can fail if the point is outsize the field's domain)
00181 template<unsigned int Dim>
00182 bool SIndex<Dim>::addIndex(SIndex<Dim>::iterator_iv& curr,
00183                            const SOffset<Dim>& so) {
00184   TAU_TYPE_STRING(taustr, "bool (" + CT(curr) + ", " + CT(so) + " )"); 
00185   TAU_PROFILE("SIndex::addIndex()", taustr, TAU_SPARSE);
00186 
00187   // if the point is in the LField's region, add it
00188   if ((*curr)->contains(so) && ! (*curr)->hasIndex(so)) {
00189     (*curr).CopyForWrite();
00190     (*curr)->addIndex(so);
00191     return true;
00192   }
00193 
00194   // if we're here, the point was outside the given LField's domain
00195   return false;
00196 }
00197 
00198 
00200 // same as above, but taking an NDIndex.  One point is added to our lists
00201 // for each point in the NDIndex region (e.g., if a 2x3 NDIndex is given,
00202 // 6 points in total will be added to this SIndex).
00203 template<unsigned int Dim>
00204 void SIndex<Dim>::addIndex(const NDIndex<Dim>& constndi) {
00205   TAU_TYPE_STRING(taustr, "void (" + CT(constndi) + " )"); 
00206   TAU_PROFILE("SIndex::addIndex()", taustr, TAU_SPARSE);
00207 
00208   // cast away const; we are not modifying the NDIndex, so this should be ok
00209   NDIndex<Dim>& ndi((NDIndex<Dim> &)constndi);
00210 
00211   // calculate the total number of points, and counters for looping
00212   unsigned int d, totalnum = ndi.size();
00213   Index::iterator counter[Dim];
00214   for (d=0; d < Dim; ++d)
00215     counter[d] = ndi[d].begin();
00216 
00217   while (totalnum-- > 0) {
00218     // create an SOffset obj and add it to our lists
00219     SOffset<Dim> newpoint;
00220     for (d=0; d < Dim; ++d)
00221       newpoint[d] = *(counter[d]);
00222     addIndex(newpoint);
00223 
00224     // increment the index iterators
00225     unsigned int chkdim = 0;
00226     while(chkdim < Dim) {
00227       ++(counter[chkdim]);
00228       if (counter[chkdim] == ndi[chkdim].end()) {
00229         counter[chkdim] = ndi[chkdim].begin();
00230         chkdim++;
00231       } else {
00232         break;
00233       }
00234     }
00235   }
00236 }
00237 
00238 
00240 // add a new index point, specified as an Offset or as a single-point NDIndex.
00241 // return success (this can fail if the point is outsize the field's domain)
00242 template<unsigned int Dim>
00243 bool SIndex<Dim>::removeIndex(const SOffset<Dim>& so) {
00244   TAU_TYPE_STRING(taustr, "bool (" + CT(so) + " )"); 
00245   TAU_PROFILE("SIndex::removeIndex()", taustr, TAU_SPARSE);
00246 
00247   // right now, this is straightforward: try to add to each LSIndex in
00248   // succession until one actually works
00249   for (iterator_iv curr = begin_iv(); curr != end_iv(); ++curr)
00250     if (removeIndex(curr, so))
00251       return true;
00252 
00253   // if we're here, we could not find a vnode to take this point
00254   return false;
00255 }
00256 
00257 
00259 // add a new index point, specified as an Offset or as a single-point NDIndex.
00260 // This version specifically tells which LField to use.
00261 // return success (this can fail if the point is outsize the field's domain)
00262 template<unsigned int Dim>
00263 bool SIndex<Dim>::removeIndex(SIndex<Dim>::iterator_iv& curr,
00264                            const SOffset<Dim>& so) {
00265   TAU_TYPE_STRING(taustr, "bool (" + CT(curr) + ", " + CT(so) + " )"); 
00266   TAU_PROFILE("SIndex::removeIndex()", taustr, TAU_SPARSE);
00267   if ((*curr)->hasIndex(so)) {
00268     (*curr).CopyForWrite();
00269     (*curr)->removeIndex(so);
00270     return true;
00271   }
00272   return false;
00273 }
00274 
00275 
00277 // same as above, but taking an NDIndex.  One point is added to our lists
00278 // for each point in the NDIndex region (e.g., if a 2x3 NDIndex is given,
00279 // 6 points in total will be added to this SIndex).
00280 template<unsigned int Dim>
00281 void SIndex<Dim>::removeIndex(const NDIndex<Dim>& constndi) {
00282   TAU_TYPE_STRING(taustr, "bool (" + CT(constndi) + " )"); 
00283   TAU_PROFILE("SIndex::removeIndex()", taustr, TAU_SPARSE);
00284 
00285   // cast away const; we are not modifying the NDIndex, so this should be ok
00286   NDIndex<Dim>& ndi((NDIndex<Dim> &)constndi);
00287 
00288   // calculate the total number of points, and counters for looping
00289   unsigned int d, totalnum = ndi.size();
00290   Index::iterator counter[Dim];
00291   for (d=0; d < Dim; ++d)
00292     counter[d] = ndi[d].begin();
00293 
00294   while (totalnum-- > 0) {
00295     // create an SOffset obj and add it to our lists
00296     SOffset<Dim> newpoint;
00297     for (d=0; d < Dim; ++d)
00298       newpoint[d] = *(counter[d]);
00299     removeIndex(newpoint);
00300 
00301     // increment the index iterators
00302     unsigned int chkdim = 0;
00303     while(chkdim < Dim) {
00304       ++(counter[chkdim]);
00305       if (counter[chkdim] == ndi[chkdim].end()) {
00306         counter[chkdim] = ndi[chkdim].begin();
00307         chkdim++;
00308       } else {
00309         break;
00310       }
00311     }
00312   }
00313 }
00314 
00315 
00317 // reserve storage space equal to the given fraction of the size of
00318 // each vnode.  if fraction=1.0, reserve storage for the entire vnode.
00319 template<unsigned int Dim>
00320 void SIndex<Dim>::reserve(double fraction) {
00321   for (iterator_iv a = begin_iv(); a != end_iv(); ++a) {
00322     typename LSIndex<Dim>::size_type newcapacity = (*a)->getDomain().size();
00323     if (fraction < 0.9999 && fraction > 0.0)
00324       newcapacity = static_cast<typename LSIndex<Dim>::size_type>(fraction *
00325                                 static_cast<double>(newcapacity));
00326     (*a)->reserve(newcapacity);
00327   }
00328 }
00329 
00330 
00332 // clear out the existing indices
00333 template<unsigned int Dim>
00334 void SIndex<Dim>::clear() {
00335   TAU_PROFILE("SIndex::clear()", "void ()", TAU_SPARSE);
00336 
00337   // tell all LSIndex objects to remove their points
00338   for (iterator_iv a = begin_iv(); a != end_iv(); ++a) {
00339     (*a).CopyForWrite();
00340     (*a)->clear();
00341   }
00342 }
00343 
00344 
00346 // return whether the given point is contained here
00347 template<unsigned int Dim>
00348 bool SIndex<Dim>::hasIndex(const SOffset<Dim>& so) const {
00349   TAU_TYPE_STRING(taustr, "bool (" + CT(so) + " )"); 
00350   TAU_PROFILE("SIndex::hasIndex()", taustr, TAU_SPARSE);
00351 
00352   for (const_iterator_iv a = begin_iv(); a != end_iv(); ++a)
00353     if ((*a)->hasIndex(so))
00354       return true;
00355   return false;
00356 }
00357 
00358 
00360 // assignment operator
00361 // NOTE: this right now only works properly when the layout's match
00362 template<unsigned int Dim>
00363 SIndex<Dim>& SIndex<Dim>::operator=(const SIndex<Dim>& si) {
00364   TAU_TYPE_STRING(taustr, CT(si) +  " (" + CT(si) + " )"); 
00365   TAU_PROFILE("SIndex::operator=()", taustr, TAU_SPARSE);
00366 
00367   if (&si != this) {
00368     // copy the offset and layout, checking ourselves in if necessary
00369     Offset = si.Offset;
00370     if (Layout == 0 || Layout != si.Layout) {
00371       if (Layout != 0)
00372         Layout->checkout(*this);
00373       Layout = si.Layout;
00374       Layout->checkin(*this);
00375     }
00376 
00377     // copy the list of index objects, replacing our current contents
00378     IndexList = si.IndexList;
00379 
00380     // copy the bounding box
00381     BoundingBox = si.BoundingBox;
00382   }
00383 
00384   return *this;
00385 }
00386 
00387 
00389 // assignment operator from a single SOffset.  This will leave this SIndex
00390 // with just the one point.
00391 template<unsigned int Dim>
00392 SIndex<Dim>& SIndex<Dim>::operator=(const SOffset<Dim>& so) {
00393   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(so) + " )"); 
00394   TAU_PROFILE("SIndex::operator=()", taustr, TAU_SPARSE);
00395 
00396   // put in the single point
00397   clear();
00398   addIndex(so);
00399 
00400   // set our bounding box to just this point
00401   toNDIndex(so, BoundingBox);
00402 
00403   return *this;
00404 }
00405 
00406 
00408 // assignment operator from an NDIndex.  All the points in the index space
00409 // will be added.
00410 template<unsigned int Dim>
00411 SIndex<Dim>& SIndex<Dim>::operator=(const NDIndex<Dim>& ndi) {
00412   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(ndi) + " )"); 
00413   TAU_PROFILE("SIndex::operator=()", taustr, TAU_SPARSE);
00414 
00415   // put in all the points from the NDIndex
00416   clear();
00417   addIndex(ndi);
00418 
00419   // set our bounding box to this NDIndex domain
00420   BoundingBox = ndi;
00421 
00422   return *this;
00423 }
00424 
00425 
00427 // intersection operator, with another SIndex object.
00428 // NOTE: this right now only works properly when the layout's match
00429 template<unsigned int Dim>
00430 SIndex<Dim>& SIndex<Dim>::operator&=(const SIndex<Dim>& si) {
00431   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(si) + " )"); 
00432   TAU_PROFILE("SIndex::operator&=()", taustr, TAU_SPARSE);
00433 
00434   if (&si != this) {
00435     // for all our own points, only keep those which are in the other one
00436     SIndex<Dim> newval(*Layout);
00437     const_iterator_iv a  = begin_iv();
00438     const_iterator_iv ea = end_iv();
00439     iterator_iv na = newval.begin_iv();
00440     for ( ; a != ea; ++a, ++na) {
00441       typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
00442       typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
00443       for ( ; ls_i != ls_e ; ++ls_i) {
00444         if (si.hasIndex(*ls_i))
00445           newval.addIndex(na, *ls_i);
00446       }
00447     }
00448 
00449     // copy over the points to here
00450     *this = newval;
00451 
00452     // the bounding box of the intersection will be the intersection
00453     // of the two original bounding boxes
00454     BoundingBox = BoundingBox.intersect(si.BoundingBox);
00455   }
00456 
00457   return *this;
00458 }
00459 
00460 
00462 // intersection operator, with another SOffset object.
00463 template<unsigned int Dim>
00464 SIndex<Dim>& SIndex<Dim>::operator&=(const SOffset<Dim>& so) {
00465   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(so) + " )"); 
00466   TAU_PROFILE("SIndex::operator&=()", taustr, TAU_SPARSE);
00467 
00468   bool found = hasIndex(so);
00469   clear();
00470   if (found)
00471     addIndex(so);
00472   toNDIndex(so, BoundingBox);
00473 
00474   return *this;
00475 }
00476 
00477 
00479 // intersection operator, with the points in an NDIndex
00480 template<unsigned int Dim>
00481 SIndex<Dim>& SIndex<Dim>::operator&=(const NDIndex<Dim>& ndi) {
00482   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(ndi) + " )"); 
00483   TAU_PROFILE("SIndex::operator&=()", taustr, TAU_SPARSE);
00484 
00485   // for all our own points, only keep those which are in the other one
00486   SIndex<Dim> newval(*Layout);
00487   const_iterator_iv a  = begin_iv();
00488   const_iterator_iv ea = end_iv();
00489   iterator_iv na = newval.begin_iv();
00490   for ( ; a != ea; ++a, ++na) {
00491     typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
00492     typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
00493     for ( ; ls_i != ls_e ; ++ls_i) {
00494       if ((*ls_i).inside(ndi))
00495         newval.addIndex(na, *ls_i);
00496     }
00497   }
00498 
00499   // the bounding box of the intersection will be the intersection
00500   // of the two original bounding boxes
00501   BoundingBox = BoundingBox.intersect(ndi);
00502 
00503   // copy over the points to here
00504   *this = newval;
00505   return *this;
00506 }
00507 
00508 
00510 // union operator, with another SIndex or SOffset object.  This will
00511 // append the point if it is not already present.
00512 // NOTE: this right now only works properly when the layout's match.
00513 template<unsigned int Dim>
00514 SIndex<Dim>& SIndex<Dim>::operator|=(const SIndex<Dim>& si) {
00515   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(si) + " )"); 
00516   TAU_PROFILE("SIndex::operator|=()", taustr, TAU_SPARSE);
00517 
00518   if (&si != this) {
00519     const_iterator_iv a  = si.begin_iv();
00520     const_iterator_iv ea = si.end_iv();
00521     iterator_iv na = begin_iv();
00522     for ( ; a != ea; ++a, ++na) {
00523       typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
00524       typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
00525       for ( ; ls_i != ls_e ; ++ls_i)
00526         addIndex(na, *ls_i);
00527     }
00528 
00529     // just reset the bounding box to the original full domain
00530     BoundingBox = Layout->getDomain();
00531   }
00532 
00533   return *this;
00534 }
00535 
00536 
00538 // union operator, with another SIndex or SOffset object.  This will
00539 // append the point if it is not already present.
00540 template<unsigned int Dim>
00541 SIndex<Dim>& SIndex<Dim>::operator|=(const SOffset<Dim>& so) {
00542   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(so) + " )"); 
00543   TAU_PROFILE("SIndex::operator|=()", taustr, TAU_SPARSE);
00544 
00545   addIndex(so);
00546 
00547   // just reset the bounding box to the original full domain
00548   BoundingBox = Layout->getDomain();
00549 
00550   return *this;
00551 }
00552 
00553 
00555 // union operator, with an NDIndex object.  This just needs to add the
00556 // points in the NDIndex object
00557 template<unsigned int Dim>
00558 SIndex<Dim>& SIndex<Dim>::operator|=(const NDIndex<Dim>& ndi) {
00559   TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(ndi) + " )"); 
00560   TAU_PROFILE("SIndex::operator|=()", taustr, TAU_SPARSE);
00561 
00562   addIndex(ndi);
00563 
00564   // just reset the bounding box to the original full domain
00565   BoundingBox = Layout->getDomain();
00566 
00567   return *this;
00568 }
00569 
00570 
00572 // () operators which make a copy of this SIndex with an extra offset.
00573 // These are functionally identical to the operator+, but provide a
00574 // nicer syntax.  That is, si(1,1) means  si + SOffset<Dim>(1,1)
00575 template<unsigned int Dim>
00576 SIndex<Dim> SIndex<Dim>::operator()(int i0) {
00577   TAU_TYPE_STRING(taustr, CT(*this) + " (int)"); 
00578   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00579 
00580   CTAssert(Dim==1);
00581   return SIndex(*this, SOffset<Dim>(i0));
00582 }
00583 
00584 template<unsigned int Dim>
00585 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1) {
00586   TAU_TYPE_STRING(taustr, CT(*this) + " (int, int)"); 
00587   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00588   CTAssert(Dim==2);
00589   return SIndex(*this, SOffset<Dim>(i0,i1));
00590 }
00591 
00592 template<unsigned int Dim>
00593 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2) {
00594   TAU_TYPE_STRING(taustr, CT(*this) + " (int, int, int)"); 
00595   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00596 
00597   CTAssert(Dim==3);
00598   return SIndex(*this, SOffset<Dim>(i0,i1,i2));
00599 }
00600 
00601 template<unsigned int Dim>
00602 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3) {
00603   TAU_TYPE_STRING(taustr, CT(*this) + " (int, int, int, int)"); 
00604   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00605 
00606   CTAssert(Dim==4);
00607   return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3));
00608 }
00609 
00610 template<unsigned int Dim>
00611 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3, int i4) {
00612   TAU_TYPE_STRING(taustr, CT(*this) + " (int, int, int, int, int)"); 
00613   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00614 
00615   CTAssert(Dim==5);
00616   return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3,i4));
00617 }
00618 
00619 template<unsigned int Dim>
00620 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3, int i4,
00621                                     int i5) {
00622   TAU_TYPE_STRING(taustr, CT(*this) + " (int, int, int, int, int, int)"); 
00623   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00624 
00625   CTAssert(Dim==6);
00626   return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3,i4,i5));
00627 }
00628 
00629 template<unsigned int Dim>
00630 SIndex<Dim> SIndex<Dim>::operator()(const SOffset<Dim>& so) {
00631   TAU_TYPE_STRING(taustr, CT(*this) + " ("  + CT(so) + " )"); 
00632   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00633 
00634   return SIndex(*this, so);
00635 }
00636 
00637 template<unsigned int Dim>
00638 SIndex<Dim> SIndex<Dim>::operator()(const int *so) {
00639   TAU_TYPE_STRING(taustr, CT(*this) + " ("  + CT(so) + " )");
00640   TAU_PROFILE("SIndex::operator()", taustr, TAU_SPARSE);
00641 
00642   return SIndex(*this, SOffset<Dim>(so));
00643 }
00644 
00645 
00647 // operator[], which is used with Index or NDIndex objects to further
00648 // subset the data.  This will only work if the dimension of the Index
00649 // arguments + Brackets is <= Dim.  Otherwise, too many dimensions worth
00650 // of Index objects are being applied
00651 template<unsigned int Dim>
00652 IndexedSIndex<Dim,1> SIndex<Dim>::operator[](const Index &i) {
00653   TAU_TYPE_STRING(taustr, CT(*this) + " (Index)"); 
00654   TAU_PROFILE("SIndex::operator[]", taustr, TAU_SPARSE);
00655 
00656   CTAssert(Dim >= 1);
00657   NDIndex<Dim> dom;
00658   dom[0] = i;
00659   return IndexedSIndex<Dim,1>(*this, dom);
00660 }
00661 
00662 
00663 
00665 // convert from the given SOffset value to an NDIndex, with offset added
00666 template<unsigned int Dim>
00667 void SIndex<Dim>::toNDIndex(const SOffset<Dim>& val, NDIndex<Dim>& NDI) {
00668   TAU_TYPE_STRING(taustr, "void ("  + CT(val) + ", " + CT(NDI) + " )"); 
00669   TAU_PROFILE("SIndex::toNDIndex()", taustr, TAU_SPARSE);
00670 
00671   for (unsigned int d=0; d < Dim; ++d) {
00672     int m = val[d] + Offset[d];
00673     NDI[d] = Index(m, m);
00674   }
00675 }
00676 
00677 
00679 // return the total size, which is the sum of the individual sizes
00680 template<unsigned int Dim>
00681 typename SIndex<Dim>::size_type_iv SIndex<Dim>::size() const {
00682   TAU_TYPE_STRING(taustr, CT(*this) + " ()"); 
00683   TAU_PROFILE("SIndex::size", taustr, TAU_SPARSE);
00684   
00685   size_type_iv retval = 0;
00686   for (const_iterator_iv a = begin_iv(); a != end_iv(); ++a)
00687     retval += (*a)->size();
00688 
00689   return retval;
00690 }
00691 
00692 
00694 // change to using a new layout.
00695 // NOTE: this needs to be fixed to properly redistribute points to
00696 // their proper nodes.
00697 template<unsigned int Dim>
00698 void SIndex<Dim>::setFieldLayout(FieldLayout<Dim>& fl) {
00699   TAU_TYPE_STRING(taustr, "void ("  + CT(fl) + " )"); 
00700   TAU_PROFILE("SIndex::setFieldLayout()", taustr, TAU_SPARSE);
00701 
00702   // create a new, empty SIndex
00703   SIndex<Dim> newindx(fl, Offset);
00704 
00705   // NOTE: PUT CODE TO REDISTRIBUTE POINTS PROPERLY HERE
00706 
00707 
00708   // copy over this new SIndex to ourselves
00709   *this = newindx;
00710 }
00711 
00712 
00714 // Repartition onto a new layout
00715 template<unsigned int Dim>
00716 void SIndex<Dim>::Repartition(UserList *userlist) {
00717   TAU_TYPE_STRING(taustr, "void ("  + CT(userlist) + " )"); 
00718   TAU_PROFILE("SIndex::Repartition()", taustr, TAU_SPARSE);
00719 
00720   if (Layout != 0 && userlist->getUserListID() == Layout->get_Id()) {
00721     // it is indeed our layout which is being repartitioned.  The easiest
00722     // way to do this is to just use the setFieldLayout with our current
00723     // layout, but which we now know is partitioned differently.
00724     setFieldLayout(*Layout);
00725   }
00726 }
00727 
00728 
00730 // Tell this object that an object is being deleted
00731 template<unsigned int Dim>
00732 void SIndex<Dim>::notifyUserOfDelete(UserList *userlist) {
00733   TAU_TYPE_STRING(taustr, "void ("  + CT(userlist) + " )"); 
00734   TAU_PROFILE("SIndex::notifyUserOfDelete()", taustr, TAU_SPARSE);
00735 
00736   if (Layout != 0 && userlist->getUserListID() == Layout->get_Id())
00737     Layout = 0;
00738 }
00739 
00740 
00742 // write contents to given ostream
00743 template<unsigned int Dim>
00744 ostream& operator<<(ostream& o, const SIndex<Dim>& si) {
00745   TAU_TYPE_STRING(taustr, "ostream (ostream, "  + CT(si) + " )"); 
00746   TAU_PROFILE("SIndex::operator<<()", taustr, TAU_SPARSE | TAU_IO);
00747 
00748   o << "vnodes = " << si.size_iv();
00749   o << ", offset = " << si.getOffset();
00750   o << ", bounding box = " << si.getDomain();
00751   o << ", points in each LField (w/offset):" << endl;
00752   for (typename SIndex<Dim>::const_iterator_iv a=si.begin_iv(); a!=si.end_iv(); ++a) {
00753     o << "  In LField w/domain=" << (*a)->getDomain() << ":" << endl;
00754     o <<   "    compressed = " << (*a)->IsCompressed() << endl;
00755     int lsize = (*a)->size();
00756     for (unsigned int i=0; i < lsize; ++i)
00757       o << "    " << (*a)->getIndex(i) + si.getOffset() << endl;
00758   }
00759 
00760   return o;
00761 }
00762 
00763 
00765 // print out debugging info
00766 template<unsigned int Dim>
00767 void SIndex<Dim>::printDebug(Inform& o) const {
00768   TAU_PROFILE("SIndex::printDebug()", "void (Inform)", TAU_SPARSE);
00769   
00770   o << *this << endl;
00771 }
00772 
00773 
00774 /***************************************************************************
00775  * $RCSfile: SIndex.cpp,v $   $Author: adelmann $
00776  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:27 $
00777  * IPPL_VERSION_ID: $Id: SIndex.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $ 
00778  ***************************************************************************/

Generated on Mon Jan 16 13:23:48 2006 for IPPL by  doxygen 1.4.6