src/Field/CompressedBrickIterator.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 COMPRESSED_BRICK_ITERATOR_H
00012 #define COMPRESSED_BRICK_ITERATOR_H
00013 
00014 // include files
00015 #include "Field/BrickIterator.h"
00016 
00017 #ifdef IPPL_USE_STANDARD_HEADERS
00018 #include <iostream>
00019 using namespace std;
00020 #else
00021 #include <iostream.h>
00022 #endif
00023 
00024 template<class T, unsigned Dim>
00025 class CompressedBrickIterator;
00026 
00028 
00029 // Global function that lets us fake member templates.
00030 template<class T, unsigned D1, unsigned D2>
00031 CompressedBrickIterator<T,D2>
00032 permute(const CompressedBrickIterator<T,D1>&,
00033         const NDIndex<D1>&, const NDIndex<D2>&);
00034 
00036 
00037 
00038 
00039 
00040 
00041 
00043 //
00044 // A version of BrickIterator that can do compression.
00045 // If it detects that the block it is pointing to is constant,
00046 // it can point to a single value and set its strides to zero.
00047 // The location it uses for that single value must be passed in
00048 // to the ctor.
00049 //
00051 
00052 template<class T, unsigned Dim>
00053 class CompressedBrickIterator : public BrickIterator<T,Dim>
00054 {
00055 public:
00056   // Replicate all the ctors from BrickIterator.
00057 
00058   // Construct w/
00059   //    a pointer to allocated memory
00060   //    owned NDIndex
00061   //    alloc NDIndex
00062   //    Location to store the compressed value.
00063   CompressedBrickIterator(T* t, const NDIndex<Dim>& c, const NDIndex<Dim>& a,
00064                           T& compressed)
00065     : BrickIterator<T,Dim>(t,c,a), CompressedData(&compressed)
00066     {
00067       if (!t) {
00068         BrickIterator<T,Dim>::Current = CompressedData;
00069         for (unsigned d=0; d<Dim; d++)
00070           BrickIterator<T,Dim>::Strides[d] = 0;
00071       }
00072     }
00073 
00074   // Construct w/
00075   //    a pointer to allocated memory
00076   //    sizes
00077   //    Location to store the compressed value.
00078   CompressedBrickIterator(T* t, const vec<int,Dim>& v, T& compressed)
00079     : BrickIterator<T,Dim>(t,v),CompressedData(&compressed)
00080     {
00081       if (!t) {
00082         BrickIterator<T,Dim>::Current = CompressedData;
00083         for (unsigned d=0; d<Dim; d++)
00084           BrickIterator<T,Dim>::Strides[d] = 0;
00085       }
00086     }
00087     
00088   // Construct with just a location for the compressed data.
00089   CompressedBrickIterator(T& t) : CompressedData(&t) {}
00090 
00091   // Null ctor for array allocations.
00092   // Not functional.  You have to overwrite this with a real one to use it.
00093   CompressedBrickIterator() : CompressedData(0) {}
00094 
00095   // Construct with just a domain and a compressed value.
00096   // This makes it compressed.
00097   CompressedBrickIterator(const NDIndex<Dim>& a, T& compressed);
00098 
00099   // Construct with a regular BrickIterator
00100   // and a place to store the compressed value.
00101   CompressedBrickIterator(const BrickIterator<T,Dim>& x, T& compressed)
00102     : BrickIterator<T,Dim>(x), CompressedData(&compressed)  {}
00103 
00104   // return true if it is currently compressed, false otherwise.
00105   bool IsCompressed() const
00106   {
00107     return BrickIterator<T,Dim>::Current == CompressedData;
00108   }
00109 
00110   // Check and see if it can compress.
00111   bool CanCompress(const T&) const;
00112 
00113   // Make it compress to a given value.
00114   void Compress(T& val);
00115 
00116   // Try to sparsify a CompressedBrickIterator.
00117   // Return true on success, false otherwise.
00118   // If it is already compressed it quickly returns true.
00119   bool TryCompress() { return TryCompress(**this); }
00120 
00121   // Here is a version that lets the user specify a value
00122   // to try sparsifying on.
00123   bool TryCompress(T val);
00124 
00125   // Since this has a potentially self-referential pointer,
00126   // we need the copy ctor and assignment operator to deal with it.
00127   const CompressedBrickIterator<T,Dim>&
00128   operator=(const CompressedBrickIterator<T,Dim>& rhs);
00129 
00130   CompressedBrickIterator(const CompressedBrickIterator<T,Dim>& X);
00131 
00132   // put data into a message to send to another node
00133   // ... for putMessage, the second argument
00134   // is used for an optimization for when the entire brick is being
00135   // sent.  If that is so, do not copy data into a new buffer, just
00136   // put the pointer into the message.  USE WITH CARE.  The default is
00137   // tohave putMessage make a copy of the data in the brick before adding
00138   // it to the message.  In many situations, this is required since the
00139   // data referred to by the iterator is not contiguous.  getMessage
00140   // has no such option, it always does the most efficient thing it can.
00141   Message& putMessage(Message& m, bool makecopy = true);
00142 
00143   // get data out from a message
00144   Message& getMessage(Message& m);
00145 
00146   // Permute the order of the loops (given by the first NDIndex) 
00147   // to correspond to the order in the second NDIndex.
00148   // Obviously this would be better done as a member template,
00149   // but we can fake it with a global function and some accessor functions.
00150   CompressedBrickIterator<T,1>
00151   permute(NDIndex<Dim>& current, NDIndex<1>& permuted) const
00152   { return ::permute(*this,current,permuted); }
00153   CompressedBrickIterator<T,2>
00154   permute(NDIndex<Dim>& current, NDIndex<2>& permuted) const
00155   { return ::permute(*this,current,permuted); }
00156   CompressedBrickIterator<T,3>
00157   permute(NDIndex<Dim>& current, NDIndex<3>& permuted) const
00158   { return ::permute(*this,current,permuted); }
00159   CompressedBrickIterator<T,4>
00160   permute(NDIndex<Dim>& current, NDIndex<4>& permuted) const
00161   { return ::permute(*this,current,permuted); }
00162   CompressedBrickIterator<T,5>
00163   permute(NDIndex<Dim>& current, NDIndex<5>& permuted) const
00164   { return ::permute(*this,current,permuted); }
00165   CompressedBrickIterator<T,6>
00166   permute(NDIndex<Dim>& current, NDIndex<6>& permuted) const
00167   { return ::permute(*this,current,permuted); }
00168   // The global function permute needs some special accessor functions.
00169   void SetCurrent(T* p) { BrickIterator<T,Dim>::Current = p; }
00170   void SetCount(int d, int count) { BrickCounter<Dim>::Counts[d] = count; }
00171   void ResetCounter(int d) { BrickCounter<Dim>::Counters[d] = 0; }
00172   void SetStride(int d, int stride) { BrickIterator<T,Dim>::Strides[d] = stride; }
00173   int GetStride(int d) const { return BrickIterator<T,Dim>::Strides[d]; }
00174   T& GetCompressedData() const { return *CompressedData; }
00175   void SetCompressedData(T *newData)
00176   { 
00177     CompressedData = newData;
00178   }
00179 
00180 private:
00181   // If you are able to be compressed, put the constant value here.
00182   T* CompressedData;
00183 
00184 };
00185 
00186 
00187 #include "Field/CompressedBrickIterator.cpp"
00188 
00189 #endif // COMPRESSED_BRICK_ITERATOR_H
00190 
00191 /***************************************************************************
00192  * $RCSfile: CompressedBrickIterator.h,v $   $Author: adelmann $
00193  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00194  * IPPL_VERSION_ID: $Id: CompressedBrickIterator.h,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00195  ***************************************************************************/
00196 

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