OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
40template<class T, unsigned Dim>
42CompressedBrickIterator(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
77template<unsigned Dim, bool B=(Dim<=3)>
78class CompressedLoopTag
79{
80};
81
82//
83// Here is the one dimensional version that checks if all the values
84// in a block are the same.
85//
86
87template<class T, unsigned Dim>
88inline bool
91 //mwerks CompressedLoopTag<1> )
92{
93
94 // Loop over all the elements.
95 int n = iter.size(0);
96 for (int i=0; i<n; ++i)
97 // If it is not the same, return failure.
98 if ( val != iter.offset(i) )
99 return false;
100 // If we get to here then all the values were the same.
101 return true;
102}
103
104//
105// Here is the two dimensional version that checks if all the values
106// in a block are the same.
107//
108
109template<class T, unsigned Dim>
110inline bool
113 //mwerks CompressedLoopTag<2> )
114{
115
116 // Loop over all of the elements.
117 int n0 = iter.size(0);
118 int n1 = iter.size(1);
119
120 if ( (n0>0)&&(n1>0) )
121 for (int i1=0; i1<n1; ++i1)
122 for (int i0=0; i0<n0; ++i0)
123 {
124 // If it is not the same, return failure.
125 if ( !(val == iter.offset(i0,i1)) )
126 return false;
127 }
128 // If we get to here then all the values were the same.
129 return true;
130}
131
132//
133// Here is the three dimensional version that checks if all the values
134// in a block are the same.
135//
136
137template<class T, unsigned Dim>
138inline bool
141 //mwerks CompressedLoopTag<3> )
142{
143
144 // Loop over all of the elements.
145 int n0 = iter.size(0);
146 int n1 = iter.size(1);
147 int n2 = iter.size(2);
148 if ( (n0>0)&&(n1>0)&&(n2>0) )
149 for (int i2=0; i2<n2; ++i2)
150 for (int i1=0; i1<n1; ++i1)
151 for (int i0=0; i0<n0; ++i0)
152 // If it is not the same, return failure.
153 if ( !(val == iter.offset(i0,i1,i2)) )
154 return false;
155 // If we get to here then all the values were the same.
156 return true;
157}
158
159//
160// Here is the N dimensional version that checks if all the values
161// in a block are the same.
162//
163// Note that for this one we pass iter by value instead of by
164// reference because we use the step() member function.
165//
166
167template<class T, unsigned Dim1, unsigned Dim2>
168inline bool
171{
172
173 // Loop over the outermost dimension.
174 int n = iter.size(Dim2-1);
175 for (int i=0; i<n; ++i)
176 {
177 // Check if the next innermost dimension is all equal.
178 //mwerks if ( ! all_values_equal(iter,val,CompressedLoopTag<(Dim2-1)>()) )
179 if ( ! all_values_equal(iter,val,
180 CompressedLoopTag<(Dim2-1),((Dim2-1)<=3)>()) )
181 // If not, we're done.
182 return false;
183 // Otherwise step one in the outermost dimension.
184 iter.step(Dim2-1);
185 }
186 // If we get to here they were all equal.
187 return true;
188}
189
191//
192// The function that compresses the iterator if all the
193// data it points to are equal to the given value.
194//
196
197template<class T, unsigned Dim>
199{
200
201
202 if ( IsCompressed() )
203 return *CompressedData == val;
204 else
205 return all_values_equal(*this,val,CompressedLoopTag<Dim,(Dim<=3)>());
206 //mwerks return all_values_equal(*this,val,CompressedLoopTag<Dim>());
207}
208
209
210// put data into a message to send to another node
211// ... for putMessage, the second argument
212// is used for an optimization for when the entire brick is being
213// sent. If that is so, do not copy data into a new buffer, just
214// put the pointer into the message. USE WITH CARE. The default is
215// tohave putMessage make a copy of the data in the brick before adding
216// it to the message. In many situations, this is required since the
217// data referred to by the iterator is not contiguous. getMessage
218// has no such option, it always does the most efficient thing it can.
219template<class T, unsigned Dim>
221{
222
223 // Add in flag indicating if we're compressed. Put it in as an integer.
224 int compressed = (IsCompressed() ? 1 : 0);
225 m.put(compressed);
226 if (compressed == 1)
227 {
228 // If we are compressed, just add in the sizes and the value.
229 int s[Dim];
230 for (unsigned int i=0; i < Dim; ++i)
231 s[i] = BrickCounter<Dim>::size(i);
232 m.put(s, s + Dim);
234 }
235 else
236 {
237 // If uncompressed, just do as a normal BrickIterator.
239 }
240 return m;
241}
242
243// get data out from a message
244template<class T, unsigned Dim>
246{
247 // Inform msg("CBI::getMessage", INFORM_ALL_NODES);
248 int compressed = 0;
249 m.get(compressed);
250 // msg << " Compressed = " << compressed << endl;
251 if (compressed == 1)
252 {
253 int s[Dim];
254 m.get((int*) s);
255 for (unsigned int i=0; i < Dim; ++i) {
259 }
260 PAssert(CompressedData != 0);
261 BrickIterator<T,Dim>::Current = CompressedData;
263 // msg << " Current value = " << *Current << endl;
264 // msg << " Compres value = " << *CompressedData << endl;
265 }
266 else
267 {
268 // ((BrickIterator<T,Dim>*)this)->getMessage(m);
270 }
271 return m;
272}
273
275
276template<class T, unsigned D1, unsigned D2>
279 const NDIndex<D1>& current, const NDIndex<D2>& perm)
280{
281
282 unsigned int d1, d2;
283
284 // This is the iterator we'll be building.
286 if ( iter.IsCompressed() )
287 {
288 permute = CompressedBrickIterator<T,D2>( perm, *iter );
289 }
290 else
291 {
292 // Set the pointer to the same place as the one passed in.
293 permute.SetCurrent( &*iter );
294
295 // Loop over each dimension of the iterator.
296 for (d2=0; d2<D2; ++d2)
297 {
298 // The size of the loop comes from the permuted NDIndex.
299 permute.SetCount(d2,perm[d2].length());
300 // Set the counters to zero.
301 permute.ResetCounter(d2);
302 // Set the stride to zero in case we don't find a match below.
303 permute.SetStride(d2,0);
304 // Check each Index in current to find a match.
305 for (d1=0; d1<D1; ++d1)
306 {
307 if ( current[d1].sameBase( perm[d2] ) )
308 {
309 // Found it. Get the stride for this loop.
310 permute.SetStride(d2,iter.GetStride(d1));
311 // On to the next.
312 break;
313 }
314 }
315 }
316 }
317 // Done constructing permute.
318 return permute;
319}
320
322
323template<class T, unsigned Dim>
327{
328
329 if ( this != &rhs )
330 {
331 *(dynamic_cast<BrickIterator<T,Dim>*>(this)) = rhs;
332 CompressedData = rhs.CompressedData;
333 }
334 return *this;
335}
336
338
339template<class T, unsigned Dim>
342 : BrickIterator<T,Dim>(X), CompressedData(X.CompressedData)
343{
344
345}
346
348
349// Make it compress to a given value.
350// NOTE!!!! This function can only be useful in the following two contexts:
351// 1. the iterator was constructed with specific internal storage for
352// CompressedData; and this external storage will be modified (the new
353// value 'val' will be written into the storage.
354// 2. the iterator was constructed with no internal storage, and you call
355// Compress with an external variable for which you can take the address
356// and have 'CompressedData' point to.
357template<class T, unsigned Dim>
358void
360{
361
362
363 // Inform msg("CBI::Compress", INFORM_ALL_NODES);
364 // msg << "Before storing value " << val << ": ";
365 // msg << "CompressedData = " << (void *)CompressedData;
366 if (CompressedData != 0) {
367 // msg << ", old deref value = " << *CompressedData;
368 *CompressedData = val;
369 // msg << ", new deref value = " << *CompressedData;
370 } else {
371 CompressedData = &val;
372 }
373 // msg << endl;
374 BrickIterator<T,Dim>::Current = CompressedData;
375 for (unsigned d=0; d<Dim; ++d)
377}
378
380
381// Here is a version that lets the user specify a value
382// to try sparsifying on.
383template<class T, unsigned Dim>
384bool
386{
387
388
389 // Inform msg("CBI::TryCompress", INFORM_ALL_NODES);
390 // msg << "Trying to compress to value " << val;
391 // msg << " : IsCompressed = " << IsCompressed() << endl;
392 if ( IsCompressed() )
393 return true;
394 if ( CanCompress(val) )
395 {
396 // msg << " Compressing now." << endl;
397 // NOTE!!!! This next call will ONLY work if this iterator was
398 // constructed with some external storage for the CompressedData.
399 // If at the time of this call CompressedData == 0, then this will
400 // just not work, since CompressedData will be set to the address of
401 // val which is a temporary variable only active within the scope of
402 // this function. (bfh)
403 Compress(val);
404 return true;
405 }
406 // msg << " Cannot compress." << endl;
407 return false;
408}
409
410/***************************************************************************
411 * $RCSfile: CompressedBrickIterator.cpp,v $ $Author: adelmann $
412 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:26 $
413 * IPPL_VERSION_ID: $Id: CompressedBrickIterator.cpp,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $
414 ***************************************************************************/
const unsigned Dim
void putMessage(Message &m, const T &t)
Definition: Message.h:549
void getMessage_iter(Message &m, OutputIterator o)
Definition: Message.h:595
CompressedBrickIterator< T, D2 > permute(const CompressedBrickIterator< T, D1 > &iter, const NDIndex< D1 > &current, const NDIndex< D2 > &perm)
bool all_values_equal(const CompressedBrickIterator< T, Dim > &iter, T val, CompressedLoopTag< 1, true >)
#define X(arg)
Definition: fftpack.cpp:112
#define PAssert(c)
Definition: PAssert.h:102
bool CanCompress(const T &) const
Message & getMessage(Message &m)
Message & putMessage(Message &m, bool makecopy=true)
const CompressedBrickIterator< T, Dim > & operator=(const CompressedBrickIterator< T, Dim > &rhs)
int size(unsigned d) const
Definition: BrickIterator.h:43
T & offset(int i) const
Message & getMessage(Message &)
Message & putMessage(Message &, bool makecopy=true)
void step(unsigned d)
Definition: BrickIterator.h:95
Message & put(const T &val)
Definition: Message.h:406
Message & get(const T &cval)
Definition: Message.h:476