src/Field/BrickIterator.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 "Field/AssignDefs.h"
00028 #include "Index/NDIndex.h"
00029 #include "Utility/PAssert.h"
00030 #include "Profile/Profiler.h"
00031 
00033 // BrickCounter methods
00034 
00035 template<unsigned Dim>
00036 BrickCounter<Dim>::BrickCounter(const NDIndex<Dim>& counted)
00037 {
00038   // Remove this profiling because this is too lightweight.
00039   // TAU_TYPE_STRING(taustr, "void (" + CT(counted) + " )" );
00040   // TAU_PROFILE("BrickCounter::BrickCounter()", taustr, TAU_FIELD);
00041   for (unsigned d=0; d<Dim; ++d)
00042     {
00043       BrickCounter<Dim>::Counters[d] = 0;
00044       BrickCounter<Dim>::Counts[d] = counted[d].length();
00045     }
00046 }
00047 
00049 
00050 template<unsigned Dim>
00051 void
00052 BrickCounter<Dim>::op_pp()
00053 {
00054   // Remove this profiling because this is too lightweight.
00055   // TAU_TYPE_STRING(taustr, CT(*this) + " void ()" );
00056   // TAU_PROFILE("BrickCounter::op_pp()", taustr, TAU_FIELD);
00057   for (unsigned d=0; d<Dim; ++d) {
00058     step(d);
00059     if ( BrickCounter<Dim>::Counters[d] != BrickCounter<Dim>::Counts[d] )
00060       return;
00061     rewind(d);
00062   }
00063   // If we get to here we have looped over the whole thing.
00064 }
00065 
00066 
00068 // BrickIterator methods
00069 
00070 template<class T, unsigned Dim>
00071 BrickIterator<T,Dim>::BrickIterator(T* p,
00072                                     const NDIndex<Dim>& counted,
00073                                     const NDIndex<Dim>& domalloc)
00074 : BrickCounter<Dim>(counted), Current(p), Whole(true)
00075 {
00076   // Remove this profiling because this is too lightweight.
00077   // TAU_TYPE_STRING(taustr, "void (" + CT(p) + ", " + CT(counted) + ", " + CT(alloc) + " )" );
00078   // TAU_PROFILE("BrickIterator::BrickIterator()", taustr, TAU_FIELD);
00079 
00080   // Calculate the strides,carriage returns and offset for the pointer.
00081   int n=1;
00082   for (unsigned d=0; d<Dim; ++d) {
00083     Strides[d] = n*counted[d].stride();
00084     Current += n*(counted[d].first() - domalloc[d].first());
00085     n *= domalloc[d].length();
00086     Whole = (Whole && counted[d] == domalloc[d]);
00087   }
00088 }
00089 
00091 
00092 template< class T, unsigned Dim >
00093 BrickIterator<T,Dim>::BrickIterator(T* p, const vec<int,Dim>& sizes)
00094 {
00095   // Remove this profiling because this is too lightweight.
00096   //TAU_TYPE_STRING(taustr, "void (" + CT(p) + ", " + CT(sizes) + " )" );
00097   //TAU_PROFILE("BrickIterator::BrickIterator()", taustr, TAU_FIELD);
00098 
00099   int n = 1;
00100   for (unsigned d=0; d<Dim; ++d) {
00101     BrickCounter<Dim>::Counts[d] = sizes[d];
00102     BrickCounter<Dim>::Counters[d] = 0;
00103     Strides[d] = n;
00104     n *= sizes[d];
00105   }
00106   Current = p;
00107   Whole = true;
00108 }
00109 
00111 
00112 template<class T, unsigned Dim>
00113 void
00114 BrickIterator<T,Dim>::op_pp()
00115 {
00116   // Remove this profiling because this is too lightweight.
00117   // TAU_TYPE_STRING(taustr, CT(*this) + " void ()" );
00118   // TAU_PROFILE("BrickIterator::op_pp()", taustr, TAU_FIELD);
00119 
00120   for (unsigned d=0; d<Dim; ++d) {
00121     step(d);
00122     if ( BrickCounter<Dim>::Counters[d] != BrickCounter<Dim>::Counts[d] )
00123       return;
00124     rewind(d);
00125   }
00126   // If we get to here we have looped over the whole thing.
00127   Current = 0;
00128 }
00129 
00130 
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 template<class T, unsigned Dim>
00142 Message& BrickIterator<T,Dim>::putMessage(Message& m, bool makecopy) {
00143   TAU_TYPE_STRING(taustr, "Message& (" + CT(m) + ", bool)" );
00144   TAU_PROFILE("BrickIterator::putMessage", taustr, TAU_FIELD|TAU_MESSAGE);
00145 
00146   int i, n, s[Dim];
00147 
00148   // put in the size of the data, and calculate total number of elements
00149   for (n=1, i=0; i < Dim; ++i) {
00150     s[i] = BrickCounter<Dim>::Counts[i];
00151     n *= BrickCounter<Dim>::Counts[i];
00152   }
00153   m.put(s, s + Dim);
00154 
00155   // Only add in the actual data if there is something to add.
00156   if (n > 0) {
00157     // If we are not required to make a copy, check if we can just add in
00158     // the pointer.  We can do this ONLY if we are adding in the entire
00159     // domain, and not a subset, of the original domain.
00160     if (!makecopy && whole()) {
00161       // We are iterating over the whole brick (not just a subset), and
00162       // we are not required to make a copy, so, well, don't.  Just put
00163       // in the pointer to the brick and ask the message NOT to delete
00164       // the data when the message is sent.
00165       m.setCopy(false);
00166       m.setDelete(false);
00167       m.putmsg((void *)Current, sizeof(T), n);
00168     } else {
00169       // FIX THIS!! Better to give a BrickIterator begin/end pair to
00170       // putMessage than to do this.
00171       T* cpydata = (T*) malloc(sizeof(T)*n);
00172       T* cpy     = cpydata;
00173       T* cpyend  = cpydata + n;
00174       BrickIterator<T, Dim> bi = *this;
00175       for (; cpy != cpyend; ++cpy, ++bi)
00176         new (cpy) T(*bi);
00177 
00178       // put data into this message
00179       m.setCopy(false);
00180       m.setDelete(true);
00181       m.putmsg((void *)cpydata, sizeof(T), n);
00182     }
00183   }
00184 
00185   return m;
00186 }
00187 
00188 
00190 // get data out from a message
00191 template<class T, unsigned Dim>
00192 Message& BrickIterator<T,Dim>::getMessage(Message& m) {
00193   TAU_TYPE_STRING(taustr, "Message& (" + CT(m) + " )" );
00194   TAU_PROFILE("BrickIterator::getMessage", taustr, TAU_FIELD|TAU_MESSAGE);
00195   int i, n, s[Dim];
00196 
00197   // this will only work if this iterator does not yet point
00198   // at any data
00199   PInsist(Current == 0,
00200           "Iterator already has data in BrickIterator::getMessage!!");
00201 
00202   // retrieve size of data in message, and set counters, strides, etc.
00203   m.get((int*) s);
00204   for (n=1, i=0; i < Dim; ++i) {
00205     BrickCounter<Dim>::Counts[i] = s[i];
00206     BrickCounter<Dim>::Counters[i] = 0;
00207     Strides[i] = n;
00208     n *= s[i];
00209   }
00210 
00211   // retrieve actual data into an allocated buffer
00212   // NOTE: This just stores a pointer to the data that is actually stored
00213   // in the Message item.  It does not make its own copy.  So, if you use
00214   // a BrickIterator to get data from a message, you must use the data in the
00215   // BrickIterator BEFORE you delete the Message.  Otherwise, you'll be
00216   // pointing at deallocated memory.
00217   /*
00218   Current = new T[n];
00219   ::getMessage_iter(m, Current);
00220   */
00221   Current = static_cast<T *>(m.item(0).data());
00222   m.get();
00223   return m;
00224 }
00225 
00226 
00227 
00228 /***************************************************************************
00229  * $RCSfile: BrickIterator.cpp,v $   $Author: adelmann $
00230  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00231  * IPPL_VERSION_ID: $Id: BrickIterator.cpp,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00232  ***************************************************************************/

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