Initial checkin of Jade.
[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         // Get the size of the n'th dimension (1D, 2D ...)
189         int getDim(const uint n) {
190                 assert(n>0 && n<=numDimensions);
191                 return dims[n-1];
192         }
193
194         T* getBaseAddress() const { return data; }
195
196         //================================================================
197
198         // nD
199         // multi-dimensional JArray's.  a[b] where b is an array of
200         // the dimensions desired.
201         inline T& getElement(uint idx[]) {
202                 uint index = 0;
203                 for(uint i=0; i<numDimensions; i++) {
204                         assert(idx[i] >= 0 && idx[i] <= dims[i]);
205                         index += idx[i] * dimSize[i];
206                 }
207                 return data[index];
208         }
209         // multi-dimensional JArray's.  a[b] where b is an array of
210         // the dimensions desired.
211         //         inline T& operator[](uint i[]) {
212         //         T &tmp = getElement(i);
213         // //             CkPrintf("DEBUG: operator[[]] = %d *data=%d\n", tmp, *data);
214         //         return tmp;
215         //         }
216
217         // 1D
218         inline T& getElement(int i) {
219                 uint idx[] = { i };
220                 return getElement(idx);
221         }
222         inline T& operator () (int i0) {
223                 return getElement(i0);
224         }
225         // a[10]
226         inline T& operator[](int i) {
227                 //         uint idx[] = { i };
228                 //         return (*this)[idx];
229                 return getElement(i);
230         }
231
232         // 2D
233         inline T& getElement(int i, int j) {
234                 uint idx[] = { i, j };
235                 return getElement(idx);
236         }
237         inline T& operator () (int i0,int i1) {
238                 return getElement(i0, i1);
239         }
240
241         // 3D
242         inline T& getElement(int i, int j, int k) {
243                 uint idx[] = { i, j, k };
244                 return getElement(idx);
245         }
246         inline T& operator () (int i0, int i1, int i2) {
247                 return getElement(i0, i1, i2);
248         }
249
250         //         inline const T& operator[](int i) const;
251
252         // ================================================================
253
254         // 1D
255         // set Virtual Array
256         JArray& sV(uint s, uint e, uint str) {
257                 assert(start != NULL);
258                 assert(end != NULL);
259                 assert(stride != NULL);
260                 start[0] = s;
261                 end[0] = e;
262                 stride[0] = str;
263                 useVirtual = 1;
264         }
265
266         // 2D
267         // set Virtual Array
268         JArray& sV(uint s, uint e, uint str,
269                            uint s1, uint e1, uint str1) {
270                 sV(s, e, str);
271                 assert(numDimensions >= 2);
272                 start[1] = s1;
273                 end[1] = e1;
274                 stride[1] = str1;
275                 return *this;
276         }
277         // 2D set Row
278         JArray& sR(uint row) {
279                 sV(row, row, 1, 0, getDim(2)-1, 1);
280                 return *this;
281         }
282         // 2D set Column
283         JArray& sC(uint col) {
284                 sV(0, getDim(1)-1, 1, col, col, 1);
285                 return *this;
286         }
287
288         void pupHelper(T *vdata, uint *vindex, uint *path, int depth) {
289                 if (depth == numDimensions-1) {
290                         for(int i=start[depth]; i<=end[depth]; i+=stride[depth]) {
291                                 path[depth] = i;
292                                 vdata[*vindex] = getElement(path);
293                                 (*vindex)++;
294                         }
295                 } else {
296                         for(int i=start[depth]; i<=end[depth]; i+=stride[depth]) {
297                                 path[depth] = i;
298                                 pupHelper(vdata, vindex, path, depth+1);
299                         }
300                 }
301         }
302
303         inline int ceiling(float f) {
304                 int fi = (int)f;
305                 return (f- fi)>=0.5 ? fi+1: fi;
306         }
307
308         virtual void pup(PUP::er &p){
309                 // virtual case, and is packing or sizing
310                 if (!p.isUnpacking() && useVirtual==1) {
311                         p|numDimensions;
312                         uint *vdims = new uint[numDimensions];
313                         uint *vdimSize = new uint[numDimensions];
314                         int i=0;
315                         for (i=0; i<numDimensions; i++)
316                                 vdims[i] = ceiling( (end[i]-start[i]+1)/stride[i] );
317                         uint dimSz = 1;
318                         for(i=numDimensions-1; i>=0; i--) {
319                                 vdimSize[i] = dimSz;
320                                 dimSz *= vdims[i];
321                         }
322                         uint numElements=dimSz;
323                         p(vdims, numDimensions);
324                         p(vdimSize, numDimensions);
325                         T *vdata = new T[numElements];
326                         uint vindex = 0;
327                         uint *path = new uint[numDimensions];
328                         pupHelper(vdata, &vindex, path, 0);
329                         p(vdata, numElements);
330                         if (p.isPacking()) useVirtual=0;
331                         delete [] vdims;
332                         delete [] vdimSize;
333                         delete [] vdata;
334                         delete [] path;
335                 } else {// virtual case unpacking, or normal case pup
336                         p|numDimensions;
337                         if (p.isUnpacking()) {
338                                 //                 dims = new uint[numDimensions];
339                                 //                 dimSize = new uint[numDimensions];
340                                 setDimension(numDimensions);
341                         }
342                         p(dims, numDimensions);
343                         p(dimSize, numDimensions);
344                         int numElements = dims[0] * dimSize[0];
345                         if (p.isUnpacking()) {
346                                 data = new T[numElements];
347                         }
348                         p(data, numElements);
349                 }
350         }
351
352 };
353
354 #endif
355 // JARRAY_H