src/Field/BrickIterator.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 BRICK_ITERATOR_H
00012 #define BRICK_ITERATOR_H
00013 
00014 // include files
00015 #include "Utility/Vec.h"
00016 #include "Utility/RefCounted.h"
00017 #include "Utility/Pooled.h"
00018 #include "Message/Message.h"
00019 #include "PETE/IpplExpressions.h"
00020 
00021 // forward declarations
00022 template <unsigned Dim> class NDIndex;
00023 
00024 // define away "restrict" if we need to
00025 #ifdef IPPL_NO_RESTRICT
00026 #define restrict 
00027 #endif
00028 
00029 
00030 //----------------------------------------------------------------------
00031 // A set of counters for a brick iterator.
00032 template<unsigned Dim>
00033 class BrickCounter
00034 {
00035 public: 
00036 
00037   // Null ctor takes no action.
00038   BrickCounter() {}
00039 
00040   // Construct to count over a contiguous block of user allocated memory.
00041   BrickCounter(const NDIndex<Dim>&);
00042 
00043   // Go to the next element.
00044   BrickCounter& operator++() { op_pp(); return *this; }
00045 
00046   // Finished stepping in dimension d?
00047   bool done(unsigned d) const { return Counters[d] == Counts[d]; }
00048 
00049   // Step in dimension d.
00050   void step(unsigned d)   { Counters[d] += 1; }
00051   void rewind(unsigned d) { Counters[d] = 0;  }
00052 
00053   // How big is it in dimension d?
00054   inline int size(unsigned d) const { return Counts[d]; }
00055 
00056   // Where are we now?
00057   int GetOffset(unsigned d) const { return Counters[d]; }
00058 
00059 protected: 
00060   void op_pp();
00061   vec<int,Dim> Counters; // Where are we now.
00062   vec<int,Dim> Counts;   // The number of elements in each direction.
00063 
00064 };
00065 
00066 
00067 //----------------------------------------------------------------------
00068 // An iterator for the elements of a brick of data.
00069 template<class T, unsigned Dim>
00070 class BrickIterator : public BrickCounter<Dim>
00071 {
00072 public:
00073 
00074   // Null ctor fills the current ptr with null. 
00075   BrickIterator() : Current(0), Whole(true) {}
00076 
00077   // Construct w/ an alloc ptr, Counted NDIndex and Alloc NDIndex
00078   BrickIterator(T*, const NDIndex<Dim>&, const NDIndex<Dim>&);
00079 
00080   // Construct with ptr, sizes.
00081   BrickIterator(T*, const vec<int,Dim>&);
00082 
00083   // Go to the next element.
00084   BrickIterator& operator++() { op_pp(); return *this; }
00085 
00086   // Does this iterator iterate over the entire (whole) brick?
00087   bool whole() const { return Whole; }
00088 
00089   // Two iterators are the same if they point to the same thing.
00090   bool operator==(const BrickIterator<T,Dim>& a) const
00091     {
00092       return Current == a.Current;
00093     }
00094   bool operator!=(const BrickIterator<T,Dim>& a) const
00095     {
00096       return Current != a.Current;
00097     }
00098 
00099   // Return what youre pointing to.
00100   T& operator*() const
00101     {
00102       return *Current;
00103     }
00104 
00105   // Move to new places.
00106   void step(unsigned d)
00107     {
00108       BrickCounter<Dim>::step( d );
00109       Current += Strides[ d ];
00110     }
00111   void rewind(unsigned d)
00112     {
00113       BrickCounter<Dim>::rewind( d );
00114       Current -= Strides[d]*BrickCounter<Dim>::Counts[d];
00115     }
00116 
00117   // Return something given an offset in one, two or three dimensions.
00118   T& offset(int i) const
00119     {
00120       return Current[ i*Strides[0] ];
00121     }
00122   T& offset(int i, int j) const
00123     {
00124       return Current[ i*Strides[0] + j*Strides[1] ];
00125     }
00126   T& offset(int i,int j,int k) const
00127     {
00128       return Current[ i*Strides[0]+ j*Strides[1] + k*Strides[2] ];
00129     }
00130   T& offset(int *i) const
00131     {
00132       return Current[ vec<int,Dim>::dot(i,&Strides[0]) ];
00133     }
00134   T& unit_offset(int i) const
00135     {
00136       return Current[ i ];
00137     }
00138   T& unit_offset(int i, int j) const
00139     {
00140       return Current[ i + j*Strides[1] ];
00141     }
00142   T& unit_offset(int i,int j,int k) const
00143     {
00144       return Current[ i+ j*Strides[1] + k*Strides[2] ];
00145     }
00146   void moveBy(int i)
00147     {
00148       Current += i*Strides[0];
00149       BrickCounter<Dim>::Counters[0] += i;
00150     }
00151   void moveBy(int i, int j)
00152     {
00153       Current += (i*Strides[0] + j*Strides[1]);
00154       BrickCounter<Dim>::Counters[0] += i;
00155       BrickCounter<Dim>::Counters[1] += j;
00156     }
00157   void moveBy(int i, int j, int k)
00158     {
00159       Current += (i*Strides[0] + j*Strides[1] + k*Strides[2]);
00160       BrickCounter<Dim>::Counters[0] += i;
00161       BrickCounter<Dim>::Counters[1] += j;
00162       BrickCounter<Dim>::Counters[2] += k;
00163     }
00164   void moveBy(const int *i)
00165     {
00166       for (unsigned int d=0; d < Dim; ++d) {
00167         Current += i[d] * Strides[d];
00168         BrickCounter<Dim>::Counters[d] += i[d];
00169       }
00170     }
00171   int Stride(int i) const { return Strides[i]; }
00172 
00173   // message passing interface ... for putMessage, the second argument
00174   // is used for an optimization for when the entire brick is being
00175   // sent.  If that is so, do not copy data into a new buffer, just
00176   // put the pointer into the message.  USE WITH CARE.  The default is
00177   // tohave putMessage make a copy of the data in the brick before adding
00178   // it to the message.  In many situations, this is required since the
00179   // data referred to by the iterator is not contiguous.  getMessage
00180   // has no such option, it always does the most efficient thing it can.
00181   Message& putMessage(Message&, bool makecopy = true);
00182   Message& getMessage(Message&);
00183 
00184   // PETE interface
00185   typedef T PETE_Return_t;
00186   typedef BrickIterator<T,Dim> PETE_Expr_t;
00187   PETE_Expr_t MakeExpression() const { return *this; }
00188 
00189 protected: 
00190   void op_pp();
00191   T* restrict Current;          // The current datum.
00192   vec<int,Dim> Strides;         // The strides in the data.
00193   bool Whole;                   // True if iterating over whole brick
00194 };
00195 
00197 
00198 #include "Field/BrickIterator.cpp"
00199 
00200 #endif // BRICK_ITERATOR_H
00201 
00202 /***************************************************************************
00203  * $RCSfile: BrickIterator.h,v $   $Author: adelmann $
00204  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00205  * IPPL_VERSION_ID: $Id: BrickIterator.h,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00206  ***************************************************************************/

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