src/SubField/SubFieldIter.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 #ifndef SUB_FIELD_ITER_H
00012 #define SUB_FIELD_ITER_H
00013 
00014 /***************************************************************************
00015   SubFieldIter is a class is required for each type of object which is used to
00016   store a subset for a BareField.  For example, NDIndex specifies a rect-
00017   angular block, SIndex specifies a (sparse) list of individual elements,
00018   and SOffset specifies a single point (which is assumed to be the same
00019   on all nodes).  SubFieldIter acts as the iterator for the SubBareField
00020   class which uses that particular type of subset object to select a view of
00021   the field.
00022 
00023   To add a new subset object and define a new SubFieldIter class:
00024     * Add a new item to the enumeration at the top of this file.
00025     * Define a new SubFieldIter class, templated on the type of object (e.g.,
00026        NDIndex<Dim>), following the pattern for the examples below.  The
00027        required elements in SubFieldIter are
00028        (which can be set up by copying an existing class and modifying it):
00029 
00030        - derive from SubFieldIterBase
00031 
00032        - two construction options, one with needed iterator args, the other
00033          a default constructor (this is needed by PETE).  You can also
00034          define a copy constructor, or else make sure that element-wise
00035          copying will suffice for your iterator class.
00036 
00037        - override the versions of all the functions in the base class which
00038          need to be overridden, to supply the special functionality for that
00039          subset.  For example, some classes need special initialization when
00040          they are used in an expression - if so, make a specific version of
00041          'initialize' in your subset specialization class.
00042 
00043        - add specialization in SubFieldTraits to indicate how this subset
00044          object can be constructed from other subset objects, and what kind
00045          of combinations of subset objects will work.
00046 
00047        - static bool matchType(int t) { return (t == Type_u); } ... return
00048          whether the type of subset object matches the given type.  Some
00049          objects, like SOffset, match all subset types (since SOffset used
00050          as a subset object appears to the rest of the expression like a
00051          single value, e.g., as a scalar.
00052 
00053        - static void makeNDIndex(Subset_t& s, NDIndex<Dim>& i) ... convert
00054          the given subset object data to an NDIndex
00055 
00056        - bool findIntersection() { } ... find the intersection between a
00057          the current component and a given NDIndex, and return the intersection
00058          as an NDIndex.  Also return a boolean flag indicating if this
00059          intersection did indeed contain some points (true).  This is then used
00060          in a BrickExpression to take data from the RHS and store it into the
00061          LHS.  findIntersection is only called for an iterator which occurs
00062          on the LHS; if something is on the RHS, then plugBase will be called
00063          instead, with an argument of the domain as calculated by
00064          findIntersection.
00065 
00066        - void nextLField() { } ... for subsets which must keep track of their
00067          current vnode (e.g., SIndex), this increments a vnode iterator.
00068 
00069        - NDIndex<Dim> plugBase(const NDIndex<Dim>& i) const ... this is the
00070          function which takes the NDIndex component on the LHS, and plugs it
00071          in to the RHS.  This results in each SubBareField on the RHS setting
00072          internal iterators to point to the proper section of data
00073          based on any offsets it may have and on the subset from the LHS.
00074          For some subset objects, this will not depend on the given subdomain.
00075 
00076        - setLFieldData(LField<T,Dim>*, NDIndex<Dim>&) ... for iterators
00077          which occur on the LHS of an expression, the LField referred to by
00078          its internal LField iterator may need to be changed to a new one
00079          which is a copy of the existing LField (to handle the case where a
00080          Field occurs on the LHS and the RHS).  This function, which has a
00081          default definition, changes the iterator to use a different LField
00082          and to iterate over the region specified in the second argument.
00083          It is only called for iterators on the LHS.
00084 
00085        - bool CanTryCompress() ... Some subset objects cannot easily be
00086          used on the LHS with compressed LFields.  If the new one can not
00087          (for example, if it is not possible to determine if all the points
00088          referred to by the subset have the same value), this should return
00089          false, and all the other compression routines can just be no-ops.
00090 
00091  ***************************************************************************/
00092 
00093 
00094 // include files
00095 #include "Index/NDIndex.h"
00096 #include "Index/SIndex.h"
00097 #include "Field/BareField.h"
00098 #include "Field/LField.h"
00099 #include "Utility/PAssert.h"
00100 #include "PETE/IpplExpressions.h"
00101 
00102 
00104 // type codes for different subset objects
00105 enum { NoSubsetType, NDIndexSubsetType, SIndexSubsetType, SOffsetSubsetType };
00106 
00107 
00109 // A base class for all specialized versions of the SubFieldIter class.
00110 // This provides common functionality and storage, and default versions of
00111 // functions which may be overridden in the specialized classes.
00112 
00113 template<class T, unsigned int Dim, class S, unsigned int ExprDim>
00114 class SubFieldIterBase {
00115 
00116 public:
00117   // How many indices we must loop over when doing an expression involving
00118   // this object
00119   enum { ExprDim_u = ExprDim };
00120 
00121   // Construct with a SubField and the domain to use
00122   SubFieldIterBase(const BareField<T,Dim>& df,
00123                    const typename BareField<T,Dim>::iterator_if& ldf,
00124                    const S& s,
00125                    unsigned int B)
00126     : MyBareField(&(const_cast<BareField<T,Dim> &>(df))),
00127       MyDomain(&(const_cast<S&>(s))),
00128       CurrentLField(ldf),
00129       MyBrackets(B) {
00130         LFPtr = (*CurrentLField).second.get();
00131   }
00132 
00133   // Default constructor
00134   SubFieldIterBase() { }
00135 
00136   // destructor: nothing to do
00137   ~SubFieldIterBase() { }
00138 
00139   // Return the BareField, for which this iterator represents a particular
00140   // subset or view of
00141   BareField<T,Dim> &getBareField() { return *MyBareField; }
00142   const BareField<T,Dim> &getBareField() const { return *MyBareField; }
00143 
00144   // Return a copy of the current iterator pointing to the active LField
00145   typename BareField<T,Dim>::iterator_if getLFieldIter() const {
00146     return CurrentLField;
00147   }
00148 
00149   // Return the subset object
00150   S &getDomain() { return *MyDomain; }
00151   const S &getDomain() const { return *MyDomain; }
00152 
00153   // Check if our brackets are properly balanced
00154   bool checkBrackets() const { return MyBrackets == Dim; }
00155   unsigned int getBrackets() const { return MyBrackets; }
00156 
00157   // Go to the next LField.
00158   typename BareField<T,Dim>::iterator_if nextLField() {
00159     ++CurrentLField;
00160     LFPtr = (*CurrentLField).second.get();
00161     return CurrentLField;
00162   }
00163 
00164   // Return the LField pointed to by LFPtr
00165   LField<T,Dim>* getLField() { return LFPtr; }
00166   const LField<T,Dim>* getLField() const { return LFPtr; }
00167 
00168   // Use a new LField
00169   void setLField(LField<T,Dim>* p) { LFPtr = p; }
00170 
00171   // Use a new LField, where we use data on the given NDIndex region
00172   void setLFieldData(LField<T,Dim>* p, NDIndex<Dim>&)  { LFPtr = p; }
00173 
00174   /* tjw 3/3/99: try to mimic changes made in 
00175      IndexedBareFieldIterator::FillGCIfNecessary:
00176 
00177   // Fill the guard cells for our field, if necessary.  We punt on
00178   // trying to check for a stencil op, just fill GC's if the Field has
00179   // it's dirty flag set.
00180   // If we were trying to check for a stencil op, the arguments are
00181   // the domain we are doing the expression on, and the NDIndex domain
00182   // which is the bounding box for this subset object.
00183   void FillGCIfNecessary(const NDIndex<Dim> &, const NDIndex<Dim> &) {
00184     bool isdirty = getBareField().isDirty();
00185     // bool isstencil = isStencil(i, j);
00186     // if (isdirty && isstencil) {
00187     if (isdirty)
00188       getBareField().fillGuardCells();
00189   }
00190   tjw 3/3/99 */
00191 
00192   //tjw 3/3/99:
00193   // Fill the guard cells for our field, if necessary.  We punt on
00194   // trying to check for a stencil op, just fill GC's if the Field has
00195   // it's dirty flag set.
00196   // If we were trying to check for a stencil op, the arguments are
00197   // the domain we are doing the expression on, and the NDIndex domain
00198   // which is the bounding box for this subset object.
00199   void FillGCIfNecessary() const {
00200     bool isdirty = this->getBareField().isDirty();
00201     if (isdirty)
00202       ( const_cast<BareField<T,Dim> &>(this->getBareField()) ).fillGuardCells();
00203   }
00204   //tjw 3/3/99.
00205 
00206 private:
00207   // ptr to the subfield we are iterating over
00208   BareField<T,Dim>* MyBareField;
00209 
00210   // pointer to the subset object
00211   S* MyDomain;
00212 
00213   // a pointer to the LField we're working with, which generally starts out
00214   // as the LField pointed to by CurrentLField, but can change if, say, we're
00215   // using a copy of the LField on the LHS of an expression
00216   LField<T,Dim>* LFPtr;
00217 
00218   // iterator pointing to the current LField we're looping over
00219   typename BareField<T,Dim>::iterator_if CurrentLField;
00220 
00221   // how many brackets have been applied so far
00222   unsigned int MyBrackets;
00223 };
00224 
00225 
00227 // The general subset-object-templated class definition for the SubField
00228 // iterator.
00229 
00230 template<class T, unsigned int Dim, class S>
00231 class SubFieldIter { };
00232 
00233 
00235 // A specialized versions of the SubFieldIter class for an NDIndex
00236 // subset object.  This overrides certain functions from the base class,
00237 // and provides definitions of needed functions not available in the base.
00238 
00239 template<class T, unsigned int Dim>
00240 class SubFieldIter<T, Dim, NDIndex<Dim> >
00241   : public SubFieldIterBase<T, Dim, NDIndex<Dim>, Dim>,
00242     public PETE_Expr<SubFieldIter<T, Dim, NDIndex<Dim> > >
00243 {
00244 
00245 public:
00246   // public typedefs
00247   typedef NDIndex<Dim>                   Subset_t;
00248   typedef SubFieldIter<T, Dim, Subset_t> SFI;
00249 
00250   // Construct with a SubField and the domain to use
00251   SubFieldIter(const BareField<T,Dim>& df,
00252                const typename BareField<T,Dim>::iterator_if& ldf,
00253                const NDIndex<Dim>& s, unsigned int B)
00254     : SubFieldIterBase<T,Dim,Subset_t,Dim>(df, ldf, s, B) { }
00255 
00256   // Default constructor
00257   SubFieldIter() { }
00258 
00259   // destructor: nothing to do
00260   ~SubFieldIter() { }
00261 
00262   //
00263   // Methods overriding base class behavior
00264   //
00265 
00266   // Use a new LField, where we use data on the given NDIndex region
00267   void setLFieldData(LField<T,Dim>* p, NDIndex<Dim>& n)  {
00268     SubFieldIterBase<T,Dim,Subset_t,Dim>::setLFieldData(p, n);
00269     P = this->getLField()->begin(n);
00270   }
00271 
00272   // Return a special code indicating what the subset type is, and match the
00273   // types together.
00274   static int  getSubsetType()  { return NDIndexSubsetType; }
00275   static bool matchType(int t) { return (t == NDIndexSubsetType); }
00276 
00277   // If necessary, this routine will distribute any data it needs to
00278   // among the processors.  For example, single-value subset objects must
00279   // broadcast the single value to all the nodes.
00280   void initialize() { }
00281 
00282   // Calculate the intersection with the current component and the given
00283   // subdomain.  Return true if an intersection exists, and the intersection
00284   // domain in the second argument.
00285   bool findIntersection(const NDIndex<Dim>& loc, NDIndex<Dim>& inter) {
00286     inter = this->getDomain().intersect(loc);
00287     return ( ! inter.empty() );
00288   }
00289 
00290   // convert this subset object into an NDIndex object
00291   static void makeNDIndex(const Subset_t& s, NDIndex<Dim>& i) { i = s; }
00292 
00293   // The LHS tells this guy about a given local domain.  Not all
00294   // subsetting operations will care about this.  The LField iterator P
00295   // will be set in this call to iterate through the values it needs to.
00296   bool plugBase(const NDIndex<Dim>& i) {
00297     // make sure we have a fully indexed object
00298     PInsist(this->checkBrackets(),"Field not fully indexed!!");
00299 
00300     // Find the modified domain after we plug in the information from what
00301     // domain is being iterated over on the LHS
00302     NDIndex<Dim> plugged = this->getDomain().plugBase(i);
00303 
00304     // Try to find a single local array that has all of the rhs.
00305     // Loop over all the local arrays.
00306     typename BareField<T,Dim>::iterator_if lf_i = this->getBareField().begin_if();
00307     typename BareField<T,Dim>::iterator_if lf_e = this->getBareField().end_if();
00308     for ( ; lf_i != lf_e; ++lf_i) {
00309       // is the search domain completely within the LField we're examining?
00310       if ((*lf_i).second->getAllocated().contains(plugged)) {
00311         // Found it.  Make this one current and go.
00312         setLFieldData((*lf_i).second.get(), plugged);
00313         return true;
00314       }
00315     }
00316 
00317     // Didn't find it.
00318     return false;
00319   }
00320 
00321   // Finished this dimension, rewind.
00322   void rewind(unsigned d) { P.rewind(d); }
00323 
00324   // Step one or n in a given dimension.
00325   void step(unsigned int d)        { P.step(d); }
00326   void step(unsigned int d, int n) { P.step(d, n); }
00327 
00328   // How big in this dimension.
00329   int size(unsigned d) const { return P.size(d); }
00330 
00331   // return the value currently pointed at, or offset in 1,2, or 3 dims
00332   T& operator*()                 { return *P; }
00333   T& offset()                    { return *P; }
00334   T& offset(int i)               { return P.offset(i); }
00335   T& offset(int i, int j)        { return P.offset(i, j); }
00336   T& offset(int i, int j, int k) { return P.offset(i, j, k); }
00337   T& unit_offset(int i)               { return P.unit_offset(i); }
00338   T& unit_offset(int i, int j)        { return P.unit_offset(i, j); }
00339   T& unit_offset(int i, int j, int k) { return P.unit_offset(i, j, k); }
00340   int Stride(int d) const { return P.Stride(d); }
00341 
00342   // Compression interface
00343   bool CanCompress() const    { return this->getLField()->CanCompress(); }
00344   void Compress(T v)          { return this->getLField()->Compress(v);   }
00345   bool TryCompress()          { return this->getLField()->TryCompress(); }
00346   bool TryCompress(T v)       { return this->getLField()->TryCompress(v);}
00347   bool IsCompressed() const   {
00348       PAssert(this->getLField()->IsCompressed() == P.IsCompressed());
00349       return this->getLField()->IsCompressed();
00350   }
00351   bool DomainCompressed() const { return true; }
00352 
00353   //
00354   // PETE Interface
00355   //
00356 
00357   enum        { IsExpr = 1 };
00358   typedef SFI PETE_Expr_t;
00359   typedef T   PETE_Return_t;
00360   PETE_Expr_t MakeExpression() const { return *this; }
00361 
00362 private:
00363   // where in this LField are we
00364   typename LField<T,Dim>::iterator P;
00365 };
00366 
00367 
00369 // A specialized versions of the SubFieldIter class for an SIndex
00370 // subset object.  This overrides certain functions from the base class,
00371 // and provides definitions of needed functions not available in the base.
00372 
00373 template<class T, unsigned int Dim>
00374 class SubFieldIter<T, Dim, SIndex<Dim> >
00375   : public SubFieldIterBase<T, Dim, SIndex<Dim>, 1U>,
00376     public PETE_Expr<SubFieldIter<T, Dim, SIndex<Dim> > >
00377 {
00378 public:
00379   // public typedefs
00380   typedef SIndex<Dim>                    Subset_t;
00381   typedef SubFieldIter<T, Dim, Subset_t> SFI;
00382 
00383   // Construct with a SubField and the domain to use
00384   SubFieldIter(const BareField<T,Dim>& df,
00385                const typename BareField<T,Dim>::iterator_if& ldf,
00386                const SIndex<Dim>& s, unsigned int B)
00387     : SubFieldIterBase<T,Dim,Subset_t,1U>(df, ldf, s, B) {
00388     ComponentLF = this->getDomain().begin_iv();
00389     computeLSOffset();
00390   }
00391 
00392   // Default constructor
00393   SubFieldIter() { }
00394 
00395   // destructor: nothing to do
00396   ~SubFieldIter() { }
00397 
00398   //
00399   // Methods overriding base class behavior
00400   //
00401 
00402   // Go to the next LField.
00403   typename BareField<T,Dim>::iterator_if nextLField() {
00404     typename BareField<T,Dim>::iterator_if lfi =
00405       SubFieldIterBase<T,Dim,Subset_t,1U>::nextLField();
00406     ++ComponentLF;
00407     computeLSOffset();
00408     return lfi;
00409   }
00410 
00411   // Return a special code indicating what the subset type is, and match the
00412   // types together.
00413   static int  getSubsetType()  { return SIndexSubsetType; }
00414   static bool matchType(int t) { return (t == SIndexSubsetType); }
00415 
00416   // If necessary, this routine will distribute any data it needs to
00417   // among the processors.  For example, single-value subset objects must
00418   // broadcast the single value to all the nodes.
00419   void initialize() { }
00420 
00421   // Calculate the intersection with the current LField domain and the
00422   // given subdomain.  Return true if an intersection exists, and the
00423   // intersection domain in the second argument.
00424   bool findIntersection(const NDIndex<Dim>&, NDIndex<Dim>& inter) {
00425     // If there are any points in the LField, we return the owned domain
00426     // for the LField.
00427     if ((*ComponentLF)->size() > 0) {
00428       inter = this->getLField()->getOwned();
00429       return true;
00430     }
00431     return false;
00432   }
00433 
00434   // convert this subset object into an NDIndex object
00435   static void makeNDIndex(const Subset_t& s, NDIndex<Dim>& i) {
00436     //i = s.getFieldLayout().getDomain();
00437     i = s.getDomain();
00438   }
00439 
00440   // The LHS tells this guy about a given local domain.  Not all
00441   // subsetting operations will care about this.
00442   bool plugBase(const NDIndex<Dim>&) { return true; }
00443 
00444   // Finished this dimension, rewind.
00445   void rewind(unsigned) { }
00446 
00447   // Step one or n in a given dimension.
00448   void step(unsigned int)      { }
00449   void step(unsigned int, int) { }
00450 
00451   // How big in this dimension
00452   int size(unsigned d) const { return (d == 0 ? (*ComponentLF)->size() : 0); }
00453 
00454   // return the value currently pointed at, or the Nth value.  We only provide
00455   // options for 1D, since SIndex looks like a 1D array of values to the
00456   // BrickExpression object.
00457   T& operator*()                 { return offset(0); }
00458   T& offset()                    { return offset(0); }
00459   T& offset(int i)               {
00460     SOffset<Dim> loc = (*ComponentLF)->getIndex(i);
00461     loc -= LFOffset;
00462     return this->getLField()->begin().offset(loc.begin());
00463   }
00464   T& unit_offset(int i)          { return offset(i); }
00465   int Stride(int)                { return 1; }
00466 
00467   // Compression interface
00468   bool CanCompress() const      { return false; }
00469   void Compress(T)              { }
00470   bool TryCompress()            { return false; }
00471   bool TryCompress(T)           { return false; }
00472   bool IsCompressed() const     { return this->getLField()->IsCompressed(); }
00473   bool DomainCompressed() const { return (*ComponentLF)->IsCompressed(); }
00474 
00475   //
00476   // PETE Interface
00477   //
00478 
00479   enum        { IsExpr = 1 };
00480   typedef SFI PETE_Expr_t;
00481   typedef T   PETE_Return_t;
00482   PETE_Expr_t MakeExpression() const { return *this; }
00483 
00484 private:
00485   typename Subset_t::iterator_iv ComponentLF;
00486   SOffset<Dim>                   LFOffset;
00487 
00488   // calculate the offset for the current LField.  This is the position of
00489   // the lower-left corner of owned domain, minus the offset we are adding to
00490   // our sparse indices.
00491   void computeLSOffset() {
00492     if (this->getLFieldIter() != this->getBareField().end_if()) {
00493       NDIndex<Dim> owned = this->getLField()->getOwned();
00494       for (unsigned int d=0; d < Dim; ++d)
00495         LFOffset[d] = (owned[d].first() - this->getDomain().getOffset()[d]);
00496     }
00497   }
00498 };
00499 
00500 
00502 // A specialized versions of the SubFieldIter class for an SOffset, which
00503 // is used to act as a single-value
00504 // subset object.  This overrides certain functions from the base class,
00505 // and provides definitions of needed functions not available in the base. 
00506 template<class T, unsigned int Dim>
00507 class SubFieldIter<T, Dim, SOffset<Dim> >
00508   : public SubFieldIterBase<T, Dim, SOffset<Dim>, 1U>,
00509     public PETE_Expr<SubFieldIter<T, Dim, SOffset<Dim> > >
00510 {
00511 
00512 public:
00513   // public typedefs
00514   typedef SOffset<Dim>                   Subset_t;
00515   typedef SubFieldIter<T, Dim, Subset_t> SFI;
00516 
00517   // Construct with a SubField and the domain to use
00518   SubFieldIter(const BareField<T,Dim>& df,
00519                const typename BareField<T,Dim>::iterator_if& ldf,
00520                const SOffset<Dim>& s, unsigned int B)
00521     : SubFieldIterBase<T,Dim,Subset_t,1U>(df, ldf, s, B), SingleValPtr(0) { }
00522 
00523   // Default constructor
00524   SubFieldIter() { }
00525 
00526   // destructor: nothing to do
00527   ~SubFieldIter() { }
00528 
00529   //
00530   // Methods overriding base class behavior
00531   //
00532 
00533   // Use a new LField, where we use data on the given NDIndex region
00534   void setLFieldData(LField<T,Dim>* p, NDIndex<Dim>& n)  {
00535     SubFieldIterBase<T,Dim,Subset_t,1U>::setLFieldData(p, n);
00536     // the following if test COULD be removed if we assume this function is
00537     // called after 'findIntersection' is called and while we're still working
00538     // on the same LField.
00539     if (n.contains(Component)) {
00540       SOffset<Dim> s = this->getDomain();
00541       NDIndex<Dim> owned = p->getOwned();
00542       for (unsigned int d=0; d < Dim; ++d)
00543         s[d] -= owned[d].first();
00544       SingleValPtr = &(p->begin().offset(s.begin()));
00545     }
00546   }
00547 
00548   // Return a special code indicating what the subset type is, and match the
00549   // types together.
00550   static int  getSubsetType()  { return SOffsetSubsetType; }
00551   static bool matchType(int)   { return true; }
00552 
00553   // initialization routines
00554   void initialize() {
00555     // make an NDIndex with the point in it
00556     makeNDIndex(this->getDomain(), Component);
00557 
00558     // distribute the value to all the nodes
00559     this->getBareField().getsingle(Component, SingleValStore);
00560   }
00561 
00562   // Calculate the intersection with the current component and the given
00563   // subdomain.  Return true if an intersection exists, and the intersection
00564   // domain in the second argument.
00565   bool findIntersection(const NDIndex<Dim>& loc, NDIndex<Dim>& inter) {
00566     inter = Component.intersect(loc);
00567     return ( ! inter.empty() );
00568   }
00569 
00570   // convert this subset object into an NDIndex object
00571   static void makeNDIndex(const Subset_t& s, NDIndex<Dim>& i) {
00572     for (unsigned int d=0; d < Dim; ++d)
00573       i[d] = Index(s[d], s[d]);
00574   }
00575 
00576   // The LHS tells this guy about a given local domain.  Not all
00577   // subsetting operations will care about this.
00578   bool plugBase(const NDIndex<Dim>&) { return true; }
00579 
00580   // Finished this dimension, rewind.
00581   void rewind(unsigned) { }
00582 
00583   // Step one or n in a given dimension.
00584   void step(unsigned int)      { }
00585   void step(unsigned int, int) { }
00586 
00587   // How big in this dimension.
00588   int size(unsigned int d) const { return (d == 0 ? 1 : 0); }
00589 
00590   // return the value currently pointed at, or the Nth value.  We only provide
00591   // options for 1D, since SOffset looks like a 1D array of values to the
00592   // BrickExpression object.
00593   T& operator*()                 { return offset(0); }
00594   T& offset()                    { return offset(0); }
00595   T& offset(int)                 {
00596     return (SingleValPtr == 0 ? SingleValStore : *SingleValPtr);
00597   }
00598   T& unit_offset(int)            { return offset(0); }
00599   int Stride(int d)              { return 0; }
00600 
00601   // Compression interface
00602   bool CanCompress() const      { return false; }
00603   void Compress(T)              { }
00604   bool TryCompress()            { return false; }
00605   bool TryCompress(T)           { return false; }
00606   bool IsCompressed() const     { return false; }
00607   bool DomainCompressed() const { return true; }
00608 
00609   //
00610   // PETE Interface
00611   //
00612 
00613   enum        { IsExpr = 1 };
00614   typedef SFI PETE_Expr_t;
00615   typedef T   PETE_Return_t;
00616   PETE_Expr_t MakeExpression() const { return *this; }
00617 
00618 private:
00619   T* SingleValPtr;
00620   T  SingleValStore;
00621   NDIndex<Dim> Component;
00622 };
00623 
00624 
00625 #endif // SUB_FIELD_ITER_H
00626 
00627 /***************************************************************************
00628  * $RCSfile: SubFieldIter.h,v $   $Author: adelmann $
00629  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00630  * IPPL_VERSION_ID: $Id: SubFieldIter.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00631  ***************************************************************************/

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