OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
CompressedBrickIterator.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  * This program was prepared by PSI.
7  * All rights in the program are reserved by PSI.
8  * Neither PSI nor the author(s)
9  * makes any warranty, express or implied, or assumes any liability or
10  * responsibility for the use of this software
11  *
12  * Visit www.amas.web.psi for more details
13  *
14  ***************************************************************************/
15 
16 // -*- C++ -*-
17 /***************************************************************************
18  *
19  * The IPPL Framework
20  *
21  *
22  * Visit http://people.web.psi.ch/adelmann/ for more details
23  *
24  ***************************************************************************/
25 
26 // include files
28 #include "Utility/PAssert.h"
29 
30 
32 //
33 // The constructor that produces a compressed CompressedBrickIterator.
34 // All it really does is initialize the BrickIterator like normal
35 // except with a pointer to the CompressedData, with strides equal
36 // to zero.
37 //
39 
40 template<class T, unsigned Dim>
42 CompressedBrickIterator(const NDIndex<Dim>& o, T& compressed)
43 {
44 
45  // Point to the single data element.
46  BrickIterator<T,Dim>::Current = CompressedData = &compressed;
47  for (unsigned d=0; d<Dim; ++d)
48  {
49  // The counts start off at zero.
51  // The counts are just the lengths.
52  BrickCounter<Dim>::Counts[d] = o[d].length();
53  // Set all the strides to zero.
55  }
56 }
57 
59 //
60 // The routine that checks to see if all the values are the same.
61 // This is a regular function so that we can do compile time recursion.
62 //
64 
65 //
66 // CompressedLoopTag
67 //
68 // A tag that we can use to get the compile recursion to work.
69 //
70 // If B==true then we have an explicit function available.
71 // If B==false we need to use the general loop.
72 //
73 // If Dim>3 we use the general loop, but it calls the
74 // one for Dim-1 so the inner loops are always efficient.
75 //
76 
77 template<unsigned Dim, bool B=(Dim<=3)>
78 class CompressedLoopTag
79 {
80 #ifdef IPPL_PURIFY
81  // Add explicit default/copy constructors and op= to avoid UMR's.
82 public:
83  CompressedLoopTag() {}
84  CompressedLoopTag(const CompressedLoopTag<Dim,B> &) {}
85  CompressedLoopTag<Dim,B>&
86  operator=(const CompressedLoopTag<Dim,B> &) { return *this; }
87 #endif
88 };
89 
90 //
91 // Here is the one dimensional version that checks if all the values
92 // in a block are the same.
93 //
94 
95 template<class T, unsigned Dim>
96 inline bool
99  //mwerks CompressedLoopTag<1> )
100 {
101 
102  // Loop over all the elements.
103  int n = iter.size(0);
104  for (int i=0; i<n; ++i)
105  // If it is not the same, return failure.
106  if ( val != iter.offset(i) )
107  return false;
108  // If we get to here then all the values were the same.
109  return true;
110 }
111 
112 //
113 // Here is the two dimensional version that checks if all the values
114 // in a block are the same.
115 //
116 
117 template<class T, unsigned Dim>
118 inline bool
121  //mwerks CompressedLoopTag<2> )
122 {
123 
124  // Loop over all of the elements.
125  int n0 = iter.size(0);
126  int n1 = iter.size(1);
127 
128  if ( (n0>0)&&(n1>0) )
129  for (int i1=0; i1<n1; ++i1)
130  for (int i0=0; i0<n0; ++i0)
131  {
132  // If it is not the same, return failure.
133  if ( !(val == iter.offset(i0,i1)) )
134  return false;
135  }
136  // If we get to here then all the values were the same.
137  return true;
138 }
139 
140 //
141 // Here is the three dimensional version that checks if all the values
142 // in a block are the same.
143 //
144 
145 template<class T, unsigned Dim>
146 inline bool
149  //mwerks CompressedLoopTag<3> )
150 {
151 
152  // Loop over all of the elements.
153  int n0 = iter.size(0);
154  int n1 = iter.size(1);
155  int n2 = iter.size(2);
156  if ( (n0>0)&&(n1>0)&&(n2>0) )
157  for (int i2=0; i2<n2; ++i2)
158  for (int i1=0; i1<n1; ++i1)
159  for (int i0=0; i0<n0; ++i0)
160  // If it is not the same, return failure.
161  if ( !(val == iter.offset(i0,i1,i2)) )
162  return false;
163  // If we get to here then all the values were the same.
164  return true;
165 }
166 
167 //
168 // Here is the N dimensional version that checks if all the values
169 // in a block are the same.
170 //
171 // Note that for this one we pass iter by value instead of by
172 // reference because we use the step() member function.
173 //
174 
175 template<class T, unsigned Dim1, unsigned Dim2>
176 inline bool
179 {
180 
181  // Loop over the outermost dimension.
182  int n = iter.size(Dim2-1);
183  for (int i=0; i<n; ++i)
184  {
185  // Check if the next innermost dimension is all equal.
186  //mwerks if ( ! all_values_equal(iter,val,CompressedLoopTag<(Dim2-1)>()) )
187  if ( ! all_values_equal(iter,val,
188  CompressedLoopTag<(Dim2-1),((Dim2-1)<=3)>()) )
189  // If not, we're done.
190  return false;
191  // Otherwise step one in the outermost dimension.
192  iter.step(Dim2-1);
193  }
194  // If we get to here they were all equal.
195  return true;
196 }
197 
199 //
200 // The function that compresses the iterator if all the
201 // data it points to are equal to the given value.
202 //
204 
205 template<class T, unsigned Dim>
207 {
208 
209 
210  if ( IsCompressed() )
211  return *CompressedData == val;
212  else
213  return all_values_equal(*this,val,CompressedLoopTag<Dim,(Dim<=3)>());
214  //mwerks return all_values_equal(*this,val,CompressedLoopTag<Dim>());
215 }
216 
217 
218 // put data into a message to send to another node
219 // ... for putMessage, the second argument
220 // is used for an optimization for when the entire brick is being
221 // sent. If that is so, do not copy data into a new buffer, just
222 // put the pointer into the message. USE WITH CARE. The default is
223 // tohave putMessage make a copy of the data in the brick before adding
224 // it to the message. In many situations, this is required since the
225 // data referred to by the iterator is not contiguous. getMessage
226 // has no such option, it always does the most efficient thing it can.
227 template<class T, unsigned Dim>
229 {
230 
231  // Add in flag indicating if we're compressed. Put it in as an integer.
232  int compressed = (IsCompressed() ? 1 : 0);
233  m.put(compressed);
234  if (compressed == 1)
235  {
236  // If we are compressed, just add in the sizes and the value.
237  int s[Dim];
238  for (unsigned int i=0; i < Dim; ++i)
239  s[i] = BrickCounter<Dim>::size(i);
240  m.put(s, s + Dim);
242  }
243  else
244  {
245  // If uncompressed, just do as a normal BrickIterator.
247  }
248  return m;
249 }
250 
251 // get data out from a message
252 template<class T, unsigned Dim>
254 {
255  // Inform msg("CBI::getMessage", INFORM_ALL_NODES);
256  int compressed = 0;
257  m.get(compressed);
258  // msg << " Compressed = " << compressed << endl;
259  if (compressed == 1)
260  {
261  int s[Dim];
262  m.get((int*) s);
263  for (unsigned int i=0; i < Dim; ++i) {
264  BrickCounter<Dim>::Counts[i] = s[i];
267  }
268  PAssert(CompressedData != 0);
269  BrickIterator<T,Dim>::Current = CompressedData;
271  // msg << " Current value = " << *Current << endl;
272  // msg << " Compres value = " << *CompressedData << endl;
273  }
274  else
275  {
276  // ((BrickIterator<T,Dim>*)this)->getMessage(m);
278  }
279  return m;
280 }
281 
283 
284 template<class T, unsigned D1, unsigned D2>
287  const NDIndex<D1>& current, const NDIndex<D2>& perm)
288 {
289 
290  unsigned int d1, d2;
291 
292  // This is the iterator we'll be building.
294  if ( iter.IsCompressed() )
295  {
296  permute = CompressedBrickIterator<T,D2>( perm, *iter );
297  }
298  else
299  {
300  // Set the pointer to the same place as the one passed in.
301  permute.SetCurrent( &*iter );
302 
303  // Loop over each dimension of the iterator.
304  for (d2=0; d2<D2; ++d2)
305  {
306  // The size of the loop comes from the permuted NDIndex.
307  permute.SetCount(d2,perm[d2].length());
308  // Set the counters to zero.
309  permute.ResetCounter(d2);
310  // Set the stride to zero in case we don't find a match below.
311  permute.SetStride(d2,0);
312  // Check each Index in current to find a match.
313  for (d1=0; d1<D1; ++d1)
314  {
315  if ( current[d1].sameBase( perm[d2] ) )
316  {
317  // Found it. Get the stride for this loop.
318  permute.SetStride(d2,iter.GetStride(d1));
319  // On to the next.
320  break;
321  }
322  }
323  }
324  }
325  // Done constructing permute.
326  return permute;
327 }
328 
330 
331 template<class T, unsigned Dim>
335 {
336 
337  if ( this != &rhs )
338  {
339  *(dynamic_cast<BrickIterator<T,Dim>*>(this)) = rhs;
340  CompressedData = rhs.CompressedData;
341  }
342  return *this;
343 }
344 
346 
347 template<class T, unsigned Dim>
350  : BrickIterator<T,Dim>(X), CompressedData(X.CompressedData)
351 {
352 
353 }
354 
356 
357 // Make it compress to a given value.
358 // NOTE!!!! This function can only be useful in the following two contexts:
359 // 1. the iterator was constructed with specific internal storage for
360 // CompressedData; and this external storage will be modified (the new
361 // value 'val' will be written into the storage.
362 // 2. the iterator was constructed with no internal storage, and you call
363 // Compress with an external variable for which you can take the address
364 // and have 'CompressedData' point to.
365 template<class T, unsigned Dim>
366 void
368 {
369 
370 
371  // Inform msg("CBI::Compress", INFORM_ALL_NODES);
372  // msg << "Before storing value " << val << ": ";
373  // msg << "CompressedData = " << (void *)CompressedData;
374  if (CompressedData != 0) {
375  // msg << ", old deref value = " << *CompressedData;
376  *CompressedData = val;
377  // msg << ", new deref value = " << *CompressedData;
378  } else {
379  CompressedData = &val;
380  }
381  // msg << endl;
382  BrickIterator<T,Dim>::Current = CompressedData;
383  for (unsigned d=0; d<Dim; ++d)
385 }
386 
388 
389 // Here is a version that lets the user specify a value
390 // to try sparsifying on.
391 template<class T, unsigned Dim>
392 bool
394 {
395 
396 
397  // Inform msg("CBI::TryCompress", INFORM_ALL_NODES);
398  // msg << "Trying to compress to value " << val;
399  // msg << " : IsCompressed = " << IsCompressed() << endl;
400  if ( IsCompressed() )
401  return true;
402  if ( CanCompress(val) )
403  {
404  // msg << " Compressing now." << endl;
405  // NOTE!!!! This next call will ONLY work if this iterator was
406  // constructed with some external storage for the CompressedData.
407  // If at the time of this call CompressedData == 0, then this will
408  // just not work, since CompressedData will be set to the address of
409  // val which is a temporary variable only active within the scope of
410  // this function. (bfh)
411  Compress(val);
412  return true;
413  }
414  // msg << " Cannot compress." << endl;
415  return false;
416 }
417 
418 /***************************************************************************
419  * $RCSfile: CompressedBrickIterator.cpp,v $ $Author: adelmann $
420  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:26 $
421  * IPPL_VERSION_ID: $Id: CompressedBrickIterator.cpp,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $
422  ***************************************************************************/
Message & putMessage(Message &, bool makecopy=true)
Message & putMessage(Message &m, bool makecopy=true)
const CompressedBrickIterator< T, Dim > & operator=(const CompressedBrickIterator< T, Dim > &rhs)
Definition: rbendmap.h:8
Definition: rbendmap.h:8
T & offset(int i) const
bool all_values_equal(const CompressedBrickIterator< T, Dim > &iter, T val, CompressedLoopTag< 1, true >)
void getMessage_iter(Message &m, OutputIterator o)
Definition: Message.h:603
Message & getMessage(Message &)
Message & getMessage(Message &m)
CompressedBrickIterator< T, D2 > permute(const CompressedBrickIterator< T, D1 > &, const NDIndex< D1 > &, const NDIndex< D2 > &)
int size(unsigned d) const
Definition: BrickIterator.h:48
Message & get(const T &cval)
Definition: Message.h:484
Message & put(const T &val)
Definition: Message.h:414
void step(unsigned d)
bool CanCompress(const T &) const
#define PAssert(c)
Definition: PAssert.h:117
const unsigned Dim
void putMessage(Message &m, const T &t)
Definition: Message.h:557