00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include "ndim.h"
00005
00006
00007 int ndim_pack(int sz, int ndim, int *dims, int *start, int *end,
00008 unsigned char *inarray, unsigned char *outbuf)
00009 {
00010 int i, total, firstdim, onechunk;
00011 int *dope, n1;
00012 int *id;
00013 unsigned char *in, *out, *in_first;
00014
00015 if (!dims || !start || !end || !inarray || !outbuf)
00016 return -1;
00017
00018
00019 if (ndim==1)
00020 {
00021 memcpy(outbuf,&inarray[sz*start[0]], sz*(end[0]-start[0]+1));
00022 return 0;
00023 }
00024
00025
00026
00027 firstdim = 0;
00028 n1 = sz;
00029 total = sz;
00030 for (i=0; i<ndim; i++)
00031 {
00032 total *= end[i]-start[i]+1;
00033 if (i<ndim-1 && start[i]==0 && end[i]==dims[i]-1 && firstdim==i)
00034 {
00035 firstdim = i+1;
00036 n1 *= end[i]-start[i]+1;
00037 }
00038 }
00039
00040
00041 dope = malloc(ndim*sizeof(int));
00042 dope[0] = sz;
00043 for (i=1;i<ndim; i++)
00044 dope[i] = dope[i-1]*dims[i-1];
00045
00046
00047 onechunk = 0;
00048 if (firstdim == ndim-1)
00049 onechunk = 1;
00050 else
00051 {
00052 onechunk = 1;
00053 for (i=firstdim; i<ndim; i++)
00054 {
00055 if (start[i] != end[i])
00056 onechunk = 0;
00057 }
00058 }
00059
00060 in = in_first = inarray;
00061 id = malloc(ndim*sizeof(int));
00062 for (i=0; i<ndim; i++)
00063 {
00064 id[i] = start[i];
00065 if (i==firstdim)
00066 in_first = in;
00067 in += dope[i]*id[i];
00068 }
00069
00070 if (onechunk)
00071 {
00072
00073 memcpy(outbuf,in,total);
00074 }
00075 else
00076 {
00077 out = outbuf;
00078 while ((int) (out-outbuf) < total)
00079 {
00080
00081
00082
00083
00084
00085 memcpy(out, in, n1);
00086 out += n1;
00087
00088
00089 id[firstdim] += 1;
00090 if (id[firstdim] > end[firstdim])
00091 {
00092
00093
00094 in = in_first;
00095 for (i=firstdim; i<ndim-1; i++)
00096 {
00097 if (id[i] > end[i])
00098 {
00099 id[i] = start[i];
00100 id[i+1] += 1;
00101 }
00102
00103 in += dope[i]*id[i];
00104 }
00105 in += dope[ndim-1]*id[ndim-1];
00106 }
00107 else
00108 in += dope[firstdim];
00109 }
00110 }
00111 free(dope);
00112 free(id);
00113 return 0;
00114 }
00115
00116
00117
00118 int ndim_unpack(int sz, int ndim, int *dims, int *start, int *end,
00119 unsigned char *inbuf, unsigned char *outarray)
00120 {
00121 int i, total, firstdim, onechunk;
00122 int *dope, n1;
00123 int *id;
00124 unsigned char *in, *out, *out_first;
00125
00126 if (!dims || !start || !end || !inbuf || !outarray)
00127 return -1;
00128
00129
00130 if (ndim==1)
00131 {
00132 memcpy(&outarray[sz*start[0]],inbuf, sz*(end[0]-start[0]+1));
00133
00134
00135
00136
00137
00138
00139 return 0;
00140 }
00141
00142
00143
00144 firstdim = 0;
00145 n1 = sz;
00146 total = sz;
00147 for (i=0; i<ndim; i++)
00148 {
00149 total *= end[i]-start[i]+1;
00150 if (i<ndim-1 && start[i]==0 && end[i]==dims[i]-1 && firstdim==i)
00151 {
00152 firstdim = i+1;
00153 n1 *= end[i]-start[i]+1;
00154 }
00155 }
00156
00157
00158 dope = malloc(ndim*sizeof(int));
00159 dope[0] = sz;
00160 for (i=1;i<ndim; i++)
00161 dope[i] = dope[i-1]*dims[i-1];
00162
00163
00164 onechunk = 0;
00165 if (firstdim == ndim-1)
00166 onechunk = 1;
00167 else
00168 {
00169 onechunk = 1;
00170 for (i=firstdim; i<ndim; i++)
00171 {
00172 if (start[i] != end[i])
00173 onechunk = 0;
00174 }
00175 }
00176
00177
00178
00179
00180 out = out_first = outarray;
00181 id = malloc(ndim*sizeof(int));
00182 for (i=0; i<ndim; i++)
00183 {
00184 id[i] = start[i];
00185 if (i==firstdim)
00186 out_first = out;
00187 out += dope[i]*id[i];
00188 }
00189
00190
00191 if (onechunk)
00192 {
00193
00194 memcpy(out,inbuf,total);
00195 }
00196 else
00197 {
00198 in = inbuf;
00199 while ((int) (in-inbuf) < total)
00200 {
00201
00202
00203
00204
00205
00206 memcpy(out,in,n1);
00207 in += n1;
00208
00209
00210 id[firstdim] += 1;
00211 if (id[firstdim] > end[firstdim])
00212 {
00213
00214
00215 out = out_first;
00216 for (i=firstdim; i<ndim-1; i++)
00217 {
00218 if (id[i] > end[i])
00219 {
00220 id[i] = start[i];
00221 id[i+1] += 1;
00222 }
00223
00224 out += dope[i]*id[i];
00225 }
00226 out += dope[ndim-1]*id[ndim-1];
00227 }
00228 else
00229 out += dope[firstdim];
00230 }
00231 }
00232 free(dope);
00233 free(id);
00234 return 0;
00235 }
00236
00237
00238
00239
00240 int ndim_permute(int sz, int ndim, int *dims, int *perm,
00241 unsigned char *in, unsigned char *out)
00242 {
00243 int i, bytes, count, n, identity;
00244 int *dope1, *dope2;
00245 int *id, *permdims;
00246 unsigned char *p1, *p2;
00247
00248
00249 if (!dims || !perm || !in || !out || ndim<=0)
00250 return -1;
00251
00252
00253 if (ndim==1)
00254 {
00255 memcpy(out,in, sz*dims[0]);
00256 return 0;
00257 }
00258
00259 permdims = malloc(ndim*sizeof(int));
00260 memset(permdims,0,ndim*sizeof(int));
00261
00262
00263 identity = 1;
00264 for (i=0; i<ndim; i++)
00265 {
00266 if (perm[i]<0 || perm[i]>=ndim)
00267 {
00268 fprintf(stderr,"ERROR in ndim_permute: perm is not a valid permutation "
00269 "of 0 through ndim-1=%d\nbecause perm[%d]=%d.\n",ndim-1,i,perm[i]);
00270 return 1;
00271 }
00272 permdims[perm[i]] += 1;
00273 if (perm[i] != i)
00274 identity=0;
00275 }
00276
00277
00278
00279 count = 1;
00280 for (i=0; i<ndim; i++)
00281 {
00282 count *= dims[i];
00283
00284
00285 }
00286 bytes = sz*count;
00287
00288
00289
00290 if (identity)
00291 {
00292 memcpy(out,in,bytes);
00293 return 0;
00294 }
00295
00296
00297 for (i=0; i<ndim; i++)
00298 {
00299 if (permdims[i]!=1)
00300 {
00301 fprintf(stderr,"ERROR in ndim_permute: perm is not a valid permutation "
00302 "because %d occurs %d times.\n",i,permdims[i]);
00303 return 1;
00304 }
00305 }
00306
00307 for (i=0; i<ndim; i++)
00308 {
00309 permdims[i] = dims[perm[i]];
00310 #ifdef DEBUG
00311 printf("permdims[%d] = %d\n",i,permdims[i]);
00312 #endif
00313 }
00314
00315
00316
00317 dope1 = malloc(ndim*sizeof(int));
00318 dope2 = malloc(ndim*sizeof(int));
00319 id = malloc(ndim*sizeof(int));
00320 dope1[0] = sz;
00321 id[0] = sz;
00322 dope2[perm[0]] = sz;
00323 for (i=1; i<ndim; i++)
00324 {
00325 dope1[i] = dope1[i-1]*dims[i-1];
00326 id[i] = id[i-1]*permdims[i-1];
00327
00328 dope2[perm[i]] = id[i];
00329 }
00330 free(permdims);
00331
00332
00333 memset(id, 0, ndim*sizeof(int));
00334 p1 = in;
00335 p2 = out;
00336
00337 #ifdef DEBUG
00338 printf("sz = %d\n",sz);
00339 #endif
00340
00341 for (n=0; n<count; n++)
00342 {
00343 memcpy(p2, p1, sz);
00344 id[0] += 1;
00345 #ifdef DEBUG
00346 printf("id = (%d",id[0]);
00347 for (i=1;i<ndim;i++)
00348 printf(",%d",id[i]);
00349 printf(")\n");
00350 #endif
00351 if (id[0] >= dims[0])
00352 {
00353
00354
00355 p1 = in;
00356 p2 = out;
00357 for (i=0; i<ndim-1; i++)
00358 {
00359 if (id[i] >= dims[i])
00360 {
00361 id[i] = 0;
00362 id[i+1] += 1;
00363 }
00364
00365 p1 += dope1[i]*id[i];
00366 p2 += dope2[i]*id[i];
00367 }
00368 p1 += dope1[ndim-1]*id[ndim-1];
00369 p2 += dope2[ndim-1]*id[ndim-1];
00370 }
00371 else
00372 {
00373 p1 += dope1[0];
00374 p2 += dope2[0];
00375 }
00376 }
00377 free(dope1);
00378 free(dope2);
00379 free(id);
00380 return 0;
00381 }
00382
00383
00384