GRASS Programmer's Manual  6.4.4(2014)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
filecompare.c
Go to the documentation of this file.
1 #include <rpc/types.h>
2 #include <rpc/xdr.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <unistd.h>
7 #include <grass/G3d.h>
8 
9 /*--------------------------------------------------------------------------*/
10 
11 static unsigned char clearMask[9] =
12  { 255, 128, 192, 224, 240, 248, 252, 254, 255 };
13 
14 /*---------------------------------------------------------------------------*/
15 
16 static void G3d_float2xdrFloat(float *f, float *xdrf)
17 {
18  XDR xdrEncodeStream;
19 
20  xdrmem_create(&xdrEncodeStream, (caddr_t) xdrf, 4, XDR_ENCODE);
21 
22  if (!xdr_setpos(&xdrEncodeStream, 0))
23  G3d_fatalError("G3d_float2xdrFloat: positioning xdr failed");
24 
25  if (!xdr_float(&xdrEncodeStream, f))
26  G3d_fatalError("G3d_float2xdrFloat: writing xdr failed");
27 
28  xdr_destroy(&xdrEncodeStream);
29 }
30 
31 /*---------------------------------------------------------------------------*/
32 
33 static void G3d_double2xdrDouble(double *d, double *xdrd)
34 {
35  XDR xdrEncodeStream;
36 
37  xdrmem_create(&xdrEncodeStream, (caddr_t) xdrd, 8, XDR_ENCODE);
38 
39  if (!xdr_setpos(&xdrEncodeStream, 0))
40  G3d_fatalError("G3d_double2xdrDouble: positioning xdr failed");
41 
42  if (!xdr_double(&xdrEncodeStream, d))
43  G3d_fatalError("G3d_double2xdrDouble: writing xdr failed");
44 
45  xdr_destroy(&xdrEncodeStream);
46 }
47 
48 /*---------------------------------------------------------------------------*/
49 
50 static void G3d_truncFloat(float *f, int p)
51 {
52  unsigned char *c;
53 
54  if ((p == -1) || (p >= 23))
55  return;
56 
57  c = (unsigned char *)f;
58 
59  c++;
60  if (p <= 7) {
61  *c++ &= clearMask[(p + 1) % 8];
62  *c++ = 0;
63  *c = 0;
64  return;
65  }
66 
67  c++;
68  if (p <= 15) {
69  *c++ &= clearMask[(p + 1) % 8];
70  *c = 0;
71  return;
72  }
73 
74  c++;
75  *c &= clearMask[(p + 1) % 8];
76  return;
77 }
78 
79 /*---------------------------------------------------------------------------*/
80 
81 static void G3d_truncDouble(double *d, int p)
82 {
83  unsigned char *c;
84 
85  if ((p == -1) || (p >= 52))
86  return;
87 
88  c = (unsigned char *)d;
89 
90  c++;
91  if (p <= 4) {
92  *c++ &= clearMask[(p + 4) % 8];
93  *c++ = 0;
94  *c++ = 0;
95  *c++ = 0;
96  *c++ = 0;
97  *c++ = 0;
98  *c = 0;
99  return;
100  }
101 
102  c++;
103  if (p <= 12) {
104  *c++ &= clearMask[(p + 4) % 8];
105  *c++ = 0;
106  *c++ = 0;
107  *c++ = 0;
108  *c++ = 0;
109  *c = 0;
110  return;
111  }
112 
113  c++;
114  if (p <= 20) {
115  *c++ &= clearMask[(p + 4) % 8];
116  *c++ = 0;
117  *c++ = 0;
118  *c++ = 0;
119  *c = 0;
120  return;
121  }
122 
123  c++;
124  if (p <= 28) {
125  *c++ &= clearMask[(p + 4) % 8];
126  *c++ = 0;
127  *c++ = 0;
128  *c = 0;
129  return;
130  }
131 
132  c++;
133  if (p <= 36) {
134  *c++ &= clearMask[(p + 4) % 8];
135  *c++ = 0;
136  *c = 0;
137  return;
138  }
139 
140  c++;
141  if (p <= 44) {
142  *c++ &= clearMask[(p + 4) % 8];
143  *c = 0;
144  return;
145  }
146 
147  c++;
148  *c &= clearMask[(p + 4) % 8];
149  return;
150 }
151 
152 /*---------------------------------------------------------------------------*/
153 
154 static void G3d_float2Double(float *f, double *d)
155 {
156  unsigned char *c1, *c2, sign, c;
157  int e;
158 
159  c1 = (unsigned char *)f;
160  c2 = (unsigned char *)d;
161 
162  sign = (*c1 & (unsigned char)128);
163  e = (((*c1 & (unsigned char)127) << 1) |
164  ((*(c1 + 1) & (unsigned char)128) >> 7));
165 
166  if ((*c1 != 0) || (*(c1 + 1) != 0) || (*(c1 + 2) != 0) ||
167  (*(c1 + 3) != 0))
168  e += 1023 - 127;
169  c = e / 16;
170 
171  *c2++ = (sign | c);
172 
173  c1++;
174 
175  c = e % 16;
176  *c2 = (c << 4);
177  *c2++ |= ((*c1 & (unsigned char)127) >> 3);
178 
179  *c2 = ((*c1++ & (unsigned char)7) << 5);
180  *c2++ |= (*c1 >> 3);
181 
182  *c2 = ((*c1++ & (unsigned char)7) << 5);
183  *c2++ |= (*c1 >> 3);
184 
185  *c2++ = ((*c1 & (unsigned char)7) << 5);
186 
187  *c2++ = (unsigned char)0;
188  *c2++ = (unsigned char)0;
189  *c2 = (unsigned char)0;
190 }
191 
192 /*---------------------------------------------------------------------------*/
193 
194 static int G3d_compareFloats(float *f1, int p1, float *f2, int p2)
195 {
196  unsigned char *c1, *c2;
197  float xdrf1, xdrf2;
198 
199  if (G3d_isNullValueNum(f1, FCELL_TYPE))
200  return G3d_isNullValueNum(f2, FCELL_TYPE);
201 
202  G3d_float2xdrFloat(f1, &xdrf1);
203  G3d_float2xdrFloat(f2, &xdrf2);
204 
205  c1 = (unsigned char *)&xdrf1;
206  c2 = (unsigned char *)&xdrf2;
207 
208  /* printf ("%d %d (%d %d %d %d) (%d %d %d %d) %d\n", p1, p2, *c1, *(c1 + 1), *(c1 + 2), *(c1 + 3), *c2, *(c2 + 1), *(c2 + 2), *(c2 + 3), *f1 == *f2); */
209 
210  if ((p1 != -1) && (p1 < 23) && ((p1 < p2) || (p2 == -1)))
211  G3d_truncFloat(&xdrf2, p1);
212  if ((p2 != -1) && (p2 < 23) && ((p2 < p1) || (p1 == -1)))
213  G3d_truncFloat(&xdrf1, p2);
214 
215  /* printf ("%d %d (%d %d %d %d) (%d %d %d %d) %d\n", p1, p2, *c1, *(c1 + 1), *(c1 + 2), *(c1 + 3), *c2, *(c2 + 1), *(c2 + 2), *(c2 + 3), *f1 == *f2); */
216 
217  return (*c1 == *c2) && (*(c1 + 1) == *(c2 + 1)) &&
218  (*(c1 + 2) == *(c2 + 2))
219  && (*(c1 + 3) == *(c2 + 3));
220 }
221 
222 
223 /*---------------------------------------------------------------------------*/
224 
225 static int G3d_compareDoubles(double *d1, int p1, double *d2, int p2)
226 {
227  unsigned char *c1, *c2;
228  double xdrd1, xdrd2;
229 
230  if (G3d_isNullValueNum(d1, DCELL_TYPE))
231  return G3d_isNullValueNum(d2, DCELL_TYPE);
232 
233  G3d_double2xdrDouble(d1, &xdrd1);
234  G3d_double2xdrDouble(d2, &xdrd2);
235 
236  c1 = (unsigned char *)&xdrd1;
237  c2 = (unsigned char *)&xdrd2;
238 
239  /* printf ("%d %d (%d %d %d %d %d %d %d %d) (%d %d %d %d %d %d %d %d)\n", p1, p2, *c1, *(c1 + 1), *(c1 + 2), *(c1 + 3), *(c1 + 4), *(c1 + 5), *(c1 + 6), *(c1 + 7), *c2, *(c2 + 1), *(c2 + 2), *(c2 + 3), *(c2 + 4), *(c2 + 5), *(c2 + 6), *(c2 + 7)); */
240 
241  if ((p1 != -1) && (p1 < 52) && ((p1 < p2) || (p2 == -1)))
242  G3d_truncDouble(&xdrd2, p1);
243  if ((p2 != -1) && (p2 < 52) && ((p2 < p1) || (p1 == -1)))
244  G3d_truncDouble(&xdrd1, p2);
245 
246  /* printf ("%d %d (%d %d %d %d %d %d %d %d) (%d %d %d %d %d %d %d %d)\n", p1, p2, *c1, *(c1 + 1), *(c1 + 2), *(c1 + 3), *(c1 + 4), *(c1 + 5), *(c1 + 6), *(c1 + 7), *c2, *(c2 + 1), *(c2 + 2), *(c2 + 3), *(c2 + 4), *(c2 + 5), *(c2 + 6), *(c2 + 7)); */
247 
248  return (*c1 == *c2) && (*(c1 + 1) == *(c2 + 1)) &&
249  (*(c1 + 2) == *(c2 + 2))
250  && (*(c1 + 3) == *(c2 + 3)) && (*(c1 + 4) == *(c2 + 4))
251  && (*(c1 + 5) == *(c2 + 5)) && (*(c1 + 6) == *(c2 + 6))
252  && (*(c1 + 7) == *(c2 + 7));
253 }
254 
255 
256 /*---------------------------------------------------------------------------*/
257 
258 static int G3d_compareFloatDouble(float *f, int p1, double *d, int p2)
259 {
260  unsigned char *c1, *c2;
261  float xdrf, fTmp;
262  double xdrd, xdrd2, dTmp;
263 
264  if (G3d_isNullValueNum(f, FCELL_TYPE))
265  return G3d_isNullValueNum(d, DCELL_TYPE);
266 
267  /* need this since assigning a double to a float actually may change the */
268  /* bit pattern. an example (in xdr format) is the double */
269  /* (63 237 133 81 81 108 3 32) which truncated to 23 bits precision should */
270  /* become (63 237 133 81 64 0 0 0). however assigned to a float it becomes */
271  /* (63 237 133 81 96 0 0 0). */
272  fTmp = *d;
273  dTmp = fTmp;
274 
275  G3d_float2xdrFloat(f, &xdrf);
276  G3d_float2Double(&xdrf, &xdrd2);
277  G3d_double2xdrDouble(&dTmp, &xdrd);
278 
279  c1 = (unsigned char *)&xdrd2;
280  c2 = (unsigned char *)&xdrd;
281 
282  /* printf ("%d %d (%d %d %d %d) (%d %d %d %d %d %d %d %d) (%d %d %d %d %d %d %d %d)\n", p1, p2, *((unsigned char *) &xdrf), *(((unsigned char *) &xdrf) + 1), *(((unsigned char *) &xdrf) + 2), *(((unsigned char *) &xdrf) + 3), *c1, *(c1 + 1), *(c1 + 2), *(c1 + 3), *(c1 + 4), *(c1 + 5), *(c1 + 6), *(c1 + 7), *c2, *(c2 + 1), *(c2 + 2), *(c2 + 3), *(c2 + 4), *(c2 + 5), *(c2 + 6), *(c2 + 7)); */
283 
284 
285  if (((p1 != -1) && ((p1 < p2) || (p2 == -1))) ||
286  ((p1 == -1) && ((p2 > 23) || (p2 == -1))))
287  G3d_truncDouble(&xdrd, (p1 != -1 ? p1 : 23));
288  if ((p2 != -1) && (p2 < 23) && ((p2 < p1) || (p1 == -1)))
289  G3d_truncDouble(&xdrd2, p2);
290 
291  /* printf ("%d %d (%d %d %d %d) (%d %d %d %d %d %d %d %d) (%d %d %d %d %d %d %d %d)\n", p1, p2, *((unsigned char *) &xdrf), *(((unsigned char *) &xdrf) + 1), *(((unsigned char *) &xdrf) + 2), *(((unsigned char *) &xdrf) + 3), *c1, *(c1 + 1), *(c1 + 2), *(c1 + 3), *(c1 + 4), *(c1 + 5), *(c1 + 6), *(c1 + 7), *c2, *(c2 + 1), *(c2 + 2), *(c2 + 3), *(c2 + 4), *(c2 + 5), *(c2 + 6), *(c2 + 7)); */
292 
293  return (*c1 == *c2) && (*(c1 + 1) == *(c2 + 1)) &&
294  (*(c1 + 2) == *(c2 + 2))
295  && (*(c1 + 3) == *(c2 + 3)) && (*(c1 + 4) == *(c2 + 4))
296  && (*(c1 + 5) == *(c2 + 5)) && (*(c1 + 6) == *(c2 + 6))
297  && (*(c1 + 7) == *(c2 + 7));
298 }
299 
300 /*---------------------------------------------------------------------------*/
301 
302 static void compareFilesNocache(void *map, void *map2)
303 {
304  double n1 = 0, n2 = 0;
305  double *n1p, *n2p;
306  float *f1p, *f2p;
307  int x, y, z, correct;
308  int p1, p2;
309  int tileX, tileY, tileZ, typeIntern, typeIntern2;
310  int nx, ny, nz;
311 
312  p1 = G3d_tilePrecisionMap(map);
313  p2 = G3d_tilePrecisionMap(map2);
314 
315  G3d_getTileDimensionsMap(map, &tileX, &tileY, &tileZ);
316  G3d_getNofTilesMap(map2, &nx, &ny, &nz);
317  typeIntern = G3d_tileTypeMap(map);
318  typeIntern2 = G3d_tileTypeMap(map2);
319 
320  n1p = &n1;
321  f1p = (float *)&n1;
322  n2p = &n2;
323  f2p = (float *)&n2;
324 
325  for (z = 0; z < nz * tileZ; z++) {
326  printf("comparing: z = %d\n", z);
327 
328  for (y = 0; y < ny * tileY; y++) {
329  for (x = 0; x < nx * tileX; x++) {
330 
331  G3d_getBlock(map, x, y, z, 1, 1, 1, n1p, typeIntern);
332  G3d_getBlock(map2, x, y, z, 1, 1, 1, n2p, typeIntern2);
333 
334  if (typeIntern == FCELL_TYPE) {
335  if (typeIntern2 == FCELL_TYPE)
336  correct = G3d_compareFloats(f1p, p1, f2p, p2);
337  else
338  correct = G3d_compareFloatDouble(f1p, p1, n2p, p2);
339  }
340  else {
341  if (typeIntern2 == FCELL_TYPE)
342  correct = G3d_compareFloatDouble(f2p, p2, n1p, p1);
343  else
344  correct = G3d_compareDoubles(n1p, p1, n2p, p2);
345  }
346 
347  if (!correct) {
348  int xTile, yTile, zTile, xOffs, yOffs, zOffs;
349 
350  G3d_coord2tileCoord(map2, x, y, z, &xTile, &yTile, &zTile,
351  &xOffs, &yOffs, &zOffs);
352  printf("(%d %d %d) (%d %d %d) (%d %d %d) %.20f %.20f\n",
353  x, y, z, xTile, yTile, zTile, xOffs, yOffs, zOffs,
354  *n1p, *n2p);
356  ("compareFilesNocache: files don't match\n");
357  }
358  }
359  }
360  }
361 
362  printf("Files are identical up to precision.\n");
363 }
364 
365 /*---------------------------------------------------------------------------*/
366 
367 
385 void
386 G3d_compareFiles(const char *f1, const char *mapset1, const char *f2,
387  const char *mapset2)
388 {
389  void *map, *map2;
390  double n1 = 0, n2 = 0;
391  double *n1p, *n2p;
392  float *f1p, *f2p;
393  int x, y, z, correct;
394  int p1, p2;
395  int rows, cols, depths;
396  int tileX, tileY, tileZ, typeIntern, typeIntern2, tileX2, tileY2, tileZ2;
397  int nx, ny, nz;
398 
399  printf("\nComparing %s and %s\n", f1, f2);
400 
401  map = G3d_openCellOld(f1, mapset1, G3D_DEFAULT_WINDOW,
402  G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT);
403  if (map == NULL)
404  G3d_fatalError("G3d_compareFiles: error in G3d_openCellOld");
405 
406  G3d_printHeader(map);
407 
408  map2 = G3d_openCellOld(f2, mapset2, G3D_DEFAULT_WINDOW,
409  G3D_TILE_SAME_AS_FILE, G3D_USE_CACHE_DEFAULT);
410  if (map2 == NULL)
411  G3d_fatalError("G3d_compareFiles: error in G3d_openCellOld");
412 
413  G3d_printHeader(map2);
414 
415  typeIntern = G3d_tileTypeMap(map);
416  typeIntern2 = G3d_tileTypeMap(map2);
417 
418  p1 = G3d_tilePrecisionMap(map);
419  p2 = G3d_tilePrecisionMap(map2);
420 
421  G3d_getTileDimensionsMap(map, &tileX, &tileY, &tileZ);
422  G3d_getTileDimensionsMap(map2, &tileX2, &tileY2, &tileZ2);
423  G3d_getNofTilesMap(map2, &nx, &ny, &nz);
424  G3d_getCoordsMap(map, &rows, &cols, &depths);
425 
426  if ((!G3d_tileUseCacheMap(map)) || (!G3d_tileUseCacheMap(map2))) {
427  compareFilesNocache(map, map2);
428  G3d_closeCell(map);
429  G3d_closeCell(map2);
430  return;
431  }
432 
433  n1p = &n1;
434  f1p = (float *)&n1;
435  n2p = &n2;
436  f2p = (float *)&n2;
437 
438  G3d_autolockOn(map);
439  G3d_autolockOn(map2);
440  G3d_minUnlocked(map, cols / tileX + 1);
441 
442  G3d_getCoordsMap(map2, &rows, &cols, &depths);
443  G3d_minUnlocked(map2, cols / tileX + 1);
444 
445  G3d_getCoordsMap(map, &rows, &cols, &depths);
446  for (z = 0; z < depths; z++) {
447  printf("comparing: z = %d\n", z);
448 
449  if ((z % tileZ) == 0) {
450  if (!G3d_unlockAll(map))
451  G3d_fatalError("G3d_compareFiles: error in G3d_unlockAll");
452  }
453  if ((z % tileZ2) == 0) {
454  if (!G3d_unlockAll(map2))
455  G3d_fatalError("G3d_compareFiles: error in G3d_unlockAll");
456  }
457 
458  for (y = 0; y < rows; y++) {
459  for (x = 0; x < cols; x++) {
460  G3d_getValueRegion(map, x, y, z, n1p, typeIntern);
461  G3d_getValueRegion(map2, x, y, z, n2p, typeIntern2);
462 
463  G3d_isNullValueNum(n1p, typeIntern);
464  G3d_isNullValueNum(n2p, typeIntern2);
465 
466  if (typeIntern == FCELL_TYPE) {
467  if (typeIntern2 == FCELL_TYPE)
468  correct = G3d_compareFloats(f1p, p1, f2p, p2);
469  else
470  correct = G3d_compareFloatDouble(f1p, p1, n2p, p2);
471  }
472  else {
473  if (typeIntern2 == FCELL_TYPE)
474  correct = G3d_compareFloatDouble(f2p, p2, n1p, p1);
475  else
476  correct = G3d_compareDoubles(n1p, p1, n2p, p2);
477  }
478 
479  if (!correct) {
480  int xTile, yTile, zTile, xOffs, yOffs, zOffs;
481 
482  G3d_coord2tileCoord(map2, x, y, z, &xTile, &yTile, &zTile,
483  &xOffs, &yOffs, &zOffs);
484  G3d_fatalError("G3d_compareFiles: files don't match\n");
485  }
486  }
487  }
488  }
489 
490  printf("Files are identical up to precision.\n");
491  G3d_closeCell(map);
492  G3d_closeCell(map2);
493 }
XDR xdrEncodeStream
Definition: g3dfpxdr.c:62
#define NULL
Definition: strings.c:26
void G3d_getValueRegion(G3D_Map *map, int x, int y, int z, void *value, int type)
Returns in *value the cell-value of the cell with region-coordinate (x, y, z). The value returned is ...
Definition: tileio.c:244
void G3d_printHeader(G3D_Map *map)
Prints the header information of map.
Definition: headerinfo.c:228
void G3d_getTileDimensionsMap(G3D_Map *map, int *x, int *y, int *z)
Returns the tile dimensions used for map.
Definition: headerinfo.c:142
int G3d_isNullValueNum(const void *n, int type)
Definition: g3dnull.c:9
int y
Definition: plot.c:34
void G3d_getNofTilesMap(G3D_Map *map, int *nx, int *ny, int *nz)
Returns the dimensions of the tile-cube used to tile the region of map. These numbers include partial...
Definition: headerinfo.c:51
void G3d_compareFiles(const char *f1, const char *mapset1, const char *f2, const char *mapset2)
Compares the cell-values of file f1 in mapset mapset1 and file f2 in mapset mapset2. The values are compared up to precision. Terminates in error if the files don't match. This function uses the more advanced features of the cache. The source code can be found in filecompare.c.
Definition: filecompare.c:386
int G3d_tileUseCacheMap(G3D_Map *map)
Returns 1 if map uses cache, returns 0 otherwise.
Definition: headerinfo.c:212
int G3d_closeCell(G3D_Map *map)
Closes g3d-file. If map is new and cache-mode is used for map then every tile which is not flushed be...
Definition: g3dclose.c:144
int G3d_unlockAll(G3D_Map *map)
Unlocks every tile in cache of map.
Definition: tileread.c:312
int G3d_tilePrecisionMap(G3D_Map *map)
Returns the precision used to store map.
Definition: headerinfo.c:195
void * G3d_openCellOld(const char *name, const char *mapset, G3D_Region *window, int typeIntern, int cache)
Opens existing g3d-file name in mapset. Tiles are stored in memory with type which must be any of FCE...
Definition: g3dopen.c:85
tuple cols
void G3d_minUnlocked(G3D_Map *map, int minUnlocked)
Sets the minimum number of unlocked tiles to minUnlocked. This function should be used in combination...
Definition: tileread.c:386
dglInt32_t sign(dglInt32_t x)
Definition: flow.c:25
void G3d_coord2tileCoord(G3D_Map *map, int x, int y, int z, int *xTile, int *yTile, int *zTile, int *xOffs, int *yOffs, int *zOffs)
Converts cell-coordinates (x, y, z) into tile-coordinates (xTile, yTile, zTile) and the coordinate of...
Definition: tilemath.c:136
void G3d_autolockOn(G3D_Map *map)
Turns autolock mode on.
Definition: tileread.c:337
void G3d_getBlock(G3D_Map *map, int x0, int y0, int z0, int nx, int ny, int nz, void *block, int type)
Copies the cells contained in the block (cube) with vertices (x0, y0, z0) and (x0 + nx - 1...
Definition: getblock.c:103
int G3d_tileTypeMap(G3D_Map *map)
Returns the type in which tiles of map are stored in memory.
Definition: headerinfo.c:161
void G3d_fatalError(const char *,...)
This function prints the error message msg, and terminates the program with an error status...
Definition: g3derror.c:58
void G3d_getCoordsMap(G3D_Map *map, int *rows, int *cols, int *depths)
Returns the size of the region of map in cells.
Definition: headerinfo.c:19