Merge branch 'charm' of charmgit:charm into charm
[charm.git] / src / langs / jade / JArray.h
1 // emacs mode line -*- mode: c++; tab-width: 4 -*-
2
3 #ifndef JARRAY_H
4 #define JARRAY_H
5
6 #include <iostream>
7 #include <assert.h>
8
9 //for PUP::er
10 #include <charm++.h>
11
12 // for memcopy
13 #include <string.h>
14
15 #ifndef NULL
16 #define NULL 0
17 #endif
18 #define DPRINT(a)
19
20 typedef unsigned int uint;
21
22 template<class T>
23 class JArray {
24         uint numDimensions;
25         // e.g. a[10][20] dims = 10, 20  dimSize = 20, 1
26         uint *dims;              // array containing size of dim 1, 2, ...; 1-based
27         uint *dimSize;   // array containing num elements in dim 1, 2, ...; 1-based
28         T *data;
29
30         // virtual array to be used for next PUP
31         uint useVirtual;
32         uint *start;
33         uint *end;
34         uint *stride;
35
36 public:
37         // Ways to set the dimension of the array:
38         // cons(dims)
39         // cons(), setDimension
40         // cons(), pup
41         // cons(), resize
42
43         // Constructor with dimensionality
44         JArray(const int numDims):dims(NULL), data(NULL), dimSize(NULL), useVirtual(0), start(NULL), end(NULL), stride(NULL)
45         {
46                 //ckout << CkMyPe() << ": JArray(" << numDims << ") reached" << endl;
47 //              assert(numDims<=3); // @@ arbitrary limitation, code should work ok for larger dims
48                 setDimension(numDims);
49         }
50
51         // Constructor without dimensionality
52         // something should be called immediately to set the dimensionality
53         JArray():numDimensions(0), dims(NULL), data(NULL), dimSize(NULL), useVirtual(0), start(NULL), end(NULL), stride(NULL)
54         {
55                 //ckout << CkMyPe() << ": JArray() reached" << endl;
56         }
57
58         // Constructor from 1D C array
59         JArray(const int numElements, T *rawdata):numDimensions(0), dims(NULL), data(NULL), dimSize(NULL), useVirtual(0), start(NULL), end(NULL), stride(NULL)
60         {
61                 //CkPrintf("DEBUG: %d %d %d\n", numElements, rawdata[0], rawdata[1]);
62                 setDimension(1);
63                 resize1D(numElements);
64                 for(uint i=0; i<numElements; i++)
65                         data[i] = rawdata[i];
66         }
67
68         // Allocates dims and dimSize, but does not create the data array;
69         // resize or pup must be called.
70         void setDimension(uint numDims) {
71                 //ckout << CkMyPe() << ": JArray::setDimension(" << numDims << ") reached" << endl;
72                 numDimensions = numDims;
73                 dims = new uint[numDimensions];
74                 dimSize = new uint[numDimensions];
75                 start = new uint[numDimensions];
76                 end = new uint[numDimensions];
77                 stride = new uint[numDimensions];
78                 for(uint i=0; i<numDimensions; i++)
79                         dims[i] = dimSize[i] = start[i] = end[i] = stride[i] = 0;
80         }
81
82         // Copy constructor.  Needed for param marshalling.
83         // virtual array stuff is not copied
84         //
85         // Differs from copy assignment because cc deals with
86         // unallocated memory, but ca deals with a constructed object.
87         JArray(const JArray &rhs) {
88                 int i = 0;
89
90                 //CkPrintf("DEBUG: Copy constructor called\n");
91                 setDimension(rhs.numDimensions);
92                 //CkPrintf("DEBUG: CC: rhs.numDimensions = %d numDimensions = %d\n", rhs.numDimensions, numDimensions);
93                 for(i=0; i<numDimensions; i++) {
94                         dims[i]=rhs.dims[i];
95                         dimSize[i]=rhs.dimSize[i];
96                         start[i] = end[i] = stride[i] = 0;
97                 }
98                 useVirtual=0;
99
100                 //memcpy(dims, rhs.dims, numDimensions*sizeof(uint));
101                 //CkPrintf("DEBUG: CC: rhs.dims[0] = %d, dims[0] = %d\n", rhs.dims[0], dims[0]);
102                 //std::copy(dims, dims+numDimensions, rhs.dims);
103                 //CkPrintf("DEBUG: CC: rhs.dims[0] = %d, dims[0] = %d\n", rhs.dims[0], dims[0]);
104                 //memcpy(dimSize, rhs.dimSize, numDimensions*sizeof(uint));
105                 //std::copy(dimSize, dimSize+numDimensions, rhs.dimSize);
106
107                 int numElements = dims[0] * dimSize[0];
108                 //         CkPrintf("DEBUG: CC: numElements = %d\n", numElements);
109                 //         delete [] data;
110                 data = new T[numElements];
111                 //memcpy(data, rhs.data, numElements);
112                 //std::copy(data, data+numElements, rhs.data);
113                 for(i=0; i<numElements; i++)
114                         data[i] = rhs.data[i];
115                 //         CkPrintf("DEBUG: CC: *data = %d *rhs.data = %d\n", *data, *rhs.data);
116         }
117
118         ~JArray() {
119                 delete [] dims;
120                 delete [] dimSize;
121                 delete [] data;
122                 delete [] start;
123                 delete [] end;
124                 delete [] stride;
125                 dims = NULL;
126                 dimSize = NULL;
127                 data = NULL;
128                 start = NULL;
129                 end = NULL;
130                 stride = NULL;
131         }
132
133         // resize populates dims and dimSize, and allocates the data array
134         // numDimensions may already be set, numDims is provided again just for verification.
135         // if numDimensions is not set, we set it to numDims.
136         //
137         // We do not allow resizing a JArray into a different number of
138         // dimensions.  We could, but will disallow it until I can think
139         // of a need for it.
140         JArray& resize(const uint numDims, const uint d[]){
141                 //         ckout << CkMyPe() << ": JArray::resize(" << numDims << ".. reached" << endl;
142                 int i;
143                 if (numDimensions == 0)
144                         setDimension(numDims);
145                 else
146                         assert(numDimensions==numDims);
147
148                 uint dimSz = 1;
149                 for(i=numDimensions-1; i>=0; i--) {
150                         dimSize[i] = dimSz;
151                         dimSz *= d[i];
152                         dims[i] = d[i];
153                 }
154
155                 uint numElements=dimSz;
156
157                 //         cout << "DEBUG: " << numElements << " elements " << ", dimSize ";
158                 //         for(i=0; i<numDimensions; i++)
159                 //                 cout << dimSize[i] << " ";
160                 //         cout << endl;
161
162                 // resizing an already allocated array blows away the data.
163                 if (data != NULL)
164                         delete [] data;
165                 data = new T[numElements];
166
167                 return *this;
168         }
169
170         // resize
171         JArray& resize1D(const uint d1){
172                 uint d[] = { d1 };
173                 return resize(1, d);
174         }
175
176         // resize
177         JArray& resize2D(const uint d1, const uint d2){
178                 uint d[] = { d1, d2 };
179                 return resize(2, d);
180         }
181
182         // resize
183         JArray& resize3D(const uint d1, const uint d2, const uint d3){
184                 uint d[] = { d1, d2, d3 };
185                 return resize(3, d);
186         }
187
188         // resize
189         JArray& resize4D(const uint d1, const uint d2, const uint d3, const uint d4){
190                 uint d[] = { d1, d2, d3, d4 };
191                 return resize(4, d);
192         }
193
194         // resize
195         JArray& resize5D(const uint d1, const uint d2, const uint d3, const uint d4, const uint d5){
196                 uint d[] = { d1, d2, d3, d4, d5 };
197                 return resize(5, d);
198         }
199
200         // resize
201         JArray& resize6D(const uint d1, const uint d2, const uint d3, const uint d4, const uint d5, const uint d6){
202                 uint d[] = { d1, d2, d3, d4, d5, d6 };
203                 return resize(6, d);
204         }
205
206         // Get the size of the n'th dimension (1D, 2D ...)
207         int getDim(const uint n) {
208                 assert(n>0 && n<=numDimensions);
209                 return dims[n-1];
210         }
211
212         T* getBaseAddress() const { return data; }
213
214         //================================================================
215
216         // nD
217         // multi-dimensional JArray's.  a[b] where b is an array of
218         // the dimensions desired.
219         inline T& getElement(uint idx[]) {
220                 uint index = 0;
221                 for(uint i=0; i<numDimensions; i++) {
222                         assert(//idx[i] >= 0 && 
223                                 idx[i] <= dims[i]);
224                         index += idx[i] * dimSize[i];
225                 }
226                 return data[index];
227         }
228         // multi-dimensional JArray's.  a[b] where b is an array of
229         // the dimensions desired.
230         //         inline T& operator[](uint i[]) {
231         //         T &tmp = getElement(i);
232         // //             CkPrintf("DEBUG: operator[[]] = %d *data=%d\n", tmp, *data);
233         //         return tmp;
234         //         }
235
236         // 1D
237         inline T& getElement(int i) {
238                 return data[i];
239         }
240         inline T& getElementSlow(int i) {
241                 uint idx[] = { i };
242                 return getElement(idx);
243         }
244         inline T& operator () (int i0) {
245                 return getElement(i0);
246         }
247         // a[10]
248         inline T& operator[](int i) {
249                 //         uint idx[] = { i };
250                 //         return (*this)[idx];
251                 return getElement(i);
252         }
253
254         // 2D
255         inline T& getElement(int i, int j) {
256                 return data[i*dimSize[0]+j];
257         }
258         inline T& getElementSlow(int i, int j) {
259                 uint idx[] = { i, j };
260                 return getElement(idx);
261         }
262         inline T& operator () (int i0,int i1) {
263                 return getElement(i0, i1);
264         }
265
266         // 3D
267         inline T& getElement(int i, int j, int k) {
268                 return data[i*dimSize[0]+j*dimSize[1]+k];
269         }
270         inline T& getElementSlow(int i, int j, int k) {
271                 uint idx[] = { i, j, k };
272                 return getElement(idx);
273         }
274         inline T& operator () (int i0, int i1, int i2) {
275                 return getElement(i0, i1, i2);
276         }
277
278         //         inline const T& operator[](int i) const;
279
280         // ================================================================
281
282         // 1D
283         // set Virtual Array
284         JArray& sV(uint s, uint e, uint str) {
285                 assert(start != NULL);
286                 assert(end != NULL);
287                 assert(stride != NULL);
288                 start[0] = s;
289                 end[0] = e;
290                 stride[0] = str;
291                 useVirtual = 1;
292                 return *this;
293         }
294
295         // 2D
296         // set Virtual Array
297         JArray& sV(uint s, uint e, uint str,
298                            uint s1, uint e1, uint str1) {
299                 sV(s, e, str);
300                 assert(numDimensions >= 2);
301                 start[1] = s1;
302                 end[1] = e1;
303                 stride[1] = str1;
304                 return *this;
305         }
306         // 2D set Row
307         JArray& sR(uint row) {
308                 sV(row, row, 1, 0, getDim(2)-1, 1);
309                 return *this;
310         }
311         // 2D set Column
312         JArray& sC(uint col) {
313                 sV(0, getDim(1)-1, 1, col, col, 1);
314                 return *this;
315         }
316
317         void pupHelper(T *vdata, uint *vindex, uint *path, int depth) {
318                 if (depth == numDimensions-1) {
319                         for(int i=start[depth]; i<=end[depth]; i+=stride[depth]) {
320                                 path[depth] = i;
321                                 vdata[*vindex] = getElement(path);
322                                 (*vindex)++;
323                         }
324                 } else {
325                         for(int i=start[depth]; i<=end[depth]; i+=stride[depth]) {
326                                 path[depth] = i;
327                                 pupHelper(vdata, vindex, path, depth+1);
328                         }
329                 }
330         }
331
332         inline int ceiling(float f) {
333                 int fi = (int)f;
334                 return (f- fi)>=0.5 ? fi+1: fi;
335         }
336
337         virtual void pup(PUP::er &p){
338                 // virtual case, and is packing or sizing
339                 if (!p.isUnpacking() && useVirtual==1) {
340                         p|numDimensions;
341                         uint *vdims = new uint[numDimensions];
342                         uint *vdimSize = new uint[numDimensions];
343                         int i=0;
344                         for (i=0; i<numDimensions; i++)
345                                 vdims[i] = ceiling( (end[i]-start[i]+1)/stride[i] );
346                         uint dimSz = 1;
347                         for(i=numDimensions-1; i>=0; i--) {
348                                 vdimSize[i] = dimSz;
349                                 dimSz *= vdims[i];
350                         }
351                         uint numElements=dimSz;
352                         p(vdims, numDimensions);
353                         p(vdimSize, numDimensions);
354                         T *vdata = new T[numElements];
355                         uint vindex = 0;
356                         uint *path = new uint[numDimensions];
357                         pupHelper(vdata, &vindex, path, 0);
358                         p(vdata, numElements);
359                         if (p.isPacking()) useVirtual=0;
360                         delete [] vdims;
361                         delete [] vdimSize;
362                         delete [] vdata;
363                         delete [] path;
364                 } else {// virtual case unpacking, or normal case pup
365                         p|numDimensions;
366                         if (p.isUnpacking()) {
367                                 //                 dims = new uint[numDimensions];
368                                 //                 dimSize = new uint[numDimensions];
369                                 setDimension(numDimensions);
370                         }
371                         p(dims, numDimensions);
372                         p(dimSize, numDimensions);
373                         int numElements = dims[0] * dimSize[0];
374                         if (p.isUnpacking()) {
375                                 data = new T[numElements];
376                         }
377                         p(data, numElements);
378                 }
379         }
380
381 };
382
383 #endif
384 // JARRAY_H